#include "lib.h" int psyc_inherits(char *sho, size_t slen, char *lon, size_t llen) { // this allows to pass zero-terminated strings instead of providing // the length.. but we would be faster here if we expected the callee // to always use the PSYC_C2ARG() macro instead. additionally, the // empty string would then be fully supported (in case you want that) // Disabled this, let's use that macro rather. //if (!slen) slen = strlen(sho); //if (!llen) llen = strlen(lon); if (slen == 0 || *sho != '_' || llen == 0 || *lon != '_') { P1(("Please use long format keywords (compact ones would be faster, I know..)\n")); return -2; } if (slen > llen) { P1(("The long string is shorter than the short one.\n")); return -3; } if (!strncmp(sho, lon, slen)) { /* according to PSYC spec we have hereby already proved * inheritance. the following check is optional! */ if (llen > slen && lon[slen] != '_') { /* It is illegal to introduce a keyword family * that starts just like an existing one. Since * _failure exists, you can't use _fail. But * implementations are not required to recognize * that. */ P1(("Illegal choice of keyword names!\n")); return -4; } return 0; } P4(("%.*s does not inherit from %.*s.\n", (int) llen, lon, (int) slen, sho)); return 1; } int psyc_matches(char *sho, size_t slen, char *lon, size_t llen) { char *s, *l, *se, *le; //if (!slen) slen = strlen(sho); //if (!llen) llen = strlen(lon); if (slen == 0 || *sho != '_' || llen == 0 || *lon != '_') { P1(("Please use long format keywords (compact ones would be faster, I know..)\n")); return -2; } if (slen > llen) { P1(("The long string is shorter than the short one.\n")); return -3; } if (slen == llen) { if (!strncmp(sho, lon, slen)) { P1(("Identical arguments.\n")); return 0; } P1(("Same length but different.\nNo match, but they could be related or have a common type.\n")); return -4; } P3(("# psyc_matches short '%.*s' in long '%.*s' ?\n", (int) slen, sho, (int) llen, lon)); se = sho + slen; le = lon + llen; sho++; lon++; slen--; llen--; while (*sho && sho < se) { P3(("# comparing short '%.*s' (%d)\n", (int) slen, sho, (int) slen)); unless(s = memchr(sho, '_', slen)) s = se; P4(("# sho goes '%c' and lon goes '%c'\n", *sho, (int) *lon)); while (*lon && lon < le) { P3(("# against long '%.*s' (%d)\n", (int) llen, lon, (int) llen)); unless(l = memchr(lon, '_', llen)) l = le; P3(("# %ld == %ld && !strncmp '%.*s', '%.*s'\n", s - sho, l - lon, (int) (s - sho), sho, (int) (s - sho), lon)); if (l - lon == s - sho && !strncmp(sho, lon, s - sho)) goto foundone; P4(("# failed\n")); llen -= l - lon + 1; lon = ++l; } goto failed; foundone: P3(("# found %ld of short '%.*s' and long '%.*s'\n", s - sho, (int) (s - sho), sho, (int) (s - sho), lon)); llen -= l - lon; slen -= s - sho; sho = ++s; lon = ++l; } return 0; failed: P4(("No, they don't match.\n")); return 1; } /** * Look up value associated with a key in a map. */ void * psyc_map_lookup(const PsycMap * map, size_t size, const char *key, size_t keylen, PsycBool inherit) { //size_t cursor = 1; size_t c = 0; uint8_t i, match = 0; if (keylen < 2 || key[0] != '_') return 0; //for (c = 0, i = 0; c < keylen && i < size; c++) { for (i = 0; i < size; i++) { if (!(keylen == map[i].key.length || (inherit && keylen > map[i].key.length && key[map[i].key.length] == '_'))) continue; match = 1; for (c = 0; c < keylen; c++) { if (c < map[i].key.length && map[i].key.data[c] == key[c]) continue; else if (c == map[i].key.length && key[c] == '_') return map[i].value; // after the end of a matching prefix else if (map[i].key.data[c] > key[c]) return NULL; match = 0; break; } if (match) return map[i].value; } return NULL; } #ifdef CMDTOOL int main(int argc, char **argv) { if (argc != 3) { printf("Usage: %s \n\n" "Example: %s _failure_delivery _failure_unsuccessful_delivery_death\n", argv[0], argv[0]); return -1; } if (psyc_matches(argv[1], 0, argv[2], 0) == 0) printf("Yes, %s matches %s!\n", argv[1], argv[2]); if (psyc_inherits(argv[1], 0, argv[2], 0) == 0) printf("Yes, %s inherits from %s!\n", argv[2], argv[1]); } #endif