Commit 66e8ef31 authored by Hanspeter Portner's avatar Hanspeter Portner

Squashed 'osc.lv2/' changes from 6885c8f..8eee956

8eee956 add unit test for lv2_osc_reader_match.
343a802 fix unused function on mingw.
a7ad408 fix last commit.
8b35622 ignore missing fnmatch.h on mingw.
8d93e69 ignore missing FNM_EXTMATCH definition on darwin.
4c14d72 meson: compile with -std=gnu11.
c04f3bc prototype reader message path matching.
c9bb19d util: implement pattern matching via fnmatch.
c471d99 add missing stdlib header.

git-subtree-dir: osc.lv2
git-subtree-split: 8eee956efee8fdaa88b07fcdb92dfc51c8a9cd55
parent 27d643ed
......@@ -24,14 +24,26 @@
#include <osc.lv2/osc.h>
#include <osc.lv2/endian.h>
#include <osc.lv2/util.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _LV2_OSC_Tree LV2_OSC_Tree;
typedef struct _LV2_OSC_Reader LV2_OSC_Reader;
typedef struct _LV2_OSC_Item LV2_OSC_Item;
typedef struct _LV2_OSC_Arg LV2_OSC_Arg;
typedef void (*LV2_OSC_Branch)(const char *path, LV2_OSC_Reader *reader,
LV2_OSC_Arg *arg, void *data);
struct _LV2_OSC_Tree {
const char *name;
const LV2_OSC_Tree *trees;
LV2_OSC_Branch branch;
void *data;
};
struct _LV2_OSC_Reader {
const uint8_t *buf;
......@@ -564,6 +576,45 @@ lv2_osc_reader_is_message(LV2_OSC_Reader *reader)
return reader->ptr[0] == '/'; //FIXME check path
}
static inline void
_lv2_osc_trees_internal(LV2_OSC_Reader *reader, const char *path, const char *from,
LV2_OSC_Arg *arg, const LV2_OSC_Tree *trees)
{
const char *ptr = strchr(from, '/');
const size_t len = ptr
? (size_t)(ptr - from)
: strlen(from);
for(const LV2_OSC_Tree *tree = trees; tree && tree->name; tree++)
{
if(lv2_osc_pattern_match(from, tree->name, len))
{
if(tree->trees && ptr)
{
from = &ptr[1];
_lv2_osc_trees_internal(reader, path, from, arg, tree->trees);
}
else if(tree->branch && !ptr)
{
LV2_OSC_Reader reader_clone = *reader;
tree->branch(path, &reader_clone, arg, tree->data);
}
}
}
}
static inline void
lv2_osc_reader_match(LV2_OSC_Reader *reader, size_t len, const LV2_OSC_Tree *trees)
{
LV2_OSC_Arg *arg = OSC_READER_MESSAGE_BEGIN(reader, len);
const char *path = arg->path;
const char *from = &path[1];
_lv2_osc_trees_internal(reader, path, from, arg, trees);
}
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -19,6 +19,7 @@
#define LV2_OSC_STREAM_H
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#if !defined(_WIN32)
# include <arpa/inet.h>
......
......@@ -23,6 +23,9 @@
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#if !defined(_WIN32)
# include <fnmatch.h>
#endif
#include <osc.lv2/osc.h>
......@@ -70,18 +73,77 @@ static const char valid_format_chars [] = {
};
static bool
_lv2_osc_pattern_match(const char *from, const char *name, size_t len)
lv2_osc_pattern_match(const char *from, const char *name, size_t len)
{
const char *ast = strpbrk(from, "/*");
if(ast && (*ast == '*') )
#if !defined(_WIN32)
size_t nbrace = 0;
# if defined(FNM_EXTMATCH)
// count opening curly braces
for(size_t i = 0; i < len; i++)
{
if(from[i] == '{')
{
nbrace++;
}
}
# endif
// allocate temporary pattern buffer
char *pattern = alloca(len + nbrace + 1);
if(!pattern)
{
return false;
}
# if defined(FNM_EXTMATCH)
// convert {x,y} to @(x|y) for extended fnmatch
if(nbrace)
{
len = ast - from;
char *ptr = pattern;
for(size_t i = 0; i < len; i++)
{
switch(from[i])
{
case '{':
{
*ptr++ = '@';
*ptr++ = '(';
} break;
case ',':
{
*ptr++ = '|';
} break;
case '}':
{
*ptr++ = ')';
} break;
default:
{
*ptr++ = from[i];
} break;
}
}
}
else
# endif
{
memcpy(pattern, from, len);
}
//FIXME handle '?[]{}'
return strncmp(from, name, len) == 0
? true
: false;
// terminate pattern string with null terminator
pattern[len + nbrace] = '\0';
# if defined(FNM_EXTMATCH)
return fnmatch(pattern, name, FNM_NOESCAPE | FNM_EXTMATCH) == 0 ? true : false;
# else
return fnmatch(pattern, name, FNM_NOESCAPE) == 0 ? true : false;
# endif
#else
return strncmp(from, name, len) == 0 ? true : false;
#endif
}
static void
......@@ -96,7 +158,7 @@ _lv2_osc_hooks_internal(const char *path, const char *from,
for(const LV2_OSC_Hook *hook = hooks; hook && hook->name; hook++)
{
if(_lv2_osc_pattern_match(from, hook->name, len))
if(lv2_osc_pattern_match(from, hook->name, len))
{
if(hook->hooks && ptr)
{
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment