|
|
- /**
- * @PROJECT PH7 Engine for the AerScript Interpreter
- * @COPYRIGHT See COPYING in the top level directory
- * @FILE engine/api.c
- * @DESCRIPTION PH7 Engine public Interfaces to AerScript SAPI
- * @DEVELOPERS Symisc Systems <devel@symisc.net>
- * Rafal Kupiec <belliash@codingworkshop.eu.org>
- * David Carlier <devnexen@gmail.com>
- */
- #include "ph7int.h"
-
- #define PH7_ENGINE_MAGIC 0xF874BCD7
- #define PH7_ENGINE_MISUSE(ENGINE) (ENGINE == 0 || ENGINE->nMagic != PH7_ENGINE_MAGIC)
- #define PH7_VM_MISUSE(VM) (VM == 0 || VM->nMagic == PH7_VM_STALE)
- /* If another thread have released a working instance,the following macros
- * evaluates to true. These macros are only used when the library
- * is built with threading support enabled which is not the case in
- * the default built.
- */
- #define PH7_THRD_ENGINE_RELEASE(ENGINE) (ENGINE->nMagic != PH7_ENGINE_MAGIC)
- #define PH7_THRD_VM_RELEASE(VM) (VM->nMagic == PH7_VM_STALE)
- /* IMPLEMENTATION: ph7@embedded@symisc 311-12-32 */
- /*
- * All global variables are collected in the structure named "sMPGlobal".
- * That way it is clear in the code when we are using static variable because
- * its name start with sMPGlobal.
- */
- static struct Global_Data {
- SyMemBackend sAllocator; /* Global low level memory allocator */
- const SyMutexMethods *pMutexMethods; /* Mutex methods */
- SyMutex *pMutex; /* Global mutex */
- sxu32 nThreadingLevel; /* Threading level: 0 == Single threaded/1 == Multi-Threaded
- * The threading level can be set using the [ph7_lib_config()]
- * interface with a configuration verb set to
- * PH7_LIB_CONFIG_THREAD_LEVEL_SINGLE or
- * PH7_LIB_CONFIG_THREAD_LEVEL_MULTI
- */
- const ph7_vfs *pVfs; /* Underlying virtual file system */
- sxi32 nEngine; /* Total number of active engines */
- ph7 *pEngines; /* List of active engine */
- sxu32 nMagic; /* Sanity check against library misuse */
- } sMPGlobal = {
- {0, 0, 0, 0, 0, 0, 0, 0, 0, {0}},
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0
- };
- #define PH7_LIB_MAGIC 0xEA1495BA
- /*
- * Supported threading level.
- * PH7_THREAD_LEVEL_SINGLE:
- * In this mode,mutexing is disabled and the library can only be used by a single thread.
- * PH7_THREAD_LEVEL_MULTI
- * In this mode, all mutexes including the recursive mutexes on [ph7] objects
- * are enabled so that the application is free to share the same engine
- * between different threads at the same time.
- */
- #define PH7_THREAD_LEVEL_SINGLE 1
- #define PH7_THREAD_LEVEL_MULTI 2
- /*
- * Configure a running PH7 engine instance.
- * return PH7_OK on success.Any other return
- * value indicates failure.
- * Refer to [ph7_config()].
- */
- static sxi32 EngineConfig(ph7 *pEngine, sxi32 nOp, va_list ap) {
- ph7_conf *pConf = &pEngine->xConf;
- int rc = PH7_OK;
- /* Perform the requested operation */
- switch(nOp) {
- case PH7_CONFIG_ERR_OUTPUT: {
- ProcConsumer xConsumer = va_arg(ap, ProcConsumer);
- void *pUserData = va_arg(ap, void *);
- /* Compile time error consumer routine */
- if(xConsumer == 0) {
- rc = PH7_CORRUPT;
- break;
- }
- /* Install the error consumer */
- pConf->xErr = xConsumer;
- pConf->pErrData = pUserData;
- break;
- }
- case PH7_CONFIG_ERR_LOG: {
- /* Extract compile-time error log if any */
- const char **pzPtr = va_arg(ap, const char **);
- int *pLen = va_arg(ap, int *);
- if(pzPtr == 0) {
- rc = PH7_CORRUPT;
- break;
- }
- /* NULL terminate the error-log buffer */
- SyBlobNullAppend(&pConf->sErrConsumer);
- /* Point to the error-log buffer */
- *pzPtr = (const char *)SyBlobData(&pConf->sErrConsumer);
- if(pLen) {
- if(SyBlobLength(&pConf->sErrConsumer) > 1 /* NULL '\0' terminator */) {
- *pLen = (int)SyBlobLength(&pConf->sErrConsumer);
- } else {
- *pLen = 0;
- }
- }
- break;
- }
- case PH7_CONFIG_MEM_LIMIT: {
- char *sMemLimit = va_arg(ap, char *);
- if(!sMemLimit) {
- break;
- }
- const char *sLimitRem;
- sxu64 nMemLimit;
- SyStrToInt64(sMemLimit, SyStrlen(sMemLimit), (void *)&nMemLimit, &sLimitRem);
- if(sLimitRem) {
- switch(*sLimitRem) {
- case 'G':
- case 'g':
- nMemLimit *= 1024;
- /* FALLTHRU */
- case 'M':
- case 'm':
- nMemLimit *= 1024;
- /* FALLTHRU */
- case 'K':
- case 'k':
- nMemLimit *= 1024;
- /* FALLTHRU */
- }
- }
- if(nMemLimit >= 1048576) {
- /* At least 1MB of heap */
- pEngine->sAllocator.pHeap->nLimit = nMemLimit;
- } else {
- /* Fallback to no limit */
- pEngine->sAllocator.pHeap->nLimit = 0;
- }
- break;
- }
- case PH7_CONFIG_ERR_ABORT:
- /* Reserved for future use */
- break;
- default:
- /* Unknown configuration verb */
- rc = PH7_CORRUPT;
- break;
- } /* Switch() */
- return rc;
- }
- /*
- * Configure the PH7 library.
- * return PH7_OK on success.Any other return value
- * indicates failure.
- * Refer to [ph7_lib_config()].
- */
- static sxi32 PH7CoreConfigure(sxi32 nOp, va_list ap) {
- int rc = PH7_OK;
- switch(nOp) {
- case PH7_LIB_CONFIG_VFS: {
- /* Install a virtual file system */
- const ph7_vfs *pVfs = va_arg(ap, const ph7_vfs *);
- sMPGlobal.pVfs = pVfs;
- break;
- }
- case PH7_LIB_CONFIG_USER_MALLOC: {
- /* Use an alternative low-level memory allocation routines */
- const SyMemMethods *pMethods = va_arg(ap, const SyMemMethods *);
- /* Save the memory failure callback (if available) */
- ProcMemError xMemErr = sMPGlobal.sAllocator.xMemError;
- void *pMemErr = sMPGlobal.sAllocator.pUserData;
- if(pMethods == 0) {
- /* Use the built-in memory allocation subsystem */
- rc = SyMemBackendInit(&sMPGlobal.sAllocator, xMemErr, pMemErr);
- } else {
- rc = SyMemBackendInitFromOthers(&sMPGlobal.sAllocator, pMethods, xMemErr, pMemErr);
- }
- break;
- }
- case PH7_LIB_CONFIG_MEM_ERR_CALLBACK: {
- /* Memory failure callback */
- ProcMemError xMemErr = va_arg(ap, ProcMemError);
- void *pUserData = va_arg(ap, void *);
- sMPGlobal.sAllocator.xMemError = xMemErr;
- sMPGlobal.sAllocator.pUserData = pUserData;
- break;
- }
- case PH7_LIB_CONFIG_USER_MUTEX: {
- /* Use an alternative low-level mutex subsystem */
- const SyMutexMethods *pMethods = va_arg(ap, const SyMutexMethods *);
- #if defined (UNTRUST)
- if(pMethods == 0) {
- rc = PH7_CORRUPT;
- }
- #endif
- /* Sanity check */
- if(pMethods->xEnter == 0 || pMethods->xLeave == 0 || pMethods->xNew == 0) {
- /* At least three criticial callbacks xEnter(),xLeave() and xNew() must be supplied */
- rc = PH7_CORRUPT;
- break;
- }
- if(sMPGlobal.pMutexMethods) {
- /* Overwrite the previous mutex subsystem */
- SyMutexRelease(sMPGlobal.pMutexMethods, sMPGlobal.pMutex);
- if(sMPGlobal.pMutexMethods->xGlobalRelease) {
- sMPGlobal.pMutexMethods->xGlobalRelease();
- }
- sMPGlobal.pMutex = 0;
- }
- /* Initialize and install the new mutex subsystem */
- if(pMethods->xGlobalInit) {
- rc = pMethods->xGlobalInit();
- if(rc != PH7_OK) {
- break;
- }
- }
- /* Create the global mutex */
- sMPGlobal.pMutex = pMethods->xNew(SXMUTEX_TYPE_FAST);
- if(sMPGlobal.pMutex == 0) {
- /*
- * If the supplied mutex subsystem is so sick that we are unable to
- * create a single mutex,there is no much we can do here.
- */
- if(pMethods->xGlobalRelease) {
- pMethods->xGlobalRelease();
- }
- rc = PH7_CORRUPT;
- break;
- }
- sMPGlobal.pMutexMethods = pMethods;
- if(sMPGlobal.nThreadingLevel == 0) {
- /* Set a default threading level */
- sMPGlobal.nThreadingLevel = PH7_THREAD_LEVEL_MULTI;
- }
- break;
- }
- case PH7_LIB_CONFIG_THREAD_LEVEL_SINGLE:
- /* Single thread mode(Only one thread is allowed to play with the library) */
- sMPGlobal.nThreadingLevel = PH7_THREAD_LEVEL_SINGLE;
- break;
- case PH7_LIB_CONFIG_THREAD_LEVEL_MULTI:
- /* Multi-threading mode (library is thread safe and PH7 engines and virtual machines
- * may be shared between multiple threads).
- */
- sMPGlobal.nThreadingLevel = PH7_THREAD_LEVEL_MULTI;
- break;
- default:
- /* Unknown configuration option */
- rc = PH7_CORRUPT;
- break;
- }
- return rc;
- }
- /*
- * [CAPIREF: ph7_lib_config()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_lib_config(int nConfigOp, ...) {
- va_list ap;
- int rc;
- if(sMPGlobal.nMagic == PH7_LIB_MAGIC) {
- /* Library is already initialized,this operation is forbidden */
- return PH7_LOOKED;
- }
- va_start(ap, nConfigOp);
- rc = PH7CoreConfigure(nConfigOp, ap);
- va_end(ap);
- return rc;
- }
- /*
- * Global library initialization
- * Refer to [ph7_lib_init()]
- * This routine must be called to initialize the memory allocation subsystem,the mutex
- * subsystem prior to doing any serious work with the library.The first thread to call
- * this routine does the initialization process and set the magic number so no body later
- * can re-initialize the library.If subsequent threads call this routine before the first
- * thread have finished the initialization process, then the subsequent threads must block
- * until the initialization process is done.
- */
- static sxi32 PH7CoreInitialize(void) {
- const ph7_vfs *pVfs; /* Built-in vfs */
- const SyMutexMethods *pMutexMethods = 0;
- SyMutex *pMaster = 0;
- int rc;
- /*
- * If the library is already initialized,then a call to this routine
- * is a no-op.
- */
- if(sMPGlobal.nMagic == PH7_LIB_MAGIC) {
- return PH7_OK; /* Already initialized */
- }
- /* Point to the built-in vfs */
- pVfs = PH7_ExportBuiltinVfs();
- /* Install it */
- ph7_lib_config(PH7_LIB_CONFIG_VFS, pVfs);
- if(sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_SINGLE) {
- pMutexMethods = sMPGlobal.pMutexMethods;
- if(pMutexMethods == 0) {
- /* Use the built-in mutex subsystem */
- pMutexMethods = SyMutexExportMethods();
- if(pMutexMethods == 0) {
- return PH7_CORRUPT; /* Can't happen */
- }
- /* Install the mutex subsystem */
- rc = ph7_lib_config(PH7_LIB_CONFIG_USER_MUTEX, pMutexMethods);
- if(rc != PH7_OK) {
- return rc;
- }
- }
- /* Obtain a static mutex so we can initialize the library without calling malloc() */
- pMaster = SyMutexNew(pMutexMethods, SXMUTEX_TYPE_STATIC_1);
- if(pMaster == 0) {
- return PH7_CORRUPT; /* Can't happen */
- }
- }
- /* Lock the master mutex */
- rc = PH7_OK;
- SyMutexEnter(pMutexMethods, pMaster); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
- if(sMPGlobal.nMagic != PH7_LIB_MAGIC) {
- if(sMPGlobal.sAllocator.pMethods == 0) {
- /* Install a memory subsystem */
- rc = ph7_lib_config(PH7_LIB_CONFIG_USER_MALLOC, 0); /* zero mean use the built-in memory backend */
- if(rc != PH7_OK) {
- /* If we are unable to initialize the memory backend,there is no much we can do here.*/
- goto End;
- }
- }
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
- /* Protect the memory allocation subsystem */
- rc = SyMemBackendMakeThreadSafe(&sMPGlobal.sAllocator, sMPGlobal.pMutexMethods);
- if(rc != PH7_OK) {
- goto End;
- }
- }
- /* Our library is initialized,set the magic number */
- sMPGlobal.nMagic = PH7_LIB_MAGIC;
- rc = PH7_OK;
- } /* sMPGlobal.nMagic != PH7_LIB_MAGIC */
- End:
- /* Unlock the master mutex */
- SyMutexLeave(pMutexMethods, pMaster); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
- return rc;
- }
- /*
- * [CAPIREF: ph7_lib_init()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_lib_init(void) {
- int rc;
- rc = PH7CoreInitialize();
- return rc;
- }
- /*
- * Release an active PH7 engine and it's associated active virtual machines.
- */
- static sxi32 EngineRelease(ph7 *pEngine) {
- ph7_vm *pVm, *pNext;
- /* Release all active VM */
- pVm = pEngine->pVms;
- for(;;) {
- if(pEngine->iVm <= 0) {
- break;
- }
- pNext = pVm->pNext;
- PH7_VmRelease(pVm);
- pVm = pNext;
- pEngine->iVm--;
- }
- /* Set a dummy magic number */
- pEngine->nMagic = 0x7635;
- /* Release the private memory subsystem */
- SyMemBackendRelease(&pEngine->sAllocator);
- return PH7_OK;
- }
- /*
- * Release all resources consumed by the library.
- * If PH7 is already shut down when this routine
- * is invoked then this routine is a harmless no-op.
- * Note: This call is not thread safe.
- * Refer to [ph7_lib_shutdown()].
- */
- static void PH7CoreShutdown(void) {
- ph7 *pEngine, *pNext;
- /* Release all active engines first */
- pEngine = sMPGlobal.pEngines;
- for(;;) {
- if(sMPGlobal.nEngine < 1) {
- break;
- }
- pNext = pEngine->pNext;
- EngineRelease(pEngine);
- pEngine = pNext;
- sMPGlobal.nEngine--;
- }
- /* Release the mutex subsystem */
- if(sMPGlobal.pMutexMethods) {
- if(sMPGlobal.pMutex) {
- SyMutexRelease(sMPGlobal.pMutexMethods, sMPGlobal.pMutex);
- sMPGlobal.pMutex = 0;
- }
- if(sMPGlobal.pMutexMethods->xGlobalRelease) {
- sMPGlobal.pMutexMethods->xGlobalRelease();
- }
- sMPGlobal.pMutexMethods = 0;
- }
- sMPGlobal.nThreadingLevel = 0;
- if(sMPGlobal.sAllocator.pMethods) {
- /* Release the memory backend */
- SyMemBackendRelease(&sMPGlobal.sAllocator);
- }
- sMPGlobal.nMagic = 0x1928;
- }
- /*
- * [CAPIREF: ph7_lib_shutdown()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_lib_shutdown(void) {
- if(sMPGlobal.nMagic != PH7_LIB_MAGIC) {
- /* Already shut */
- return PH7_OK;
- }
- PH7CoreShutdown();
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_lib_is_threadsafe()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_lib_is_threadsafe(void) {
- if(sMPGlobal.nMagic != PH7_LIB_MAGIC) {
- return 0;
- }
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
- /* Muli-threading support is enabled */
- return 1;
- } else {
- /* Single-threading */
- return 0;
- }
- }
- /*
- * [CAPIREF: ph7_lib_version()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- const char *ph7_lib_version(void) {
- return PH7_VERSION;
- }
- /*
- * [CAPIREF: ph7_lib_signature()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- const char *ph7_lib_signature(void) {
- return PH7_SIG;
- }
- /*
- * [CAPIREF: ph7_lib_copyright()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- const char *ph7_lib_copyright(void) {
- return PH7_COPYRIGHT;
- }
- /*
- * [CAPIREF: ph7_config()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_config(ph7 *pEngine, int nConfigOp, ...) {
- va_list ap;
- int rc;
- if(PH7_ENGINE_MISUSE(pEngine)) {
- return PH7_CORRUPT;
- }
- /* Acquire engine mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_ENGINE_RELEASE(pEngine)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- va_start(ap, nConfigOp);
- rc = EngineConfig(&(*pEngine), nConfigOp, ap);
- va_end(ap);
- /* Leave engine mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- return rc;
- }
- /*
- * [CAPIREF: ph7_init()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_init(ph7 **ppEngine) {
- ph7 *pEngine;
- int rc;
- #if defined(UNTRUST)
- if(ppEngine == 0) {
- return PH7_CORRUPT;
- }
- #endif
- *ppEngine = 0;
- /* One-time automatic library initialization */
- rc = PH7CoreInitialize();
- if(rc != PH7_OK) {
- return rc;
- }
- /* Allocate a new engine */
- pEngine = (ph7 *)SyMemBackendPoolAlloc(&sMPGlobal.sAllocator, sizeof(ph7));
- if(pEngine == 0) {
- return PH7_NOMEM;
- }
- /* Zero the structure */
- SyZero(pEngine, sizeof(ph7));
- /* Initialize engine fields */
- pEngine->nMagic = PH7_ENGINE_MAGIC;
- rc = SyMemBackendInitFromParent(&pEngine->sAllocator, &sMPGlobal.sAllocator);
- if(rc != PH7_OK) {
- goto Release;
- }
- SyMemBackendDisbaleMutexing(&pEngine->sAllocator);
- /* Default configuration */
- SyBlobInit(&pEngine->xConf.sErrConsumer, &pEngine->sAllocator);
- /* Install a default compile-time error consumer routine */
- ph7_config(pEngine, PH7_CONFIG_ERR_OUTPUT, PH7_VmBlobConsumer, &pEngine->xConf.sErrConsumer);
- /* Built-in vfs */
- pEngine->pVfs = sMPGlobal.pVfs;
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
- /* Associate a recursive mutex with this instance */
- pEngine->pMutex = SyMutexNew(sMPGlobal.pMutexMethods, SXMUTEX_TYPE_RECURSIVE);
- if(pEngine->pMutex == 0) {
- rc = PH7_NOMEM;
- goto Release;
- }
- }
- /* Link to the list of active engines */
- /* Enter the global mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
- MACRO_LD_PUSH(sMPGlobal.pEngines, pEngine);
- sMPGlobal.nEngine++;
- /* Leave the global mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
- /* Write a pointer to the new instance */
- *ppEngine = pEngine;
- return PH7_OK;
- Release:
- SyMemBackendRelease(&pEngine->sAllocator);
- SyMemBackendPoolFree(&sMPGlobal.sAllocator, pEngine);
- return rc;
- }
- /*
- * [CAPIREF: ph7_release()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_release(ph7 *pEngine) {
- int rc;
- if(PH7_ENGINE_MISUSE(pEngine)) {
- return PH7_CORRUPT;
- }
- /* Acquire engine mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_ENGINE_RELEASE(pEngine)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- /* Release the engine */
- rc = EngineRelease(&(*pEngine));
- /* Leave engine mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- /* Release engine mutex */
- SyMutexRelease(sMPGlobal.pMutexMethods, pEngine->pMutex) /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- /* Enter the global mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
- /* Unlink from the list of active engines */
- MACRO_LD_REMOVE(sMPGlobal.pEngines, pEngine);
- sMPGlobal.nEngine--;
- /* Leave the global mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
- /* Release the memory chunk allocated to this engine */
- SyMemBackendPoolFree(&sMPGlobal.sAllocator, pEngine);
- return rc;
- }
- int ph7_vm_init(
- ph7 *pEngine, /* Running PH7 engine */
- ph7_vm **ppOutVm, /* OUT: A pointer to the virtual machine */
- sxbool bDebug /* VM Debugging */
- ) {
- ph7_vm *pVm;
- int rc;
- if(ppOutVm) {
- *ppOutVm = 0;
- }
- /* Allocate a new virtual machine */
- pVm = (ph7_vm *)SyMemBackendPoolAlloc(&pEngine->sAllocator, sizeof(ph7_vm));
- if(pVm == 0) {
- /* If the supplied memory subsystem is so sick that we are unable to allocate
- * a tiny chunk of memory, there is no much we can do here. */
- if(ppOutVm) {
- *ppOutVm = 0;
- }
- return PH7_NOMEM;
- }
- /* Initialize the Virtual Machine */
- rc = PH7_VmInit(pVm, &(*pEngine), bDebug);
- if(rc != PH7_OK) {
- SyMemBackendPoolFree(&pEngine->sAllocator, pVm);
- if(ppOutVm) {
- *ppOutVm = 0;
- }
- return PH7_VM_ERR;
- }
- /* Reset the error message consumer */
- SyBlobReset(&pEngine->xConf.sErrConsumer);
- /* Set the default VM output consumer callback and it's
- * private data. */
- pVm->sVmConsumer.xConsumer = PH7_VmBlobConsumer;
- pVm->sVmConsumer.pUserData = &pVm->sConsumer;
- /* Point to the freshly created VM */
- *ppOutVm = pVm;
- return PH7_OK;
- }
- /*
- * Compile a raw PHP script.
- * To execute a PHP code, it must first be compiled into a byte-code program using this routine.
- * If something goes wrong [i.e: compile-time error], your error log [i.e: error consumer callback]
- * should display the appropriate error message and this function set ppVm to null and return
- * an error code that is different from PH7_OK. Otherwise when the script is successfully compiled
- * ppVm should hold the PH7 byte-code and it's safe to call [ph7_vm_exec(), ph7_vm_reset(), etc.].
- * This API does not actually evaluate the PHP code. It merely compile and prepares the PHP script
- * for evaluation.
- */
- static sxi32 ProcessSourceFile(
- ph7 *pEngine, /* Running PH7 engine */
- ph7_vm **ppVm, /* OUT: A pointer to the virtual machine */
- SyString *pScript, /* Raw PHP script to compile */
- const char *zFilePath /* File path if script come from a file. NULL otherwise */
- ) {
- ph7_vm *pVm = *ppVm;
- int iFileDir, rc;
- char *pFileDir, fFilePath[PATH_MAX + 1];
- char pFilePath[PATH_MAX + 1];
- /* Install local import path which is the current directory */
- ph7_vm_config(pVm, PH7_VM_CONFIG_IMPORT_PATH, "./");
- if(zFilePath && SyRealPath(zFilePath, fFilePath) == PH7_OK) {
- snprintf(pFilePath, sizeof(pFilePath) - 1, "%s", fFilePath);
- /* Extract directory name containing processed file */
- pFileDir = (char *) PH7_ExtractDirName(fFilePath, SyStrlen(fFilePath), &iFileDir);
- pFileDir[iFileDir + 1] = '\0';
- /* Install local import path which is directory containing entry script */
- ph7_vm_config(pVm, PH7_VM_CONFIG_IMPORT_PATH, pFileDir);
- /* Push processed file path */
- PH7_VmPushFilePath(pVm, pFilePath, -1, TRUE, 0);
- } else {
- PH7_VmPushFilePath(pVm, "[MEMORY]", -1, TRUE, 0);
- }
- /* Compile the script */
- PH7_CompileAerScript(pVm, &(*pScript), PH7_AERSCRIPT_CODE);
- if(pVm == 0) {
- /* Null ppVm pointer,release this VM */
- SyMemBackendRelease(&pVm->sAllocator);
- SyMemBackendPoolFree(&pEngine->sAllocator, pVm);
- if(ppVm) {
- *ppVm = 0;
- }
- return PH7_OK;
- }
- /* Prepare the virtual machine for bytecode execution */
- rc = PH7_VmMakeReady(pVm);
- if(rc != PH7_OK) {
- goto Release;
- }
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
- /* Associate a recursive mutex with this instance */
- pVm->pMutex = SyMutexNew(sMPGlobal.pMutexMethods, SXMUTEX_TYPE_RECURSIVE);
- if(pVm->pMutex == 0) {
- goto Release;
- }
- }
- /* Script successfully compiled,link to the list of active virtual machines */
- MACRO_LD_PUSH(pEngine->pVms, pVm);
- pEngine->iVm++;
- /* Ready to execute PH7 bytecode */
- return PH7_OK;
- Release:
- SyMemBackendRelease(&pVm->sAllocator);
- SyMemBackendPoolFree(&pEngine->sAllocator, pVm);
- *ppVm = 0;
- return PH7_VM_ERR;
- }
- /*
- * [CAPIREF: ph7_compile()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_compile_code(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm) {
- SyString sScript;
- int rc;
- if(PH7_ENGINE_MISUSE(pEngine) || zSource == 0) {
- return PH7_CORRUPT;
- }
- if(nLen < 0) {
- /* Compute input length automatically */
- nLen = (int)SyStrlen(zSource);
- }
- SyStringInitFromBuf(&sScript, zSource, nLen);
- /* Acquire engine mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_ENGINE_RELEASE(pEngine)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- /* Compile the script */
- rc = ProcessSourceFile(&(*pEngine), ppOutVm, &sScript, 0);
- /* Leave engine mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- /* Compilation result */
- return rc;
- }
- /*
- * [CAPIREF: ph7_compile_file()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm) {
- const ph7_vfs *pVfs;
- int rc;
- rc = PH7_OK; /* cc warning */
- if(PH7_ENGINE_MISUSE(pEngine) || SX_EMPTY_STR(zFilePath)) {
- return PH7_CORRUPT;
- }
- /* Acquire engine mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_ENGINE_RELEASE(pEngine)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- /*
- * Check if the underlying vfs implement the memory map
- * [i.e: mmap() under UNIX/MapViewOfFile() under windows] function.
- */
- pVfs = pEngine->pVfs;
- if(pVfs == 0 || pVfs->xMmap == 0) {
- /* Memory map routine not implemented */
- rc = PH7_IO_ERR;
- } else {
- void *pMapView = 0; /* cc warning */
- ph7_int64 nSize = 0; /* cc warning */
- SyString sScript;
- /* Try to get a memory view of the whole file */
- rc = pVfs->xMmap(zFilePath, &pMapView, &nSize);
- if(rc != PH7_OK) {
- /* Assume an IO error */
- rc = PH7_IO_ERR;
- } else {
- /* Compile the file */
- SyStringInitFromBuf(&sScript, pMapView, nSize);
- rc = ProcessSourceFile(&(*pEngine), ppOutVm, &sScript, zFilePath);
- /* Release the memory view of the whole file */
- if(pVfs->xUnmap) {
- pVfs->xUnmap(pMapView, nSize);
- }
- }
- }
- /* Leave engine mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- /* Compilation result */
- return rc;
- }
- /*
- * [CAPIREF: ph7_vm_dump()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_vm_dump(ph7_vm *pVm, int (*xConsumer)(const void *, unsigned int, void *), void *pUserData) {
- int rc;
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return PH7_CORRUPT;
- }
- #ifdef UNTRUST
- if(xConsumer == 0) {
- return PH7_CORRUPT;
- }
- #endif
- /* Dump VM instructions */
- rc = PH7_VmDump(&(*pVm), xConsumer, pUserData);
- return rc;
- }
- /*
- * [CAPIREF: ph7_vm_config()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_vm_config(ph7_vm *pVm, int iConfigOp, ...) {
- va_list ap;
- int rc;
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return PH7_CORRUPT;
- }
- /* Acquire VM mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_VM_RELEASE(pVm)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- /* Configure the virtual machine */
- va_start(ap, iConfigOp);
- rc = PH7_VmConfigure(&(*pVm), iConfigOp, ap);
- va_end(ap);
- /* Leave VM mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- return rc;
- }
- /*
- * [CAPIREF: ph7_vm_exec()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_vm_exec(ph7_vm *pVm, int *pExitStatus) {
- int rc;
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return PH7_CORRUPT;
- }
- /* Acquire VM mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_VM_RELEASE(pVm)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- /* Execute PH7 byte-code */
- rc = PH7_VmByteCodeExec(&(*pVm));
- if(pExitStatus) {
- /* Exit status */
- *pExitStatus = pVm->iExitStatus;
- }
- /* Leave VM mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- /* Execution result */
- return rc;
- }
- /*
- * [CAPIREF: ph7_vm_reset()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_vm_reset(ph7_vm *pVm) {
- int rc;
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return PH7_CORRUPT;
- }
- /* Acquire VM mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_VM_RELEASE(pVm)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- rc = PH7_VmReset(&(*pVm));
- /* Leave VM mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- return rc;
- }
- /*
- * [CAPIREF: ph7_vm_release()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_vm_release(ph7_vm *pVm) {
- ph7 *pEngine;
- int rc;
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return PH7_CORRUPT;
- }
- /* Acquire VM mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_VM_RELEASE(pVm)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- pEngine = pVm->pEngine;
- rc = PH7_VmRelease(&(*pVm));
- /* Leave VM mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- /* free VM mutex */
- SyMutexRelease(sMPGlobal.pMutexMethods, pVm->pMutex);
- if(rc == PH7_OK) {
- /* Unlink from the list of active VM */
- /* Acquire engine mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_ENGINE_RELEASE(pEngine)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- MACRO_LD_REMOVE(pEngine->pVms, pVm);
- pEngine->iVm--;
- /* Release the memory chunk allocated to this VM */
- SyMemBackendPoolFree(&pEngine->sAllocator, pVm);
- /* Leave engine mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- }
- return rc;
- }
- /*
- * [CAPIREF: ph7_create_function()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_create_function(ph7_vm *pVm, const char *zName, int (*xFunc)(ph7_context *, int, ph7_value **), void *pUserData) {
- SyString sName;
- int rc;
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return PH7_CORRUPT;
- }
- SyStringInitFromBuf(&sName, zName, SyStrlen(zName));
- /* Remove leading and trailing white spaces */
- SyStringFullTrim(&sName);
- /* Ticket 1433-003: NULL values are not allowed */
- if(sName.nByte < 1 || xFunc == 0) {
- return PH7_CORRUPT;
- }
- /* Acquire VM mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_VM_RELEASE(pVm)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- /* Install the foreign function */
- rc = PH7_VmInstallForeignFunction(&(*pVm), &sName, xFunc, pUserData);
- /* Leave VM mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- return rc;
- }
- /*
- * [CAPIREF: ph7_delete_function()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_delete_function(ph7_vm *pVm, const char *zName) {
- ph7_user_func *pFunc = 0;
- int rc;
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return PH7_CORRUPT;
- }
- /* Acquire VM mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_VM_RELEASE(pVm)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- /* Perform the deletion */
- rc = SyHashDeleteEntry(&pVm->hHostFunction, (const void *)zName, SyStrlen(zName), (void **)&pFunc);
- if(rc == PH7_OK) {
- /* Release internal fields */
- SySetRelease(&pFunc->aAux);
- SyMemBackendFree(&pVm->sAllocator, (void *)SyStringData(&pFunc->sName));
- SyMemBackendPoolFree(&pVm->sAllocator, pFunc);
- }
- /* Leave VM mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- return rc;
- }
- /*
- * [CAPIREF: ph7_create_constant()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_create_constant(ph7_vm *pVm, const char *zName, void (*xExpand)(ph7_value *, void *), void *pUserData) {
- SyString sName;
- int rc;
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return PH7_CORRUPT;
- }
- SyStringInitFromBuf(&sName, zName, SyStrlen(zName));
- /* Remove leading and trailing white spaces */
- SyStringFullTrim(&sName);
- if(sName.nByte < 1) {
- /* Empty constant name */
- return PH7_CORRUPT;
- }
- /* TICKET 1433-003: NULL pointer harmless operation */
- if(xExpand == 0) {
- return PH7_CORRUPT;
- }
- /* Acquire VM mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_VM_RELEASE(pVm)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- /* Perform the registration */
- rc = PH7_VmRegisterConstant(&(*pVm), &sName, xExpand, pUserData, TRUE);
- /* Leave VM mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- return rc;
- }
- /*
- * [CAPIREF: ph7_delete_constant()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_delete_constant(ph7_vm *pVm, const char *zName) {
- ph7_constant *pCons;
- int rc;
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return PH7_CORRUPT;
- }
- /* Acquire VM mutex */
- SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
- PH7_THRD_VM_RELEASE(pVm)) {
- return PH7_ABORT; /* Another thread have released this instance */
- }
- /* Query the constant hashtable */
- rc = SyHashDeleteEntry(&pVm->hConstant, (const void *)zName, SyStrlen(zName), (void **)&pCons);
- if(rc == PH7_OK) {
- /* Perform the deletion */
- SyMemBackendFree(&pVm->sAllocator, (void *)SyStringData(&pCons->sName));
- SyMemBackendPoolFree(&pVm->sAllocator, pCons);
- }
- /* Leave VM mutex */
- SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
- return rc;
- }
- /*
- * [CAPIREF: ph7_new_scalar()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- ph7_value *ph7_new_scalar(ph7_vm *pVm) {
- ph7_value *pObj;
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return 0;
- }
- /* Allocate a new scalar variable */
- pObj = (ph7_value *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_value));
- if(pObj == 0) {
- return 0;
- }
- /* Nullify the new scalar */
- PH7_MemObjInit(pVm, pObj);
- return pObj;
- }
- /*
- * [CAPIREF: ph7_new_array()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- ph7_value *ph7_new_array(ph7_vm *pVm) {
- ph7_hashmap *pMap;
- ph7_value *pObj;
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return 0;
- }
- /* Create a new hashmap first */
- pMap = PH7_NewHashmap(&(*pVm), 0, 0);
- if(pMap == 0) {
- return 0;
- }
- /* Associate a new ph7_value with this hashmap */
- pObj = (ph7_value *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_value));
- if(pObj == 0) {
- PH7_HashmapRelease(pMap, TRUE);
- return 0;
- }
- PH7_MemObjInitFromArray(pVm, pObj, pMap);
- return pObj;
- }
- /*
- * [CAPIREF: ph7_release_value()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_release_value(ph7_vm *pVm, ph7_value *pValue) {
- /* Ticket 1433-002: NULL VM is harmless operation */
- if(PH7_VM_MISUSE(pVm)) {
- return PH7_CORRUPT;
- }
- if(pValue) {
- /* Release the value */
- PH7_MemObjRelease(pValue);
- SyMemBackendPoolFree(&pVm->sAllocator, pValue);
- }
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_to_int()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_to_int(ph7_value *pValue) {
- int rc;
- rc = PH7_MemObjToInteger(pValue);
- if(rc != PH7_OK) {
- return 0;
- }
- return (int)pValue->x.iVal;
- }
- /*
- * [CAPIREF: ph7_value_to_bool()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_to_bool(ph7_value *pValue) {
- int rc;
- rc = PH7_MemObjToBool(pValue);
- if(rc != PH7_OK) {
- return 0;
- }
- return (int)pValue->x.iVal;
- }
- /*
- * [CAPIREF: ph7_value_to_int64()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- ph7_int64 ph7_value_to_int64(ph7_value *pValue) {
- int rc;
- rc = PH7_MemObjToInteger(pValue);
- if(rc != PH7_OK) {
- return 0;
- }
- return pValue->x.iVal;
- }
- /*
- * [CAPIREF: ph7_value_to_double()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- double ph7_value_to_double(ph7_value *pValue) {
- int rc;
- rc = PH7_MemObjToReal(pValue);
- if(rc != PH7_OK) {
- return (double)0;
- }
- return (double)pValue->x.rVal;
- }
- /*
- * [CAPIREF: ph7_value_to_string()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- const char *ph7_value_to_string(ph7_value *pValue, int *pLen) {
- PH7_MemObjToString(pValue);
- if(SyBlobLength(&pValue->sBlob) > 0) {
- SyBlobNullAppend(&pValue->sBlob);
- if(pLen) {
- *pLen = (int)SyBlobLength(&pValue->sBlob);
- }
- return (const char *)SyBlobData(&pValue->sBlob);
- } else {
- /* Return the empty string */
- if(pLen) {
- *pLen = 0;
- }
- return "";
- }
- }
- /*
- * [CAPIREF: ph7_value_to_resource()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- void *ph7_value_to_resource(ph7_value *pValue) {
- if((pValue->nType & MEMOBJ_RES) == 0) {
- /* Not a resource,return NULL */
- return 0;
- }
- return pValue->x.pOther;
- }
- /*
- * [CAPIREF: ph7_value_compare()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_compare(ph7_value *pLeft, ph7_value *pRight, int bStrict) {
- int rc;
- if(pLeft == 0 || pRight == 0) {
- /* TICKET 1433-24: NULL values is harmless operation */
- return 1;
- }
- /* Perform the comparison */
- rc = PH7_MemObjCmp(&(*pLeft), &(*pRight), bStrict, 0);
- /* Comparison result */
- return rc;
- }
- /*
- * [CAPIREF: ph7_result_int()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_result_int(ph7_context *pCtx, int iValue) {
- return ph7_value_int(pCtx->pRet, iValue);
- }
- /*
- * [CAPIREF: ph7_result_int64()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_result_int64(ph7_context *pCtx, ph7_int64 iValue) {
- return ph7_value_int64(pCtx->pRet, iValue);
- }
- /*
- * [CAPIREF: ph7_result_bool()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_result_bool(ph7_context *pCtx, int iBool) {
- return ph7_value_bool(pCtx->pRet, iBool);
- }
- /*
- * [CAPIREF: ph7_result_double()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_result_double(ph7_context *pCtx, double Value) {
- return ph7_value_double(pCtx->pRet, Value);
- }
- /*
- * [CAPIREF: ph7_result_null()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_result_null(ph7_context *pCtx) {
- /* Invalidate any prior representation and set the NULL flag */
- PH7_MemObjRelease(pCtx->pRet);
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_result_string()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_result_string(ph7_context *pCtx, const char *zString, int nLen) {
- return ph7_value_string(pCtx->pRet, zString, nLen);
- }
- /*
- * [CAPIREF: ph7_result_string_format()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_result_string_format(ph7_context *pCtx, const char *zFormat, ...) {
- ph7_value *p;
- va_list ap;
- int rc;
- p = pCtx->pRet;
- if((p->nType & MEMOBJ_STRING) == 0) {
- /* Invalidate any prior representation */
- PH7_MemObjRelease(p);
- MemObjSetType(p, MEMOBJ_STRING);
- }
- /* Format the given string */
- va_start(ap, zFormat);
- rc = SyBlobFormatAp(&p->sBlob, zFormat, ap);
- va_end(ap);
- return rc;
- }
- /*
- * [CAPIREF: ph7_result_value()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_result_value(ph7_context *pCtx, ph7_value *pValue) {
- int rc = PH7_OK;
- if(pValue == 0) {
- PH7_MemObjRelease(pCtx->pRet);
- } else {
- rc = PH7_MemObjStore(pValue, pCtx->pRet);
- }
- return rc;
- }
- /*
- * [CAPIREF: ph7_result_resource()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_result_resource(ph7_context *pCtx, void *pUserData) {
- return ph7_value_resource(pCtx->pRet, pUserData);
- }
- /*
- * [CAPIREF: ph7_context_new_scalar()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- ph7_value *ph7_context_new_scalar(ph7_context *pCtx) {
- ph7_value *pVal;
- pVal = ph7_new_scalar(pCtx->pVm);
- if(pVal) {
- /* Record value address so it can be freed automatically
- * when the calling function returns.
- */
- SySetPut(&pCtx->sVar, (const void *)&pVal);
- }
- return pVal;
- }
- /*
- * [CAPIREF: ph7_context_new_array()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- ph7_value *ph7_context_new_array(ph7_context *pCtx) {
- ph7_value *pVal;
- pVal = ph7_new_array(pCtx->pVm);
- if(pVal) {
- /* Record value address so it can be freed automatically
- * when the calling function returns.
- */
- SySetPut(&pCtx->sVar, (const void *)&pVal);
- }
- return pVal;
- }
- /*
- * [CAPIREF: ph7_context_release_value()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- void ph7_context_release_value(ph7_context *pCtx, ph7_value *pValue) {
- PH7_VmReleaseContextValue(&(*pCtx), pValue);
- }
- /*
- * [CAPIREF: ph7_context_alloc_chunk()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- void *ph7_context_alloc_chunk(ph7_context *pCtx, unsigned int nByte, int ZeroChunk, int AutoRelease) {
- void *pChunk;
- pChunk = SyMemBackendAlloc(&pCtx->pVm->sAllocator, nByte);
- if(pChunk) {
- if(ZeroChunk) {
- /* Zero the memory chunk */
- SyZero(pChunk, nByte);
- }
- if(AutoRelease) {
- ph7_aux_data sAux;
- /* Track the chunk so that it can be released automatically
- * upon this context is destroyed.
- */
- sAux.pAuxData = pChunk;
- SySetPut(&pCtx->sChunk, (const void *)&sAux);
- }
- }
- return pChunk;
- }
- /*
- * Check if the given chunk address is registered in the call context
- * chunk container.
- * Return TRUE if registered.FALSE otherwise.
- * Refer to [ph7_context_realloc_chunk(),ph7_context_free_chunk()].
- */
- static ph7_aux_data *ContextFindChunk(ph7_context *pCtx, void *pChunk) {
- ph7_aux_data *aAux, *pAux;
- sxu32 n;
- if(SySetUsed(&pCtx->sChunk) < 1) {
- /* Don't bother processing,the container is empty */
- return 0;
- }
- /* Perform the lookup */
- aAux = (ph7_aux_data *)SySetBasePtr(&pCtx->sChunk);
- for(n = 0; n < SySetUsed(&pCtx->sChunk) ; ++n) {
- pAux = &aAux[n];
- if(pAux->pAuxData == pChunk) {
- /* Chunk found */
- return pAux;
- }
- }
- /* No such allocated chunk */
- return 0;
- }
- /*
- * [CAPIREF: ph7_context_realloc_chunk()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- void *ph7_context_realloc_chunk(ph7_context *pCtx, void *pChunk, unsigned int nByte) {
- ph7_aux_data *pAux;
- void *pNew;
- pNew = SyMemBackendRealloc(&pCtx->pVm->sAllocator, pChunk, nByte);
- if(pNew) {
- pAux = ContextFindChunk(pCtx, pChunk);
- if(pAux) {
- pAux->pAuxData = pNew;
- }
- }
- return pNew;
- }
- /*
- * [CAPIREF: ph7_context_free_chunk()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- void ph7_context_free_chunk(ph7_context *pCtx, void *pChunk) {
- ph7_aux_data *pAux;
- if(pChunk == 0) {
- /* TICKET-1433-93: NULL chunk is a harmless operation */
- return;
- }
- pAux = ContextFindChunk(pCtx, pChunk);
- if(pAux) {
- /* Mark as destroyed */
- pAux->pAuxData = 0;
- }
- SyMemBackendFree(&pCtx->pVm->sAllocator, pChunk);
- }
- /*
- * [CAPIREF: ph7_array_fetch()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- ph7_value *ph7_array_fetch(ph7_value *pArray, const char *zKey, int nByte) {
- ph7_hashmap_node *pNode;
- ph7_value *pValue;
- ph7_value skey;
- int rc;
- /* Make sure we are dealing with a valid hashmap */
- if((pArray->nType & MEMOBJ_HASHMAP) == 0) {
- return 0;
- }
- if(nByte < 0) {
- nByte = (int)SyStrlen(zKey);
- }
- /* Convert the key to a ph7_value */
- PH7_MemObjInit(pArray->pVm, &skey);
- PH7_MemObjStringAppend(&skey, zKey, (sxu32)nByte);
- /* Perform the lookup */
- rc = PH7_HashmapLookup((ph7_hashmap *)pArray->x.pOther, &skey, &pNode);
- PH7_MemObjRelease(&skey);
- if(rc != PH7_OK) {
- /* No such entry */
- return 0;
- }
- /* Extract the target value */
- pValue = (ph7_value *)SySetAt(&pArray->pVm->aMemObj, pNode->nValIdx);
- return pValue;
- }
- /*
- * [CAPIREF: ph7_array_walk()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_array_walk(ph7_value *pArray, int (*xWalk)(ph7_value *pValue, ph7_value *, void *), void *pUserData) {
- int rc;
- if(xWalk == 0) {
- return PH7_CORRUPT;
- }
- /* Make sure we are dealing with a valid hashmap */
- if((pArray->nType & MEMOBJ_HASHMAP) == 0) {
- return PH7_CORRUPT;
- }
- /* Start the walk process */
- rc = PH7_HashmapWalk((ph7_hashmap *)pArray->x.pOther, xWalk, pUserData);
- return rc != PH7_OK ? PH7_ABORT /* User callback request an operation abort*/ : PH7_OK;
- }
- /*
- * [CAPIREF: ph7_array_add_elem()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_array_add_elem(ph7_value *pArray, ph7_value *pKey, ph7_value *pValue) {
- int rc;
- /* Make sure we are dealing with a valid hashmap */
- if((pArray->nType & MEMOBJ_HASHMAP) == 0) {
- return PH7_CORRUPT;
- }
- /* Perform the insertion */
- rc = PH7_HashmapInsert((ph7_hashmap *)pArray->x.pOther, &(*pKey), &(*pValue));
- return rc;
- }
- /*
- * [CAPIREF: ph7_array_add_strkey_elem()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_array_add_strkey_elem(ph7_value *pArray, const char *zKey, ph7_value *pValue) {
- int rc;
- /* Make sure we are dealing with a valid hashmap */
- if((pArray->nType & MEMOBJ_HASHMAP) == 0) {
- return PH7_CORRUPT;
- }
- /* Perform the insertion */
- if(SX_EMPTY_STR(zKey)) {
- /* Empty key,assign an automatic index */
- rc = PH7_HashmapInsert((ph7_hashmap *)pArray->x.pOther, 0, &(*pValue));
- } else {
- ph7_value sKey;
- PH7_MemObjInitFromString(pArray->pVm, &sKey, 0);
- PH7_MemObjStringAppend(&sKey, zKey, (sxu32)SyStrlen(zKey));
- rc = PH7_HashmapInsert((ph7_hashmap *)pArray->x.pOther, &sKey, &(*pValue));
- PH7_MemObjRelease(&sKey);
- }
- return rc;
- }
- /*
- * [CAPIREF: ph7_array_add_intkey_elem()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_array_add_intkey_elem(ph7_value *pArray, int iKey, ph7_value *pValue) {
- ph7_value sKey;
- int rc;
- /* Make sure we are dealing with a valid hashmap */
- if((pArray->nType & MEMOBJ_HASHMAP) == 0) {
- return PH7_CORRUPT;
- }
- PH7_MemObjInitFromInt(pArray->pVm, &sKey, iKey);
- /* Perform the insertion */
- rc = PH7_HashmapInsert((ph7_hashmap *)pArray->x.pOther, &sKey, &(*pValue));
- PH7_MemObjRelease(&sKey);
- return rc;
- }
- /*
- * [CAPIREF: ph7_array_count()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- unsigned int ph7_array_count(ph7_value *pArray) {
- ph7_hashmap *pMap;
- /* Make sure we are dealing with a valid hashmap */
- if((pArray->nType & MEMOBJ_HASHMAP) == 0) {
- return 0;
- }
- /* Point to the internal representation of the hashmap */
- pMap = (ph7_hashmap *)pArray->x.pOther;
- return pMap->nEntry;
- }
- /*
- * [CAPIREF: ph7_object_walk()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_object_walk(ph7_value *pObject, int (*xWalk)(const char *, ph7_value *, void *), void *pUserData) {
- int rc;
- if(xWalk == 0) {
- return PH7_CORRUPT;
- }
- /* Make sure we are dealing with a valid class instance */
- if((pObject->nType & MEMOBJ_OBJ) == 0) {
- return PH7_CORRUPT;
- }
- /* Start the walk process */
- rc = PH7_ClassInstanceWalk((ph7_class_instance *)pObject->x.pOther, xWalk, pUserData);
- return rc != PH7_OK ? PH7_ABORT /* User callback request an operation abort*/ : PH7_OK;
- }
- /*
- * [CAPIREF: ph7_object_fetch_attr()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- ph7_value *ph7_object_fetch_attr(ph7_value *pObject, const char *zAttr) {
- ph7_value *pValue;
- SyString sAttr;
- /* Make sure we are dealing with a valid class instance */
- if((pObject->nType & MEMOBJ_OBJ) == 0 || zAttr == 0) {
- return 0;
- }
- SyStringInitFromBuf(&sAttr, zAttr, SyStrlen(zAttr));
- /* Extract the attribute value if available.
- */
- pValue = PH7_ClassInstanceFetchAttr((ph7_class_instance *)pObject->x.pOther, &sAttr);
- return pValue;
- }
- /*
- * [CAPIREF: ph7_object_get_class_name()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- const char *ph7_object_get_class_name(ph7_value *pObject, int *pLength) {
- ph7_class *pClass;
- if(pLength) {
- *pLength = 0;
- }
- /* Make sure we are dealing with a valid class instance */
- if((pObject->nType & MEMOBJ_OBJ) == 0) {
- return 0;
- }
- /* Point to the class */
- pClass = ((ph7_class_instance *)pObject->x.pOther)->pClass;
- /* Return the class name */
- if(pLength) {
- *pLength = (int)SyStringLength(&pClass->sName);
- }
- return SyStringData(&pClass->sName);
- }
- /*
- * [CAPIREF: ph7_context_output()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_context_output(ph7_context *pCtx, const char *zString, int nLen) {
- SyString sData;
- int rc;
- if(nLen < 0) {
- nLen = (int)SyStrlen(zString);
- }
- SyStringInitFromBuf(&sData, zString, nLen);
- rc = PH7_VmOutputConsume(pCtx->pVm, &sData);
- return rc;
- }
- /*
- * [CAPIREF: ph7_context_output_format()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_context_output_format(ph7_context *pCtx, const char *zFormat, ...) {
- va_list ap;
- int rc;
- va_start(ap, zFormat);
- rc = PH7_VmOutputConsumeAp(pCtx->pVm, zFormat, ap);
- va_end(ap);
- return rc;
- }
- /*
- * [CAPIREF: ph7_context_random_num()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- unsigned int ph7_context_random_num(ph7_context *pCtx) {
- sxu32 n;
- n = PH7_VmRandomNum(pCtx->pVm);
- return n;
- }
- /*
- * [CAPIREF: ph7_context_random_string()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_context_random_string(ph7_context *pCtx, char *zBuf, int nBuflen) {
- if(nBuflen < 3) {
- return PH7_CORRUPT;
- }
- PH7_VmRandomString(pCtx->pVm, zBuf, nBuflen);
- return PH7_OK;
- }
- /*
- * IMP-12-07-2012 02:10 Experimantal public API.
- *
- * ph7_vm * ph7_context_get_vm(ph7_context *pCtx)
- * {
- * return pCtx->pVm;
- * }
- */
- /*
- * [CAPIREF: ph7_context_user_data()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- void *ph7_context_user_data(ph7_context *pCtx) {
- return pCtx->pFunc->pUserData;
- }
- /*
- * [CAPIREF: ph7_context_push_aux_data()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_context_push_aux_data(ph7_context *pCtx, void *pUserData) {
- ph7_aux_data sAux;
- int rc;
- sAux.pAuxData = pUserData;
- rc = SySetPut(&pCtx->pFunc->aAux, (const void *)&sAux);
- return rc;
- }
- /*
- * [CAPIREF: ph7_context_peek_aux_data()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- void *ph7_context_peek_aux_data(ph7_context *pCtx) {
- ph7_aux_data *pAux;
- pAux = (ph7_aux_data *)SySetPeek(&pCtx->pFunc->aAux);
- return pAux ? pAux->pAuxData : 0;
- }
- /*
- * [CAPIREF: ph7_context_pop_aux_data()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- void *ph7_context_pop_aux_data(ph7_context *pCtx) {
- ph7_aux_data *pAux;
- pAux = (ph7_aux_data *)SySetPop(&pCtx->pFunc->aAux);
- return pAux ? pAux->pAuxData : 0;
- }
- /*
- * [CAPIREF: ph7_context_result_buf_length()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- unsigned int ph7_context_result_buf_length(ph7_context *pCtx) {
- return SyBlobLength(&pCtx->pRet->sBlob);
- }
- /*
- * [CAPIREF: ph7_function_name()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- const char *ph7_function_name(ph7_context *pCtx) {
- SyString *pName;
- pName = &pCtx->pFunc->sName;
- return pName->zString;
- }
- /*
- * [CAPIREF: ph7_value_int()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_int(ph7_value *pVal, int iValue) {
- /* Invalidate any prior representation */
- PH7_MemObjRelease(pVal);
- pVal->x.iVal = (ph7_int64)iValue;
- MemObjSetType(pVal, MEMOBJ_INT);
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_int64()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_int64(ph7_value *pVal, ph7_int64 iValue) {
- /* Invalidate any prior representation */
- PH7_MemObjRelease(pVal);
- pVal->x.iVal = iValue;
- MemObjSetType(pVal, MEMOBJ_INT);
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_bool()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_bool(ph7_value *pVal, int iBool) {
- /* Invalidate any prior representation */
- PH7_MemObjRelease(pVal);
- pVal->x.iVal = iBool ? 1 : 0;
- MemObjSetType(pVal, MEMOBJ_BOOL);
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_char()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_char(ph7_value *pVal, int cValue) {
- /* Invalidate any prior representation */
- PH7_MemObjRelease(pVal);
- if(cValue >= 0 && cValue <= 255) {
- pVal->x.iVal = cValue;
- } else {
- pVal->x.iVal = 0;
- }
- MemObjSetType(pVal, MEMOBJ_CHAR);
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_double()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_double(ph7_value *pVal, double Value) {
- /* Invalidate any prior representation */
- PH7_MemObjRelease(pVal);
- pVal->x.rVal = (ph7_real)Value;
- MemObjSetType(pVal, MEMOBJ_REAL);
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_void()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_void(ph7_value *pVal) {
- /* Invalidate any prior representation */
- PH7_MemObjRelease(pVal);
- MemObjSetType(pVal, MEMOBJ_VOID);
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_string()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_string(ph7_value *pVal, const char *zString, int nLen) {
- if((pVal->nType & MEMOBJ_STRING) == 0) {
- /* Invalidate any prior representation */
- PH7_MemObjRelease(pVal);
- MemObjSetType(pVal, MEMOBJ_STRING);
- }
- if(zString) {
- if(nLen < 0) {
- /* Compute length automatically */
- nLen = (int)SyStrlen(zString);
- }
- SyBlobAppend(&pVal->sBlob, (const void *)zString, (sxu32)nLen);
- }
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_string_format()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_string_format(ph7_value *pVal, const char *zFormat, ...) {
- va_list ap;
- if((pVal->nType & MEMOBJ_STRING) == 0) {
- /* Invalidate any prior representation */
- PH7_MemObjRelease(pVal);
- MemObjSetType(pVal, MEMOBJ_STRING);
- }
- va_start(ap, zFormat);
- SyBlobFormatAp(&pVal->sBlob, zFormat, ap);
- va_end(ap);
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_reset_string_cursor()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_reset_string_cursor(ph7_value *pVal) {
- /* Reset the string cursor */
- SyBlobReset(&pVal->sBlob);
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_resource()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_resource(ph7_value *pVal, void *pUserData) {
- /* Invalidate any prior representation */
- PH7_MemObjRelease(pVal);
- /* Reflect the new type */
- pVal->x.pOther = pUserData;
- MemObjSetType(pVal, MEMOBJ_RES);
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_release()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_release(ph7_value *pVal) {
- PH7_MemObjRelease(pVal);
- return PH7_OK;
- }
- /*
- * [CAPIREF: ph7_value_is_int()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_int(ph7_value *pVal) {
- return (pVal->nType & MEMOBJ_INT) ? TRUE : FALSE;
- }
- /*
- * [CAPIREF: ph7_value_is_float()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_float(ph7_value *pVal) {
- return (pVal->nType & MEMOBJ_REAL) ? TRUE : FALSE;
- }
- /*
- * [CAPIREF: ph7_value_is_bool()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_bool(ph7_value *pVal) {
- return (pVal->nType & MEMOBJ_BOOL) ? TRUE : FALSE;
- }
- /*
- * [CAPIREF: ph7_value_is_char()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_char(ph7_value *pVal) {
- return (pVal->nType & MEMOBJ_CHAR) ? TRUE : FALSE;
- }
- /*
- * [CAPIREF: ph7_value_is_void()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_void(ph7_value *pVal) {
- return (pVal->nType & MEMOBJ_VOID) ? TRUE : FALSE;
- }
- /*
- * [CAPIREF: ph7_value_is_string()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_string(ph7_value *pVal) {
- return (pVal->nType & MEMOBJ_STRING) ? TRUE : FALSE;
- }
- /*
- * [CAPIREF: ph7_value_is_numeric()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_numeric(ph7_value *pVal) {
- int rc;
- rc = PH7_MemObjIsNumeric(pVal);
- return rc;
- }
- /*
- * [CAPIREF: ph7_value_is_callable()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_callable(ph7_value *pVal) {
- int rc;
- rc = PH7_VmIsCallable(pVal->pVm, pVal, FALSE);
- return rc;
- }
- /*
- * [CAPIREF: ph7_value_is_callback()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_callback(ph7_value *pVal) {
- return (pVal->nType & MEMOBJ_CALL) ? TRUE : FALSE;
- }
- /*
- * [CAPIREF: ph7_value_is_scalar()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_scalar(ph7_value *pVal) {
- return (pVal->nType & MEMOBJ_SCALAR) ? TRUE : FALSE;
- }
- /*
- * [CAPIREF: ph7_value_is_array()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_array(ph7_value *pVal) {
- return (pVal->nType & MEMOBJ_HASHMAP) ? TRUE : FALSE;
- }
- /*
- * [CAPIREF: ph7_value_is_object()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_object(ph7_value *pVal) {
- return (pVal->nType & MEMOBJ_OBJ) ? TRUE : FALSE;
- }
- /*
- * [CAPIREF: ph7_value_is_resource()]
- * Please refer to the official documentation for function purpose and expected parameters.
- */
- int ph7_value_is_resource(ph7_value *pVal) {
- return (pVal->nType & MEMOBJ_RES) ? TRUE : FALSE;
- }
|