ci.c

来自「基于h323协议的软phone」· C语言 代码 · 共 642 行 · 第 1/2 页

C
642
字号
/*

NOTICE:
This document contains information that is proprietary to RADVISION LTD.
No part of this publication may be reproduced in any form whatsoever without
written prior approval by RADVISION LTD.

RADVISION LTD reserves the right to revise this publication and make changes
without obligation to notify any person of such revisions or changes.

*/

/***************************************************************************

  ci.c  --  Configuration Interface

  Module Author: Oz Solomonovich
  This Comment:  26-Dec-1996

  Abstract:      Low level configuration interface for the H323 Stack.

                 Configuration information can reside in a number of
                 different sources.  CI converts the data from the
                 configuration source into an internal R-Tree, with the
                 aid of the helper functions found in cisupp.c.

  Platforms:     All.

  Known Bugs:    None.

***************************************************************************/

#include "rvmemory.h"
#include "rvcbase.h"
#include "rtree.h"
#include "rpool.h"

#include "ci.h"
#include "cisupp.h"


#ifdef __cplusplus
extern "C" {
#endif


/* local functions */
static int ciGetNodeID(IN HCFG hCfg, IN const char *path);


#define CONFIG_POOL_OVERHEAD  4


RVAPI
HCFG RVCALLCONV ciConstruct(IN const char *source)
{
    return ciConstructEx(source, 0, 0);
}

RVAPI
HCFG RVCALLCONV ciConstructEx(
        IN  const char * source,     /* configuration source identifier */
        IN  int          extraData,  /* maximum amount of data growth */
        IN  int          extraNodes  /* maximum number of nodes growth */
        )
{
    int nodes, data, size;
    cfgHandle *hCfg = NULL;
    RvStatus res;

    /* Initialize the common core - this might be the first API function an application
       calls in H.323 */
    res = RvCBaseInit();
    if (res != RV_OK)
        return NULL;

    if(RvMemoryAlloc(NULL, (void**)&hCfg, sizeof(cfgHandle)) != RV_OK)
    {
        RvCBaseEnd();
        return NULL;
    }

    hCfg->pool = 0;
    hCfg->tree = 0;
    hCfg->isMutexConstructed = RV_FALSE;

    if (RvMutexConstruct(&hCfg->mutex) != RV_OK)
    {
        ciDestruct((HCFG)hCfg);
        return NULL;
    }
    hCfg->isMutexConstructed = RV_TRUE;

    if (source != NULL)
    {
        ciEstimateCfgSize(source, &nodes, &data);
        if (nodes < 0  ||  data < 0)
        {
            ciDestruct((HCFG)hCfg);
            return NULL;
        }
    }
    else
    {
        data = 0;
        nodes = 0;
    }

    data  += extraData;
    nodes += extraNodes;

    size = (nodes + 1) * 2 * CONFIG_POOL_OVERHEAD + data + 100;
    size = (size + CONFIG_RPOOL_BLOCK_SIZE) / CONFIG_RPOOL_BLOCK_SIZE;   /* set to chuncks of 8 bytes */

    hCfg->pool = rpoolConstruct(CONFIG_RPOOL_BLOCK_SIZE, size, RV_FALSE, "CONFIG");
    if ((hCfg->tree = ciBuildRTree(source, nodes, hCfg->pool)) == NULL)
    {
        ciDestruct((HCFG)hCfg);
        return NULL;
    }

    return (HCFG)hCfg;
}

RVAPI
ci_errors RVCALLCONV ciDestruct(IN HCFG hCfg)
{
    int nodeID,rootID;
    cfgHandle* cfg = (cfgHandle *)hCfg;

    if (!hCfg)
        return ERR_CI_GENERALERROR;

    rootID=nodeID=rtRoot(cfg->tree);
    if (cfg->tree)  rtDestruct  (cfg->tree);
    if (cfg->pool)  rpoolDestruct(cfg->pool);

    if (cfg->isMutexConstructed)
        RvMutexDestruct(&cfg->mutex);

    RvMemoryFree((void *)hCfg);

    RvCBaseEnd();

    return ERR_CI_NOERROR;

}

RVAPI
ci_errors RVCALLCONV ciSave(
    IN HCFG hCfg,
    IN char *target)
{
    cfgHandle* cfg = (cfgHandle *)hCfg;
    ci_errors result;

    if (hCfg == NULL)
        return ERR_CI_GENERALERROR;

    RvMutexLock(&cfg->mutex);
    result = (ci_errors)ciOutputRTree(target, cfg->tree, cfg->pool);
    RvMutexUnlock(&cfg->mutex);

    return result;
}

static int ciGetNodeID(IN HCFG hCfg, IN const char *path)
{
    int nodeID;
    int len;
    RvChar* dot;
    pcfgValue cfgVal;

    if (!path || !*path)
        return ERR_CI_GENERALERROR;

    if ((nodeID = rtHead(__hCfg->tree, rtRoot(__hCfg->tree))) < 0)
        return ERR_CI_GENERALERROR;

    while (*path)
    {
        dot = (RvChar*) strchr(path, '.');
        len = dot? dot - path : strlen(path);
        cfgVal = (pcfgValue)rtGetByPath(__hCfg->tree, nodeID);

        while (rpoolChunkSize(__hCfg->pool, cfgVal->name) != len  ||
               rpoolCompareExternal(__hCfg->pool, cfgVal->name, (void*)path, len))
        {
            nodeID = rtBrother(__hCfg->tree, nodeID);
            if (nodeID < 0)
                return ERR_CI_NOTFOUND;
            cfgVal = (pcfgValue)rtGetByPath(__hCfg->tree, nodeID);
        }

        if (!dot)
            break;

        nodeID = rtHead(__hCfg->tree, nodeID);
        if (nodeID < 0)
            return ERR_CI_NOTFOUND;

        path = dot + 1;
    }

    return nodeID;
}


RVAPI
ci_errors RVCALLCONV ciGetValue(
        IN  HCFG         hCfg,
        IN  const char * path,      /* full path to nodeID, i.e. "a.b.c" */
        OUT RvBool*      isString,
        OUT RvInt32 *    value      /* data for ints, length for strings */
        )
{
    ci_str_type strtype = ci_str_not;
    ci_errors err;

    /* No need to lock this function... */
    err = ciGetValueExt(hCfg, path, &strtype, value);
    if (isString) *isString = (strtype != ci_str_not);
    return err;
}


RVAPI
ci_errors RVCALLCONV ciGetValueExt(
        IN  HCFG         hCfg,
        IN  const char  *path,      /* full path to nodeID, i.e. "a.b.c" */
        OUT ci_str_type *strType,
        OUT RvInt32 *    value      /* data for ints, length for strings */
        )
{
    cfgHandle* cfg = (cfgHandle *)hCfg;
    int bits, nodeID;
    pcfgValue cfgVal;
    ci_str_type dummy;

    if (hCfg == NULL)
        return ERR_CI_GENERALERROR;

    RvMutexLock(&cfg->mutex);
    nodeID = ciGetNodeID(hCfg, (char *)path);

    if (nodeID < 0)
    {
        RvMutexUnlock(&cfg->mutex);
        return (ci_errors)nodeID;
    }

    cfgVal = (pcfgValue)rtGetByPath(cfg->tree, nodeID);

    if (value) *value = cfgVal->value;

    if (!strType) strType = &dummy;

    if (cfgVal->isString)
    {
        char buff[MAX_CONFIG_TEMP_BUFFER_SIZE];
        rpoolCopyToExternal(cfg->pool, (void *)buff, cfgVal->str, 0, MAX_CONFIG_TEMP_BUFFER_SIZE);
        if ((bits = ciIsBitString(buff, cfgVal->value)) >= 0)
        {
            *strType = ci_str_bit;
            if (value) *value = (bits + 7) / 8;
        }
        else
        {
            *strType = ci_str_regular;
        }
    }
    else
        *strType = ci_str_not;

    RvMutexUnlock(&cfg->mutex);
    return ERR_CI_NOERROR;
}


static
ci_errors RVCALLCONV ciGetStringInternal(
                                         IN   HCFG         hCfg,
                                         IN   const char * path,      /* full path to nodeID, i.e. "a.b.c" */
                                         OUT  char *       str,
                                         IN   RvUint32     maxStrLen, /* length of output string buffer */
                                         OUT  RvUint32 *   outbits
                                         )
{
    int bits, nodeID = ciGetNodeID(hCfg, (char *)path);
    RvSize_t length;
    pcfgValue cfgVal;
    const char *srcstr;
    char buff[MAX_CONFIG_TEMP_BUFFER_SIZE];

    if (nodeID < 0)
        return (ci_errors)nodeID;

    cfgVal = (pcfgValue)rtGetByPath(__hCfg->tree, nodeID);

    if (!cfgVal->isString)
        return ERR_CI_GENERALERROR;

    rpoolCopyToExternal(__hCfg->pool, (void *)buff, cfgVal->str, 0, MAX_CONFIG_TEMP_BUFFER_SIZE);
    if ((bits = ciIsBitString(buff, cfgVal->value)) >= 0)
    {
        length = (bits + 7) / 8;
        srcstr = ciGetBitStringData(buff);
    }
    else
    {
        length = cfgVal->value;
        srcstr = buff;
    }

    if (maxStrLen < ((RvUint32)length))
        return ERR_CI_BUFFERTOOSMALL;

    memcpy(str, srcstr, length);
    if (maxStrLen > ((RvUint32)length))
        str[(int)length] = '\0';

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?