2011-05-08 21:40:26 +00:00
|
|
|
#include "lib.h"
|
2011-04-16 11:13:57 +00:00
|
|
|
|
2011-10-31 19:04:16 +00:00
|
|
|
int psyc_inherits (char* sho, size_t slen,
|
|
|
|
char* lon, size_t llen) {
|
2011-04-25 12:47:16 +00:00
|
|
|
|
|
|
|
// 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)
|
2011-04-29 21:00:03 +00:00
|
|
|
// Disabled this, let's use that macro rather.
|
|
|
|
//if (!slen) slen = strlen(sho);
|
|
|
|
//if (!llen) llen = strlen(lon);
|
2011-04-20 21:08:20 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2011-04-30 13:44:12 +00:00
|
|
|
P4(("%.*s does not inherit from %.*s.\n", (int)llen, lon, (int)slen, sho))
|
2011-04-20 21:08:20 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2011-04-18 14:51:54 +00:00
|
|
|
|
2011-10-31 19:04:16 +00:00
|
|
|
int psyc_matches (char* sho, size_t slen,
|
|
|
|
char* lon, size_t llen) {
|
2011-04-20 13:36:56 +00:00
|
|
|
char *s, *l, *se, *le;
|
2011-04-16 11:13:57 +00:00
|
|
|
|
2011-04-29 21:00:03 +00:00
|
|
|
//if (!slen) slen = strlen(sho);
|
|
|
|
//if (!llen) llen = strlen(lon);
|
2011-04-16 12:05:28 +00:00
|
|
|
|
|
|
|
if (slen == 0 || *sho != '_' ||
|
|
|
|
llen == 0 || *lon != '_') {
|
2011-04-20 16:59:27 +00:00
|
|
|
P1(("Please use long format keywords (compact ones would be faster, I know..)\n"))
|
2011-04-16 11:13:57 +00:00
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slen > llen) {
|
2011-04-20 16:59:27 +00:00
|
|
|
P1(("The long string is shorter than the short one.\n"))
|
2011-04-16 11:13:57 +00:00
|
|
|
return -3;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slen == llen) {
|
2011-04-20 16:59:27 +00:00
|
|
|
if (!strncmp(sho, lon, slen)) {
|
|
|
|
P1(("Identical arguments.\n"))
|
2011-04-16 11:13:57 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2011-04-20 16:59:27 +00:00
|
|
|
P1(("Same length but different.\nNo match, but they could be related or have a common type.\n"))
|
2011-04-16 11:13:57 +00:00
|
|
|
return -4;
|
|
|
|
}
|
2011-04-30 13:44:12 +00:00
|
|
|
P3(("# psyc_matches short '%.*s' in long '%.*s' ?\n", (int)slen, sho, (int)llen, lon))
|
2011-04-16 11:13:57 +00:00
|
|
|
|
|
|
|
se = sho+slen;
|
|
|
|
le = lon+llen;
|
2011-04-20 16:59:27 +00:00
|
|
|
sho++; lon++; slen--; llen--;
|
|
|
|
while(*sho && sho < se) {
|
2011-04-30 13:44:12 +00:00
|
|
|
P3(("# comparing short '%.*s' (%d)\n", (int)slen, sho, (int)slen))
|
2011-04-20 16:59:27 +00:00
|
|
|
unless (s = memchr(sho, '_', slen)) s = se;
|
2011-04-30 13:44:12 +00:00
|
|
|
P4(("# sho goes '%c' and lon goes '%c'\n", *sho, (int)*lon))
|
2011-04-20 16:59:27 +00:00
|
|
|
while(*lon && lon < le) {
|
2011-04-30 13:44:12 +00:00
|
|
|
P3(("# against long '%.*s' (%d)\n", (int)llen, lon, (int)llen))
|
2011-04-20 16:59:27 +00:00
|
|
|
unless (l = memchr(lon, '_', llen)) l = le;
|
2011-04-30 13:44:12 +00:00
|
|
|
P3(("# %ld == %ld && !strncmp '%.*s', '%.*s'\n", s-sho, l-lon, (int)(s-sho), sho, (int)(s-sho), lon))
|
2011-04-20 16:59:27 +00:00
|
|
|
if (l-lon == s-sho && !strncmp(sho, lon, s-sho)) goto foundone;
|
|
|
|
P4(("# failed\n"))
|
|
|
|
llen -= l-lon + 1;
|
2011-04-16 11:13:57 +00:00
|
|
|
lon = ++l;
|
|
|
|
}
|
|
|
|
goto failed;
|
|
|
|
foundone:
|
2011-04-30 13:44:12 +00:00
|
|
|
P3(("# found %ld of short '%.*s' and long '%.*s'\n", s-sho, (int)(s-sho), sho, (int)(s-sho), lon))
|
2011-04-20 16:59:27 +00:00
|
|
|
llen -= l-lon;
|
|
|
|
slen -= s-sho;
|
2011-04-16 11:13:57 +00:00
|
|
|
sho = ++s;
|
|
|
|
lon = ++l;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
failed:
|
2011-04-20 16:59:27 +00:00
|
|
|
P4(("No, they don't match.\n"))
|
2011-04-16 11:13:57 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-10-31 19:04:16 +00:00
|
|
|
/**
|
|
|
|
* Check if keyword is in array.
|
|
|
|
*
|
|
|
|
* @param array The array to search, should be ordered alphabetically.
|
|
|
|
* @param size Size of array.
|
|
|
|
* @param kw Keyword to look for.
|
|
|
|
* @param kwlen Length of keyword.
|
|
|
|
* @param inherit If true, look for any keyword inheriting from name,
|
|
|
|
otherwise only exact matches are returned.
|
|
|
|
* @param matching A temporary array used for keeping track of results.
|
|
|
|
* Should be the same size as the array we're searching.
|
|
|
|
*
|
|
|
|
* @return The value of the matched variable in the array.
|
|
|
|
*/
|
|
|
|
int psyc_in_array (const psycMatchVar *array, size_t size,
|
|
|
|
const char *kw, size_t kwlen,
|
|
|
|
psycBool inherit, int8_t *matching)
|
|
|
|
{
|
|
|
|
size_t cursor = 1;
|
|
|
|
uint8_t i, m = 0;
|
|
|
|
//memset(&matching, -1, sizeof matching);
|
|
|
|
|
|
|
|
if (kwlen < 2 || kw[0] != '_')
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// first find the keywords with matching length
|
|
|
|
for (i=0; i<size; i++)
|
|
|
|
if (kwlen == array[i].key.length ||
|
|
|
|
(inherit && kwlen > array[i].key.length && kw[array[i].key.length] == '_'))
|
|
|
|
matching[m++] = i;
|
|
|
|
|
|
|
|
matching[m] = -1; // mark the end of matching indexes
|
|
|
|
|
|
|
|
while (cursor < kwlen && matching[0] >= 0) {
|
|
|
|
for (i = m = 0; i < size; i++) {
|
|
|
|
if (matching[i] < 0)
|
|
|
|
break; // reached the end of possible matches
|
|
|
|
if (cursor < array[matching[i]].key.length &&
|
|
|
|
array[matching[i]].key.ptr[cursor] == kw[cursor])
|
|
|
|
matching[m++] = matching[i]; // found a match, update matching indexes
|
|
|
|
else if (cursor == array[matching[i]].key.length && kw[cursor] == '_')
|
|
|
|
return array[matching[0]].value; // _ after the end of a matching prefix
|
|
|
|
else if (array[matching[i]].key.ptr[cursor] > kw[cursor])
|
|
|
|
break; // passed the possible matches in alphabetical order in the array
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m < size)
|
|
|
|
matching[m] = -1; // mark the end of matching indexes
|
|
|
|
|
|
|
|
cursor++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return first match if found
|
|
|
|
return matching[0] >= 0 ? array[matching[0]].value : 0;
|
|
|
|
}
|
|
|
|
|
2011-04-16 15:30:03 +00:00
|
|
|
#ifdef CMDTOOL
|
2011-04-16 11:49:47 +00:00
|
|
|
int main(int argc, char **argv) {
|
|
|
|
if (argc != 3) {
|
|
|
|
printf("Usage: %s <short> <long>\n\nExample: %s _failure_delivery _failure_unsuccessful_delivery_death\n", argv[0], argv[0]);
|
|
|
|
return -1;
|
|
|
|
}
|
2011-04-25 21:40:38 +00:00
|
|
|
if (psyc_matches(argv[1], 0, argv[2], 0) == 0)
|
2011-04-20 21:08:20 +00:00
|
|
|
printf("Yes, %s matches %s!\n", argv[1], argv[2]);
|
2011-04-25 21:40:38 +00:00
|
|
|
if (psyc_inherits(argv[1], 0, argv[2], 0) == 0)
|
2011-04-20 21:08:20 +00:00
|
|
|
printf("Yes, %s inherits from %s!\n", argv[2], argv[1]);
|
2011-04-16 11:49:47 +00:00
|
|
|
}
|
|
|
|
#endif
|