--- liblscp/trunk/src/common.c 2004/06/18 14:19:19 132 +++ liblscp/trunk/src/common.c 2004/07/07 23:41:07 187 @@ -1,4 +1,4 @@ -// client.c +// common.c // /**************************************************************************** liblscp - LinuxSampler Control Protocol API @@ -25,8 +25,8 @@ #include -// Chunk size magic: -// LSCP_SPLIT_CHUNK1 = 2 ^ LSCP_SPLIT_CHUNK2 +// Split chunk size magic: +// LSCP_SPLIT_CHUNK1 := 2 ^ LSCP_SPLIT_CHUNK2 #define LSCP_SPLIT_CHUNK1 4 #define LSCP_SPLIT_CHUNK2 2 // Chunk size legal calculator. @@ -223,6 +223,18 @@ return psz; } +// Unquote and make a duplicate of an in-split string. +void lscp_unquote_dup ( char **ppszDst, char **ppszSrc ) +{ + // Free desteny string, if already there. + if (*ppszDst) + free(*ppszDst); + *ppszDst = NULL; + // Unquote and duplicate. + if (*ppszSrc) + *ppszDst = lscp_unquote(ppszSrc, 1); +} + // Custom tokenizer. char *lscp_strtok ( char *pchBuffer, const char *pszSeps, char **ppch ) @@ -346,6 +358,11 @@ int iSize, i, j, cchSeps; int *piSplit, *piNewSplit; + // Get it clean first. + pchHead = lscp_ltrim((char *) pszCsv); + if (*pchHead == (char) 0) + return NULL; + // Initial size is one chunk away. iSize = LSCP_SPLIT_CHUNK1; // Allocate and split... @@ -355,7 +372,6 @@ // Make a copy of the original string. i = 0; - pchHead = (char *) pszCsv; if ((piSplit[i++] = atoi(pchHead)) < 0) { free(piSplit); return NULL; @@ -419,6 +435,196 @@ #endif // LSCP_ISPLIT_COUNT +// Split a string into a null terminated array of parameter items. +lscp_param_t *lscp_psplit_create ( const char *pszCsv, const char *pszSeps1, const char *pszSeps2 ) +{ + char *pszHead, *pch; + int iSize, i, j, cchSeps1, cchSeps2; + lscp_param_t *ppSplit, *ppNewSplit; + + pszHead = strdup(pszCsv); + if (pszHead == NULL) + return NULL; + + iSize = LSCP_SPLIT_CHUNK1; + ppSplit = (lscp_param_t *) malloc(iSize * sizeof(lscp_param_t)); + if (ppSplit == NULL) { + free(pszHead); + return NULL; + } + + cchSeps1 = strlen(pszSeps1); + cchSeps2 = strlen(pszSeps2); + + i = 0; + while ((pch = strpbrk(pszHead, pszSeps1)) != NULL) { + ppSplit[i].key = pszHead; + pszHead = pch + cchSeps1; + *pch = (char) 0; + ppSplit[i].value = lscp_unquote(&pszHead, 0); + if ((pch = strpbrk(pszHead, pszSeps2)) != NULL) { + pszHead = pch + cchSeps2; + *pch = (char) 0; + } + if (++i >= iSize) { + iSize += LSCP_SPLIT_CHUNK1; + ppNewSplit = (lscp_param_t *) malloc(iSize * sizeof(lscp_param_t)); + if (ppNewSplit) { + for (j = 0; j < i; j++) { + ppNewSplit[j].key = ppSplit[j].key; + ppNewSplit[j].value = ppSplit[j].value; + } + free(ppSplit); + ppSplit = ppNewSplit; + } + } + } + + if (i < 1) + free(pszHead); + + for ( ; i < iSize; i++) { + ppSplit[i].key = NULL; + ppSplit[i].value = NULL; + } + + return ppSplit; +} + + +// Destroy a parameter list array. +void lscp_psplit_destroy ( lscp_param_t *ppSplit ) +{ + if (ppSplit && ppSplit[0].key) + free(ppSplit[0].key); + if (ppSplit) + free(ppSplit); +} + + +#ifdef LSCP_PSPLIT_COUNT + +// Compute a parameter list valid item count. +int lscp_psplit_count ( lscp_param_t *ppSplit ) +{ + int i = 0; + while (ppSplit && ppSplit[i].key) + i++; + return i; +} + +// Compute a parameter list size. +int lscp_psplit_size ( lscp_param_t *ppSplit ) +{ + return LSCP_SPLIT_SIZE(lscp_psplit_count(ppSplit)); +} + +#endif // LSCP_PSPLIT_COUNT + + +// Allocate a parameter list, optionally copying an existing one. +void lscp_plist_alloc (lscp_param_t **ppList) +{ + lscp_param_t *pParams; + int iSize, i; + + if (ppList) { + iSize = LSCP_SPLIT_CHUNK1; + pParams = (lscp_param_t *) malloc(iSize * sizeof(lscp_param_t)); + if (pParams) { + for (i = 0 ; i < iSize; i++) { + pParams[i].key = NULL; + pParams[i].value = NULL; + } + } + *ppList = pParams; + } +} + + +// Destroy a parameter list, including all it's contents. +void lscp_plist_free ( lscp_param_t **ppList ) +{ + lscp_param_t *pParams; + int i; + + if (ppList) { + if (*ppList) { + pParams = *ppList; + for (i = 0; pParams && pParams[i].key; i++) { + free(pParams[i].key); + free(pParams[i].value); + } + free(pParams); + } + *ppList = NULL; + } +} + + +// Add an item to a parameter list, growing it as fit. +void lscp_plist_append ( lscp_param_t **ppList, const char *pszKey, const char *pszValue ) +{ + lscp_param_t *pParams; + lscp_param_t *pNewParams; + int iSize, iNewSize; + int i = 0; + + if (ppList && *ppList) { + pParams = *ppList; + while (pParams[i].key) { + if (strcasecmp(pParams[i].key, pszKey) == 0) { + if (pParams[i].value) + free(pParams[i].value); + pParams[i].value = strdup(pszValue); + return; + } + i++; + } + iSize = LSCP_SPLIT_SIZE(i); + pParams[i].key = strdup(pszKey); + pParams[i].value = strdup(pszValue); + if (++i >= iSize) { + iNewSize = iSize + LSCP_SPLIT_CHUNK1; + pNewParams = (lscp_param_t *) malloc(iNewSize * sizeof(lscp_param_t)); + for (i = 0; i < iSize; i++) { + pParams[i].key = pParams[i].key; + pParams[i].value = pParams[i].value; + } + for ( ; i < iNewSize; i++) { + pNewParams[i].key = NULL; + pNewParams[i].value = NULL; + } + free(pParams); + *ppList = pNewParams; + } + } +} + +#ifdef LSCP_PLIST_COUNT + +// Compute a parameter list valid item count. +int lscp_plist_count ( lscp_param_t **ppList ) +{ + lscp_param_t *pParams; + int i = 0; + if (ppList && *ppList) { + pParams = *ppList; + while (pParams[i].key) + i++; + } + return i; +} + +// Compute the legal parameter list size. +int lscp_plist_size ( lscp_param_t **ppList ) +{ + return LSCP_SPLIT_SIZE(lscp_plist_count(ppList)); +} + +#endif // LSCP_PLIST_COUNT + + //------------------------------------------------------------------------- // Engine info struct helper functions. @@ -428,13 +634,17 @@ pEngineInfo->version = NULL; } -void lscp_engine_info_reset ( lscp_engine_info_t *pEngineInfo ) +void lscp_engine_info_free ( lscp_engine_info_t *pEngineInfo ) { if (pEngineInfo->description) free(pEngineInfo->description); if (pEngineInfo->version) free(pEngineInfo->version); +} +void lscp_engine_info_reset ( lscp_engine_info_t *pEngineInfo ) +{ + lscp_engine_info_free(pEngineInfo); lscp_engine_info_init(pEngineInfo); } @@ -457,7 +667,7 @@ pChannelInfo->volume = 0.0; } -void lscp_channel_info_reset ( lscp_channel_info_t *pChannelInfo ) +void lscp_channel_info_free ( lscp_channel_info_t *pChannelInfo ) { if (pChannelInfo->engine_name) free(pChannelInfo->engine_name); @@ -465,7 +675,11 @@ lscp_szsplit_destroy(pChannelInfo->audio_routing); if (pChannelInfo->instrument_file) free(pChannelInfo->instrument_file); +} +void lscp_channel_info_reset ( lscp_channel_info_t *pChannelInfo ) +{ + lscp_channel_info_free(pChannelInfo); lscp_channel_info_init(pChannelInfo); } @@ -480,16 +694,133 @@ pDriverInfo->parameters = NULL; } -void lscp_driver_info_reset ( lscp_driver_info_t *pDriverInfo ) +void lscp_driver_info_free ( lscp_driver_info_t *pDriverInfo ) { if (pDriverInfo->description) free(pDriverInfo->description); if (pDriverInfo->version) free(pDriverInfo->version); lscp_szsplit_destroy(pDriverInfo->parameters); +} +void lscp_driver_info_reset ( lscp_driver_info_t *pDriverInfo ) +{ + lscp_driver_info_free(pDriverInfo); lscp_driver_info_init(pDriverInfo); } +//------------------------------------------------------------------------- +// Device info struct functions. + +void lscp_device_info_init ( lscp_device_info_t *pDeviceInfo ) +{ + pDeviceInfo->driver = NULL; + lscp_plist_alloc(&(pDeviceInfo->params)); +} + +void lscp_device_info_free ( lscp_device_info_t *pDeviceInfo ) +{ + if (pDeviceInfo->driver) + free(pDeviceInfo->driver); + lscp_plist_free(&(pDeviceInfo->params)); +} + +void lscp_device_info_reset ( lscp_device_info_t *pDeviceInfo ) +{ + lscp_device_info_free(pDeviceInfo); + lscp_device_info_init(pDeviceInfo); +} + + +//------------------------------------------------------------------------- +// Device channel/port info struct functions. + +void lscp_device_port_info_init ( lscp_device_port_info_t *pDevicePortInfo ) +{ + pDevicePortInfo->name = NULL; + lscp_plist_alloc(&(pDevicePortInfo->params)); +} + +void lscp_device_port_info_free ( lscp_device_port_info_t *pDevicePortInfo ) +{ + if (pDevicePortInfo->name) + free(pDevicePortInfo->name); + lscp_plist_free(&(pDevicePortInfo->params)); +} + +void lscp_device_port_info_reset ( lscp_device_port_info_t *pDevicePortInfo ) +{ + lscp_device_port_info_free(pDevicePortInfo); + lscp_device_port_info_init(pDevicePortInfo); +} + + +//------------------------------------------------------------------------- +// Parameter struct helper functions. + +void lscp_param_info_init ( lscp_param_info_t *pParamInfo ) +{ + pParamInfo->type = LSCP_TYPE_NONE; + pParamInfo->description = NULL; + pParamInfo->mandatory = 0; + pParamInfo->fix = 0; + pParamInfo->multiplicity = 0; + pParamInfo->depends = NULL; + pParamInfo->defaultv = NULL; + pParamInfo->range_min = NULL; + pParamInfo->range_max = NULL; + pParamInfo->possibilities = NULL; +} + +void lscp_param_info_free ( lscp_param_info_t *pParamInfo ) +{ + if (pParamInfo->description) + free(pParamInfo->description); + lscp_szsplit_destroy(pParamInfo->depends); + if (pParamInfo->defaultv) + free(pParamInfo->defaultv); + if (pParamInfo->range_min) + free(pParamInfo->range_min); + if (pParamInfo->range_max) + free(pParamInfo->range_max); + lscp_szsplit_destroy(pParamInfo->possibilities); +} + +void lscp_param_info_reset ( lscp_param_info_t *pParamInfo ) +{ + lscp_param_info_free(pParamInfo); + lscp_param_info_init(pParamInfo); +} + + +//------------------------------------------------------------------------- +// Concatenate a parameter list (key='value'...) into a string, +// appending a crlf terminator. + +int lscp_param_concat ( char *pszBuffer, int cchMaxBuffer, lscp_param_t *pParams ) +{ + int cchBuffer, cchParam, i; + + if (pszBuffer == NULL) + return 0; + + cchBuffer = strlen(pszBuffer); + for (i = 0; pParams && pParams[i].key && pParams[i].value; i++) { + cchParam = strlen(pParams[i].key) + strlen(pParams[i].value) + 4; + if (cchBuffer + cchParam + 2 < cchMaxBuffer) { + sprintf(pszBuffer + cchBuffer, " %s='%s'", pParams[i].key, pParams[i].value); + cchBuffer += cchParam; + } + } + + if (cchBuffer + 2 < cchMaxBuffer) { + pszBuffer[cchBuffer++] = '\r'; + pszBuffer[cchBuffer++] = '\n'; + } + + return cchBuffer; +} + + // end of common.c