int prSymbol_matchOSCPattern(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b; int length; a = g->sp - 1; b = g->sp; if (!IsSym(a) || !IsSym(b)) return errWrongType; // int32 alen = slotRawSymbol(a)->length; // int32 blen = slotRawSymbol(b)->length; // length = sc_min(alen, blen); if (lo_pattern_match(slotRawSymbol(a)->name, slotRawSymbol(b)->name)) { SetTrue(a); } else { SetFalse(a); } return errNone; }
void lo_server_del_method(lo_server s, const char *path, const char *typespec) { lo_method it, prev, next; int pattern = 0; if (!s->first) return; if (path) pattern = strpbrk(path, " #*,?[]{}") != NULL; it = s->first; prev = it; while (it) { /* incase we free it */ next = it->next; /* If paths match or handler is wildcard */ if ((it->path == path) || (path && it->path && !strcmp(path, it->path)) || (pattern && lo_pattern_match(it->path, path))) { /* If types match or handler is wildcard */ if ((it->typespec == typespec) || (typespec && it->typespec && !strcmp(typespec, it->typespec)) ) { /* Take care when removing the head. */ if (it == s->first) { s->first = it->next; } else { prev->next = it->next; } next = it->next; free((void *)it->path); free((void *)it->typespec); free(it); it = prev; } } prev = it; if (it) it = next; } }
int lo_pattern_match(const char *str, const char *p) { int negate; int match; char c; while (*p) { if (!*str && *p != '*') return false; switch (c = *p++) { case '*': while (*p == '*' && *p != '/') p++; if (!*p) return true; // if (*p != '?' && *p != '[' && *p != '\\') if (*p != '?' && *p != '[' && *p != '{') while (*str && *p != *str) str++; while (*str) { if (lo_pattern_match(str, p)) return true; str++; } return false; case '?': if (*str) break; return false; /* * set specification is inclusive, that is [a-z] is a, z and * everything in between. this means [z-a] may be interpreted * as a set that contains z, a and nothing in between. */ case '[': if (*p != NEGATE) negate = false; else { negate = true; p++; } match = false; while (!match && (c = *p++)) { if (!*p) return false; if (*p == '-') { /* c-c */ if (!*++p) return false; if (*p != ']') { if (*str == c || *str == *p || (*str > c && *str < *p)) match = true; } else { /* c-] */ if (*str >= c) match = true; break; } } else { /* cc or c] */ if (c == *str) match = true; if (*p != ']') { if (*p == *str) match = true; } else break; } } if (negate == match) return false; /* * if there is a match, skip past the cset and continue on */ while (*p && *p != ']') p++; if (!*p++) /* oops! */ return false; break; /* * {astring,bstring,cstring} */ case '{': { // *p is now first character in the {brace list} const char *place = str; // to backtrack const char *remainder = p; // to forwardtrack // find the end of the brace list while (*remainder && *remainder != '}') remainder++; if (!*remainder++) /* oops! */ return false; c = *p++; while (c) { if (c == ',') { if(lo_pattern_match(str, remainder)) { return true; } else { // backtrack on test string str = place; // continue testing, // skip comma if (!*p++) // oops return false; } } else if (c == '}') { // continue normal pattern matching if (!*p && !*str) return true; str--; // str is incremented again below break; } else if (c == *str) { str++; if (!*str && *remainder) return false; } else { // skip to next comma str = place; while (*p != ',' && *p != '}' && *p) p++; if (*p == ',') p++; else if (*p == '}') { return false; } } c = *p++; } } break; /* Not part of OSC pattern matching case '\\': if (*p) c = *p++; */ default: if (c != *str) return false; break; } str++; } return !*str; }
static void dispatch_method(lo_server s, const char *path, char *types, void *data) { int argc = strlen(types); lo_arg **argv = NULL; lo_method it; int ret = 1; int err; int endian_fixed = 0; int pattern = strpbrk(path, " #*,?[]{}") != NULL; lo_message msg = lo_message_new(); lo_address src = lo_address_new(NULL, NULL); char hostname[LO_HOST_SIZE]; char portname[32]; const char *pptr; free(msg->types); msg->types = types; msg->typelen = strlen(types); msg->typesize = 0; msg->data = data; msg->datalen = 0; msg->datasize = 0; msg->source = src; //inet_ntop(s->addr.ss_family, &s->addr.padding, hostname, sizeof(hostname)); if (s->protocol == LO_UDP) { err = getnameinfo((struct sockaddr *)&s->addr, sizeof(s->addr), hostname, sizeof(hostname), portname, sizeof(portname), NI_NUMERICHOST | NI_NUMERICSERV); if (err) { switch (err) { case EAI_AGAIN: lo_throw(s, err, "Try again", path); break; case EAI_BADFLAGS: lo_throw(s, err, "Bad flags", path); break; case EAI_FAIL: lo_throw(s, err, "Failed", path); break; case EAI_FAMILY: lo_throw(s, err, "Cannot resolve address family", path); break; case EAI_MEMORY: lo_throw(s, err, "Out of memory", path); break; case EAI_NONAME: lo_throw(s, err, "Cannot resolve", path); break; #ifndef WIN32 case EAI_SYSTEM: lo_throw(s, err, strerror(err), path); break; #endif default: lo_throw(s, err, "Unknown error", path); break; } return; } } else { hostname[0] = '\0'; portname[0] = '\0'; } free(src->host); free(src->port); src->host = hostname; src->port = portname; src->proto = s->protocol; for (it = s->first; it; it = it->next) { /* If paths match or handler is wildcard */ if (!it->path || !strcmp(path, it->path) || (pattern && lo_pattern_match(it->path, path))) { /* If types match or handler is wildcard */ if (!it->typespec || !strcmp(types, it->typespec)) { if (!argv && *types) { int i; char *ptr = types - 1 + lo_strsize(types - 1); argv = calloc(argc + 1, sizeof(lo_arg *)); if (!endian_fixed) { for (i=0; i<argc; i++) { argv[i] = (lo_arg *)ptr; lo_arg_host_endian(types[i], ptr); ptr += lo_arg_size(types[i], ptr); } endian_fixed = 1; } } /* Send wildcard path to generic handler, expanded path to others. */ pptr = path; if (it->path) pptr = it->path; ret = it->handler(pptr, types, argv, argc, msg, it->user_data); } else if (lo_can_coerce_spec(types, it->typespec)) { int i; int opsize = 0; char *ptr = types - 1 + lo_strsize(types - 1); char *data_co, *data_co_ptr; argv = calloc(argc+1, sizeof(lo_arg *)); for (i=0; i<argc; i++) { opsize += lo_arg_size(it->typespec[i], ptr); ptr += lo_arg_size(types[i], ptr); } data_co = malloc(opsize); data_co_ptr = data_co; ptr = types - 1 + lo_strsize(types - 1); for (i=0; i<argc; i++) { argv[i] = (lo_arg *)data_co_ptr; if (!endian_fixed) { lo_arg_host_endian(types[i], ptr); } lo_coerce(it->typespec[i], (lo_arg *)data_co_ptr, types[i], (lo_arg *)ptr); data_co_ptr += lo_arg_size(it->typespec[i], data_co_ptr); ptr += lo_arg_size(types[i], ptr); } endian_fixed = 1; /* Send wildcard path to generic handler, expanded path to others. */ pptr = path; if (it->path) pptr = it->path; ret = it->handler(pptr, it->typespec, argv, argc, msg, it->user_data); free(argv); free(data_co); argv = NULL; } if (ret == 0 && !pattern) { break; } } } /* If we find no matching methods, check for protocol level stuff */ if (ret == 1 && s->protocol == LO_UDP) { char *pos = strrchr(path, '/'); /* if its a method enumeration call */ if (pos && *(pos+1) == '\0') { lo_message reply = lo_message_new(); int len = strlen(path); lo_strlist *sl = NULL, *slit, *slnew, *slend; if (!strcmp(types, "i")) { lo_message_add_int32(reply, argv[0]->i); } lo_message_add_string(reply, path); for (it = s->first; it; it = it->next) { /* If paths match */ if (it->path && !strncmp(path, it->path, len)) { char *tmp; char *sec; tmp = malloc(strlen(it->path + len) + 1); strcpy(tmp, it->path + len); #ifdef WIN32 sec = strchr(tmp,'/'); #else sec = index(tmp, '/'); #endif if (sec) *sec = '\0'; slend = sl; for (slit = sl; slit; slend = slit, slit = slit->next) { if (!strcmp(slit->str, tmp)) { free(tmp); tmp = NULL; break; } } if (tmp) { slnew = calloc(1, sizeof(lo_strlist)); slnew->str = tmp; slnew->next = NULL; if (!slend) { sl = slnew; } else { slend->next = slnew; } } } } for (slit = sl; slit; slit = slit->next) { lo_message_add_string(reply, slit->str); free(slit->str); } lo_send_message(src, "#reply", reply); lo_message_free(reply); } } free(argv); /* the address got assigned static stuff, hence not using address_free */ free(src); /* these are already part of data and will be freed later */ msg->data = NULL; msg->types = NULL; lo_message_free(msg); }