Пример #1
0
/**
 * Takes delimiter tags and sets the delimiter for the parser.
 * 
 * @param sds tag  The tag 
 *
 * @retval sdsempty()  Emtpy sds string.
 */
static sds tag_delimiter(sds tag) 
{
	puts("tag_delimiter");
	printf("tag found: '%s'\n",tag);
	sds re = sdsempty();
	sds oldl = sdsdup(ldelim), oldr = sdsdup(rdelim);
	re = sdscatprintf(re, "(%s=\\S+)\\s+(\\S+=%s)", oldl, oldr);
	struct slre_cap caps[2];

	int i;

	if ((i = slre_match(re, tag, sdslen(tag), caps, 2)) > 0) {
		ldelim = sdscpylen(ldelim, caps[0].ptr, caps[0].len);
		rdelim = sdscpylen(rdelim, caps[1].ptr, caps[1].len);
				
		oldl = sdscatprintf(sdsempty(), "%s=", oldl);
		oldr = sdscatprintf(sdsempty(), "=%s", oldr);

		ldelim = sdsreplace(ldelim, oldl, NULL);
		rdelim = sdsreplace(rdelim, oldr, NULL);

		printf("ldelim: '%s'\n", ldelim);
		printf("rdelim: '%s'\n", rdelim);
	}
	printf("Matched:  %d\n",i);
	puts("free oldl); sdsfree(oldr); sdsfree(re");
	sdsfree(oldl); sdsfree(oldr); sdsfree(re);
	return sdsempty();
}
Пример #2
0
void handle_request(char* client_message, int sock) {
  struct slre_cap caps[4], params[2];
  parse_http_request(client_message, caps);

  char *path = malloc(caps[1].len + 1);
  memcpy(path, caps[1].ptr, caps[1].len);
  path[caps[1].len] = '\0';

  if (!slre_match("^/([a-z]+)/([a-z]+)", path, strlen(path), params, 2, 0) > 0) {
    printf("Error parsing [%s]\n", path);
    exit(1);
  } else {
    char *service = malloc(params[0].len + 1);
    memcpy(service, params[0].ptr, params[0].len);
    service[params[0].len] = '\0';

    char *username = malloc(params[1].len + 1);
    memcpy(username, params[1].ptr, params[1].len);
    username[params[1].len] = '\0';
    char *image_url;


    if (strcmp(service, "instagram") == 0) {
      image_url = get_instagram_url_for(username);
    } else if (strcmp(service, "facebook") == 0) {
      image_url = get_facebook_url_for(username);
    } else if (strcmp(service, "twitter") == 0) {
      image_url = get_twitter_url_for(username);
    } else if (strcmp(service, "gravatar") == 0) {
      image_url = get_gravatar_url_for(username);
    }

    download_jpeg(image_url, sock);
  }
}
Пример #3
0
void parse_http_request(char* request, struct slre_cap *caps) {
  if (!slre_match("^\\s*(\\S+)\\s+(\\S+)\\s+HTTP/(\\d)\\.(\\d)",
                 request, strlen(request), caps, 4, 0) > 0) {
    printf("Error parsing [%s]\n", request);
    exit(1);
  }
}
Пример #4
0
/**
 * Wrapper for slre_match that returns all matches as an array.
 * 
 * @param const char *re  The regular expression to be matched.
 * @param const char *buf  The buffer to search in.
 * @param int bl  Length of buffer.
 * @param struct slre_cap *caps  Array to store subpatterns in.
 * @param int num_caps  Number of subpatterns in regular expression.
 *
 * @retval struct slre_cap*  Array of slre_cap structures.
 */
static struct slre_cap* slre_match_all(
		const char *re, 
		const char *buf, 
		int bl,
		struct slre_cap *caps, 
		int num_caps) 
{
	puts("slre_match_all");
	
	int count = 0, i = 0, j = 0;
	
	struct slre_cap* buffer;
	buffer = (struct slre_cap*)malloc(1024*sizeof(struct slre_cap)); 

	while (j < bl && 
		(i = slre_match(re, buf+j, bl-j, caps, num_caps)) > 0) {
		
		buffer[count]=caps[0];
		count++; j += i;
	}

	struct slre_cap *res = 
		(struct slre_cap*)malloc(count*sizeof(struct slre_cap));
	
	for (i=0; i<count; i++) {
		res[i] = buffer[i];
	}

	free((void*) buffer);

	return res;
}
Пример #5
0
int main(int argc, char **argv)
{
    Stopif(argc < 2, "Supply bignum value in argv[1]!\n");

    slre_cap SlreCaps[3];
    u8 InputBuffer[128];

    i32 MatchedStringLength = slre_match("((\\d|[a-f])*)",
                                         argv[1],
                                         strlen(argv[1]),
                                         SlreCaps,
                                         ARRAY_LENGTH(SlreCaps),
                                         SLRE_IGNORE_CASE);
    if (MatchedStringLength > 0)
    {
        Stopif(SlreCaps[0].len % 2, "Invalid hex digit match!\n");

        HexStringToByteArray(InputBuffer, (char *)SlreCaps[0].ptr, SlreCaps[0].len);

        u32 InputBuffLengthBytes = MatchedStringLength/2;
        ByteSwap(InputBuffer, InputBuffLengthBytes);

        for (u32 ArrayIndex = 0;
             ArrayIndex < InputBuffLengthBytes;
             ++ArrayIndex)
        {
            printf("0x%02x, ", InputBuffer[ArrayIndex]);
        }

        printf("\n");
    }
}
Пример #6
0
/* Regex must have exactly one bracket pair */
static char *slre_replace(const char *regex, const char *buf,
                          const char *sub) {
  char *s = NULL;
  int n, n1, n2, n3, s_len, len = strlen(buf);
  struct slre_cap cap = { NULL, 0 };

  do {
    s_len = s == NULL ? 0 : strlen(s);
    if ((n = slre_match(regex, buf, len, &cap, 1)) > 0) {
      n1 = cap.ptr - buf, n2 = strlen(sub),
         n3 = &buf[n] - &cap.ptr[cap.len];
    } else {
      n1 = len, n2 = 0, n3 = 0;
    }
    s = (char *) realloc(s, s_len + n1 + n2 + n3 + 1);
    memcpy(s + s_len, buf, n1);
    memcpy(s + s_len + n1, sub, n2);
    memcpy(s + s_len + n1 + n2, cap.ptr + cap.len, n3);
    s[s_len + n1 + n2 + n3] = '\0';

    buf += n > 0 ? n : len;
    len -= n > 0 ? n : len;
  } while (len > 0);

  return s;
}
Пример #7
0
/**
 * Takes partial tags and replaces them with a parsed partial template.
 * 
 * @param sds tag  The tag 
 *
 * @retval sds buff  Partial template buffer.
 */
static sds tag_partial(sds tag) 
{
	puts("tag_partial");
	printf("tag found: '%s'\n",tag);
	sds re = sdsempty();
	sds f = sdsempty();
	sds buff = sdsempty();

	re = sdscatprintf(re, "%s>([^}]+)%s", ldelim, rdelim);
	struct slre_cap caps[1];

	if (slre_match(re, tag, strlen(tag), caps, 1) > 0) {
		f = sdscatprintf(f,"%.*s", caps[0].len, caps[0].ptr);
		sdstrim(f," ");
		sds fname = sdscatprintf(sdsempty(),"%s%s", tpldir, f);
		fname = sdscat(fname,tplext);
		//puts(fname);

		FILE * fp;
		if ((fp = fopen(fname, "r")) != NULL) {
			fclose(fp);
			buff = render_template(f);
		}
		puts("free fname");
		sdsfree(fname);
		
	} 
	puts("free f");
	sdsfree(f);
//	//sdsfree(buff);
	puts("free re");
	sdsfree(re);
	return buff;
}
Пример #8
0
static int match_string(int flag, const char *str, const char *pat, void *priv)
{
	switch (flag & H_MATCH_METHOD) {
	case H_MATCH_IDENT:
		if (strcmp(str, pat) == 0)
			return 1;
		break;
	case H_MATCH_SUBSTR:
		if (strstr(str, pat))
			return 1;
		break;
#ifdef CONFIG_REGEX
	case H_MATCH_REGEX:
		{
			struct slre *slrep = (struct slre *)priv;
			struct cap caps[slrep->num_caps + 2];

			if (slre_match(slrep, str, strlen(str), caps))
				return 1;
		}
		break;
#endif
	default:
		printf("## ERROR: unsupported match method: 0x%02x\n",
			flag & H_MATCH_METHOD);
		break;
	}
	return 0;
}
Пример #9
0
int my_bind_cr(int count, int key) {
    struct slre_cap caps[4];
    if (my_eoq == 1 || slre_match("(\\\\G|;)\\s*$", rl_line_buffer, strlen(rl_line_buffer), caps, 4, SLRE_IGNORE_CASE) > 0){
        rl_done = 1;
        return 1;
    } else if( slre_match("^(\\\\q|exit)$", rl_line_buffer, strlen(rl_line_buffer), caps, 4, 0) > 0) {
        rl_done = 1;exit_flag=1;
        return 1;
    }
    if (strcmp( rl_line_buffer , "") == 0 || slre_match("^\\s+$", rl_line_buffer, strlen(rl_line_buffer), caps, 4, 0) > 0) {
        printf("\n");
        rl_on_new_line();
    }else{
        rl_insert_text(" \n");
    }
    return 1;
}
Пример #10
0
Файл: string.c Проект: mwanna/v7
static void Str_split(struct v7_c_func_arg *cfa) {
  const struct v7_string *s = &cfa->this_obj->v.str;
  const char *p1, *p2, *e = s->buf + s->len;
  int limit = cfa->num_args == 2 && cfa->args[1]->type == V7_TYPE_NUM ?
  cfa->args[1]->v.num : -1;
  int num_elems = 0;

  v7_set_class(cfa->result, V7_CLASS_ARRAY);
  if (cfa->num_args == 0) {
    v7_append(cfa->v7, cfa->result,
              v7_mkv(cfa->v7, V7_TYPE_STR, s->buf, s->len, 1));
  } else if (cfa->args[0]->type == V7_TYPE_STR) {
    const struct v7_string *sep = &cfa->args[0]->v.str;
    if (sep->len == 0) {
      // Separator is empty. Split string by characters.
      for (p1 = s->buf; p1 < e; p1++) {
        if (limit >= 0 && limit <= num_elems) return;
        v7_append(cfa->v7, cfa->result, v7_mkv(cfa->v7, V7_TYPE_STR, p1, 1, 1));
        num_elems++;
      }
    } else {
      p1 = s->buf;
      while ((p2 = memstr(p1, e - p1, sep->buf, sep->len)) != NULL) {
        if (limit >= 0 && limit <= num_elems) return;
        v7_append(cfa->v7, cfa->result,
                  v7_mkv(cfa->v7, V7_TYPE_STR, p1, p2 - p1, 1));
        p1 = p2 + sep->len;
        num_elems++;
      }
      if (limit < 0 || limit > num_elems) {
        v7_append(cfa->v7, cfa->result,
                  v7_mkv(cfa->v7, V7_TYPE_STR, p1, e - p1, 1));
      }
    }
  } else if (instanceof(cfa->args[0], &s_constructors[V7_CLASS_REGEXP])) {
    char regex[200];
    struct slre_cap caps[20];
    int n = 0;

    snprintf(regex, sizeof(regex), "(%s)", cfa->args[0]->v.regex);
    p1 = s->buf;
    while ((n = slre_match(regex, p1, e - p1, caps, ARRAY_SIZE(caps), 0)) > 0) {
      if (limit >= 0 && limit <= num_elems) return;
      v7_append(cfa->v7, cfa->result,
                v7_mkv(cfa->v7, V7_TYPE_STR, p1, caps[0].ptr - p1, 1));
      p1 += n;
      num_elems++;
    }
    if (limit < 0 || limit > num_elems) {
      v7_append(cfa->v7, cfa->result,
                v7_mkv(cfa->v7, V7_TYPE_STR, p1, e - p1, 1));
    }
  }
}
Пример #11
0
/********************************************************************
  parseCmds loops through a list of hear functions and tries to match queries 
  and execute reply response functions

********************************************************************/
void ArduinoSlackBot::parseCmds() {

  struct slre_cap matches[4];

  //you must reference the bot to get a response
  if (slre_match(botID, slackMsg.text, strlen(slackMsg.text), matches, 4, 0) > 0) {
    PRINTLN(ESP.getFreeHeap());

    for (int i=0; i <= qrListLength-1; i++) {
     
      //match the provided regex
      if (slre_match(qrList[i]->query, slackMsg.text, strlen(slackMsg.text), matches, 4, 0) > 0) {  
        PRINTLN(matches[0].ptr);
        qrList[i]->resp(); //execute provided bot response
        return; //stop matching if match is found
      } 
    }
    replyMsg(failMsg);
  }
  
}
Пример #12
0
Файл: slre.c Проект: ks07/beebs
int benchmark()
{
  int i;
  int len = strlen(text);
  struct slre_cap captures;
  volatile int ret=0;

  for(i = 0; i < 4; ++i)
  {
    ret += slre_match(regexes[i], text, len, &captures, 1);
  }

  return ret;
}
static int match_re(string source, int start, struct slre_cap* groups, string* match_start){
    int len = strlen(source) - start;

    struct slre_cap groups_with_doc[2];
    struct slre_cap groups_without_doc[2];

    int withdoc = slre_match(RE_PUBLIC_DOC, source + start, len, groups_with_doc, 2, 0);
    int withoutdoc = slre_match(RE_PUBLIC, source + start, len, groups_without_doc, 2, 0);


    if ((0 <= withdoc && 0 > withoutdoc)
            || (0 <= withdoc
                && groups_with_doc[0].ptr < groups_without_doc[0].ptr))
    {
        //With doc
        groups[0].ptr = groups_with_doc[0].ptr;
        groups[0].len = groups_with_doc[0].len;
        groups[1].ptr = groups_with_doc[1].ptr;
        groups[1].len = groups_with_doc[1].len;
        *match_start = (string) groups[0].ptr;
        return withdoc;
    }
    else if ((0 <= withoutdoc && 0 > withdoc)
            || (0 <= withoutdoc
                && groups_without_doc[0].ptr < groups_with_doc[0].ptr))
    {
        //Without doc
        groups[0].ptr = NULL;
        groups[0].len = 0;
        groups[1].ptr = groups_without_doc[1].ptr;
        groups[1].len = groups_without_doc[1].len;
        *match_start = (string) groups_without_doc[0].ptr;
        return withoutdoc;
    } else {
        return -1;
    }
}
Пример #14
0
/*
* Check if "requestLine" is a bad request
* 		Uses a regular expression library see --> https://github.com/cesanta/slre
*/
bool isBadRequest(char* requestLine)
{
	bool isBad = false;
		
	struct slre_cap caps[4];

	if (slre_match("^\\s*(\\S+)\\s+(\\S+)\\s+HTTP/(\\d)\\.(\\d)",
				   requestLine, strlen(requestLine), caps, 4, 0) <= 0) {
		isBad = true;
	}else{
		//printf("Method: [%.*s], URI: [%.*s]\n",caps[0].len, caps[0].ptr,caps[1].len, caps[1].ptr);
	}
	
	return isBad;
}
Пример #15
0
std::vector<std::string>
NP::Regex::match_groups(const std::string &re, const std::string &string, int ncaps, int flags)
{
    std::vector<std::string> result;
    slre_cap *caps = new slre_cap[ncaps];

    if (slre_match(re.c_str(), string.c_str(), string.length(), caps, ncaps, flags) > 0) {
        for (int i=0; i<ncaps; i++) {
            result.push_back(std::string(caps[i].ptr, caps[i].len));
        }
    }

    delete [] caps;
    return result;
}
Пример #16
0
int re_match( int nPossCaptures, struct cap* captures, char* mExpression, char* mString )
{
	struct slre	slre;
	int len    = strlen(mString);
	init_captures(nPossCaptures, captures);
	
	if (!slre_compile(&slre, mExpression )) {
		printf("Error compiling RE: %s\n", slre.err_str);	
		return 0;		
	}
	else if (slre_match(&slre, mString, len, captures)) {
		return 1;
	} 
	else 
		return 0;
}
Пример #17
0
/**
 * Wrapper for slre_match that counts the matches.
 * 
 * @param const char *re  The regular expression to be matched.
 * @param const char *buf  The buffer to search in.
 * @param int bl  Length of buffer.
 * @param struct slre_cap *caps  Array to store subpatterns in.
 * @param int num_caps  Number of subpatterns in regular expression.
 *
 * @retval int count  The number of matches in regular expression.
 */
static int slre_match_count(
		const char *re, 
		const char *buf, 
		int bl,
		struct slre_cap *caps, 
		int num_caps) 
{
	puts("slre_match_count");
	
	int count = 0, i = 0, j = 0;
	
	while (j < bl && 
		(i = slre_match(re, buf+j, bl-j, caps, num_caps)) > 0) {
		count++;
		j += i;
	}
	return count;
}
Пример #18
0
int pedirStringConFormato(char* dato,char* formato,char* msg, int max, int min, char*errorMsg)
{
    char buff[4000];
    struct slre_cap caps[4];
    short int hayError = 0;
    short int continuar = 1;
    do
    {
        hayError = 0;
        printf("%s",msg);
        fflush(stdin);
        scanf("%[a-zA-Z0-9 ]",buff);

        if (slre_match(formato,buff, strlen(buff), caps, 4, 0) == SLRE_NO_MATCH)
        {
            printf("No cumple el formato\n");
            hayError = 1;
        }

        if(strlen(buff) > max)
        {
            hayError = 1;
        }
        if(!hayError && strlen(buff) < min)
        {
            hayError = 1;
        }

        if(hayError)
        {
            printf("%s",errorMsg);
            continuar = confirmacionSinReintentos("Desea intentar otra vez?\n",'s','n');
        }
    }while(continuar && hayError);
    if(!hayError)
    {
        strcpy(dato,buff);
        return 0;
    }
    return -1;
}
Пример #19
0
bool
zrex_matches (zrex_t *self, const char *text)
{
    assert (self);
    assert (text);

    //  Free any previously-allocated hits
    self->hits = 0;

    bool matches = slre_match (&self->slre, text, strlen (text), self->caps) != 0;
    if (matches) {
        //  Count number of captures plus whole string
        self->hits = self->slre.num_caps + 1;
        if (self->hits > MAX_HITS)
            self->hits = MAX_HITS;

        //  Collect hits and prepare hit array, which is a single block of
        //  memory holding all hits as null-terminated strings
        uint index;
        //  First count total length of hit strings
        size_t hit_set_len = 0;
        for (index = 0; index < self->hits; index++)
            hit_set_len += self->caps [index].len + 1;
        if (hit_set_len > self->hit_set_len) {
            zstr_free (&self->hit_set);
            self->hit_set = (char *) zmalloc (hit_set_len);
            self->hit_set_len = hit_set_len;
        }
        // FIXME: no way to return an error
        assert (self->hit_set);

        //  Now prepare hit strings for access by caller
        char *hit_set_ptr = self->hit_set;
        for (index = 0; index < self->hits; index++) {
            memcpy (hit_set_ptr, self->caps [index].ptr, self->caps [index].len);
            self->hit [index] = hit_set_ptr;
            hit_set_ptr += self->caps [index].len + 1;
        }
    }
    return matches;
}
Пример #20
0
Файл: string.c Проект: mwanna/v7
static void Str_match(struct v7_c_func_arg *cfa) {
  struct slre_cap caps[100];
  const struct v7_string *s = &cfa->this_obj->v.str;
  int i, n;

  cfa->result->type = V7_TYPE_NULL;
  memset(caps, 0, sizeof(caps));

  if (cfa->num_args == 1 &&
      v7_is_class(cfa->args[0], V7_CLASS_REGEXP) &&
      (n = slre_match(cfa->args[0]->v.regex, s->buf, s->len,
                      caps, ARRAY_SIZE(caps) - 1, 0)) > 0) {
    v7_set_class(cfa->result, V7_CLASS_ARRAY);
    v7_append(cfa->v7, cfa->result,
              v7_mkv(cfa->v7, V7_TYPE_STR, s->buf, (long) n, 1));
    for (i = 0; i < (int) ARRAY_SIZE(caps); i++) {
      if (caps[i].len == 0) break;
      v7_append(cfa->v7, cfa->result,
                v7_mkv(cfa->v7, V7_TYPE_STR, caps[i].ptr, (long) caps[i].len, 1));
    }
  }
}
Пример #21
0
int mapper_get_mapperid_unif(char *str)
{
	int ret,i;
	const char *err;
	char tmpstr[4][256];

	ret = B_UNSUPPORTED;
	for(i=0;boards[i].boardid != -1;i++) {
		err = slre_match(SLRE_CASE_INSENSITIVE,boards[i].name,str,strlen(str),
			SLRE_STRING,sizeof(tmpstr[0]),tmpstr[0],
			SLRE_STRING,sizeof(tmpstr[1]),tmpstr[1],
			SLRE_STRING,sizeof(tmpstr[2]),tmpstr[2],
			SLRE_STRING,sizeof(tmpstr[3]),tmpstr[3]);
		if(err == NULL) {
			if(ret != B_UNSUPPORTED)
				log_printf("mapper_get_mapperid_unif:  duplicate match for board '%s'\n",str);
			ret = boards[i].boardid;
		}
		else if(stricmp(err,"no match") != 0)
			log_printf("mapper_get_mapperid_unif:  slre error:  %s ('%s' -- '%s')\n",err,boards[i].name,str);
	}
	return(ret);
}
Пример #22
0
static int32_t command_matches (const char *input,
                                char *output,
                                uint8_t show_ambiguous,
                                uint8_t show_complete,
                                uint8_t execute_command,
                                void *context)
{
    char cand_expand_to[MAXSTR];
    command_t *matched_command;
    char completes_to[MAXSTR];
    char expands_to[MAXSTR];
    tokens_t input_tokens;
    char match[MAXSTR];
    char match2[MAXSTR];
    int32_t longest_match;
    int32_t common_len;
    command_t *command;
    int32_t matches;
    int32_t cnt;
    int32_t t;

    matched_command = 0;
    longest_match = -1;
    matches = 0;

    /*
     * Convert the input into tokens for matching.
     */
    tokens_tostring(input, &input_tokens);

    /*
     * Find the command(s) with the most number of matching tokens.
     */
    TREE_WALK(commands, command) {

        for (t = 0; t < (int32_t)min(command->tokens.cnt,
                                     input_tokens.cnt); t++) {

            cnt = strncmp(command->tokens.args[t],
                          input_tokens.args[t],
                          strlen(input_tokens.args[t]));

            if (slre_match(&command->tokens.regexp[t],
                           input_tokens.args[t],
                           (int) strlen(input_tokens.args[t]),
                           0 /* captures */)) {
                /*
                 * Success
                 */
                cnt = 0;
            }

            if (cnt) {
                t = -1;
                break;
            }
        }

        longest_match = max(t, longest_match);
    }

    if (longest_match == -1) {
        return (0);
    }

    /*
     * Repeat and optionally dump other possibilities if the command is
     * not complete.
     */
    { TREE_WALK(commands, command) {

        for (t = 0; t < (int32_t)min(command->tokens.cnt,
                                     input_tokens.cnt); t++) {

            cnt = strncmp(command->tokens.args[t],
                          input_tokens.args[t],
                          strlen(input_tokens.args[t]));

            if (slre_match(&command->tokens.regexp[t],
                           input_tokens.args[t],
                           (int) strlen(input_tokens.args[t]),
                           0 /* captures */)) {
                /*
                 * Success
                 */
                cnt = 0;
            }

            if (cnt) {
                break;
            }
        }

// tokens_print_to(&command->readable_tokens, match, sizeof(match));
        if (t == longest_match) {
            matches++;
// CON("  MATCH    \"%s\" [%d] longest %d", match,t,longest_match);

            matched_command = command;

            if (show_complete) {
                completes_to[0] = '\0';

                for (t = 0; t < longest_match; t++) {
                    strlcat(completes_to, command->tokens.args[t],
                            sizeof(completes_to));
                    strlcat(completes_to, " ", sizeof(completes_to));
                }

                if (output) {
                    strlcpy(output, completes_to, MAXSTR);
                }
            }

            tokens_print_to(&command->input_tokens, match, sizeof(match));

            tokens_print_to(&command->readable_tokens, match2, sizeof(match2));

            if (show_ambiguous) {
                CON("  %-40s -- %s", match, match2);
            }
        } else {
// CON("  NO MATCH \"%s\" [%d] longest %d", match,t,longest_match);
        }
    } }

    /*
     * Repeat and complete the command to any full matches.
     */
    {
        expands_to[0] = '\0';

        {
            TREE_WALK(commands, command) {

                for (t = 0; t < (int32_t)min(command->tokens.cnt,
                                            input_tokens.cnt);
                    t++) {

                    cnt = strncmp(command->tokens.args[t],
                                input_tokens.args[t],
                                strlen(input_tokens.args[t]));

                    if (slre_match(&command->tokens.regexp[t],
                                input_tokens.args[t],
                                (int) strlen(input_tokens.args[t]),
                                0 /* captures */)) {
                        /*
                         * Success
                         */
                        cnt = 0;
                    }

                    if (cnt) {
                        break;
                    }
                }

                if (t == longest_match) {
                    cand_expand_to[0] = '\0';

                    for (t = 0; t < longest_match; t++) {
                        if (strisregexp(command->tokens.args[t])) {
                            strlcat(cand_expand_to, input_tokens.args[t],
                                    sizeof(cand_expand_to));
                            strlcat(cand_expand_to, " ", sizeof(cand_expand_to));
                            continue;
                        }

                        strlcat(cand_expand_to, command->tokens.args[t],
                                sizeof(cand_expand_to));
                        strlcat(cand_expand_to, " ", sizeof(cand_expand_to));
                    }

                    if (expands_to[0] != '\0') {
                        common_len = strcommon(expands_to, cand_expand_to);
                        expands_to[common_len] = '\0';
                    } else {
                        strlcpy(expands_to, cand_expand_to,
                                sizeof(expands_to));
                    }
                }
            }

            /*
             * Expands to:
             */
            if (output) {
                strlcpy(output, expands_to, MAXSTR);
            }
        }
    }

    if (execute_command && matched_command && (matches == 1)) {
        (*matched_command->callback)(&input_tokens, context);
    }

    return (matches);
}
Пример #23
0
void _ortc_parse_message(ortc_context *context, char *message){
  char *messageId, *messageCount, *messageTotal, *messagePart, *channelNameStr, *messageStr, *params, *permissionsStr, *exceptionStr, *validateString, *operationType;
  struct cap pmatch[3], pmatch2[5];
  int iMessageTotal, wsSock, opt;
  size_t len, hbLen;
  ortc_dnode *ch;
  char hbStr[24];
  
  if(message[0] == 'a') {
    if (slre_match(&context->reMessage, message, (int)strlen(message), pmatch)) {         //is message   
      channelNameStr = _ortc_get_from_slre(1, pmatch);
      messageStr = _ortc_get_from_slre(2, pmatch);
      if(slre_match(&context->reMultipart, messageStr, (int)strlen(messageStr), pmatch2)){
		messageId =    _ortc_get_from_slre(1, pmatch2);
		messageCount = _ortc_get_from_slre(2, pmatch2);
		messageTotal = _ortc_get_from_slre(3, pmatch2);
		messagePart =  _ortc_get_from_slre(4, pmatch2);
		iMessageTotal = atoi(messageTotal);
		if(iMessageTotal > 1){ //multipart message
			_ortc_dlist_insert(context->multiparts, messageId, channelNameStr, messagePart, atoi(messageCount), NULL);
		_ortc_check_if_got_all_parts(context, messageId, iMessageTotal);
		} else {
			_ortc_fire_onMessage(context, channelNameStr, messagePart);
		}
		free(messageId);
		free(messageCount);
		free(messageTotal);
		free(messagePart);
      } else {
        _ortc_fire_onMessage(context, channelNameStr, messageStr);
      }
      free(channelNameStr);
      free(messageStr);
    } else if (slre_match(&context->reOperation, message, (int)strlen(message), pmatch)) {
      params = _ortc_get_from_slre(2, pmatch);
      operationType = _ortc_get_from_slre(1, pmatch);
      if(strncmp(operationType, "ortc-validated", 14)==0){
		if(slre_match(&context->rePermissions, params, (int)strlen(params), pmatch2)){
			permissionsStr = _ortc_get_from_slre(1, pmatch2);
			_ortc_save_permissions(context, permissionsStr);
			free(permissionsStr);
		}
		_ortc_change_state(context, CONNECTED);
		
      } else if(strncmp(operationType, "ortc-subscribed", 15)==0){
	if(slre_match(&context->reChannel, params, (int)strlen(params), pmatch2)){
	  channelNameStr = _ortc_get_from_slre(1, pmatch2);
	  ch = _ortc_dlist_search(context->channels, channelNameStr);
	  if(ch != NULL)
	    ch->num += 2; //isSubscribed
	  if(context->onSubscribed != NULL)
	    context->onSubscribed(context, channelNameStr);	  
	  free(channelNameStr);
	}
      } else if(strncmp(operationType, "ortc-unsubscribed", 17)==0){
	if(slre_match(&context->reChannel, params, (int)strlen(params), pmatch2)){
	  channelNameStr = _ortc_get_from_slre(1, pmatch2);
	  _ortc_dlist_delete(context->channels, channelNameStr);
	  if(context->onUnsubscribed != NULL)
	    context->onUnsubscribed(context, channelNameStr);
	  free(channelNameStr);
	}
      } else if(strncmp(operationType, "ortc-error", 10)==0){
	if(slre_match(&context->reException, params, (int)strlen(params), pmatch2)){
		_ortc_cancel_connecting(context);
		exceptionStr = _ortc_get_from_slre(1, pmatch2);
		_ortc_exception(context, exceptionStr);
		free(exceptionStr);
	}
      }
      free(params);
      free(operationType);
    }

  } else if(message[0] == 'o' && strlen(message)==1){
    wsSock = libwebsocket_get_socket_fd(context->wsi);
    opt = ORTC_SNDBUF_SIZE;
    setsockopt(wsSock, SOL_SOCKET, SO_SNDBUF, (const char*)&opt, sizeof(opt));
	
	
	if(context->heartbeatActive){
		snprintf(hbStr, sizeof(hbStr), "%d;%d;", context->heartbeatTime, context->heartbeatFails);
		hbLen = strlen(hbStr);
	} else {
		hbLen = 0;
	}
    len = 17 + strlen(context->appKey) +  strlen(context->authToken) + strlen(context->announcementSubChannel) + strlen(context->sessionId) + strlen(context->metadata) + hbLen;
	
    validateString = malloc(len+1);
    if(validateString == NULL){
      _ortc_exception(context, "malloc() failed in ortc parese message");
      return;
    }
	if(context->heartbeatActive)
		snprintf(validateString, len, "\"validate;%s;%s;%s;%s;%s;%s\"", context->appKey, context->authToken, context->announcementSubChannel, context->sessionId, context->metadata, hbStr);
	else
		snprintf(validateString, len, "\"validate;%s;%s;%s;%s;%s;\"", context->appKey, context->authToken, context->announcementSubChannel, context->sessionId, context->metadata);
    _ortc_send_command(context, validateString);
	
  } else if(strncmp(message, "c[1000,\"Normal closure\"]", 20)==0){
	_ortc_exception(context, "Server is about to close the websocket!");
  }
}
Пример #24
0
bool static isVertexShader(char const* str) {
  return slre_match(&moduleData.vertexShaderDetectRegex, str, strlen(str), NULL);
}
Пример #25
0
int main(void) {
  struct slre_cap caps[10];

  /* Metacharacters */
  ASSERT(slre_match("$", "abcd", 4, NULL, 0) == 4);
  ASSERT(slre_match("^", "abcd", 4, NULL, 0) == 0);
  ASSERT(slre_match("x|^", "abcd", 4, NULL, 0) == 0);
  ASSERT(slre_match("x|$", "abcd", 4, NULL, 0) == 4);
  ASSERT(slre_match("x", "abcd", 4, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match(".", "abcd", 4, NULL, 0) == 1);
  ASSERT(slre_match("(?i)^.*\\\\.*$", "c:\\Tools", 8, NULL, 0) == 8);
  ASSERT(slre_match("\\", "a", 1, NULL, 0) == SLRE_INVALID_METACHARACTER);
  ASSERT(slre_match("\\x", "a", 1, NULL, 0) == SLRE_INVALID_METACHARACTER);
  ASSERT(slre_match("\\x1", "a", 1, NULL, 0) == SLRE_INVALID_METACHARACTER);
  ASSERT(slre_match("\\x20", " ", 1, NULL, 0) == 1);

  ASSERT(slre_match("^.+$", "", 0, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match("^(.+)$", "", 0, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match("(?i)^([\\+-]?)([\\d]+)$", "+", 1,
                    caps, 10) == SLRE_NO_MATCH);
  ASSERT(slre_match("(?i)^([\\+-]?)([\\d]+)$", "+27", 3,
                    caps, 10) == 3);
  ASSERT(caps[0].len == 1);
  ASSERT(caps[0].ptr[0] == '+');
  ASSERT(caps[1].len == 2);
  ASSERT(memcmp(caps[1].ptr, "27", 2) == 0);

  ASSERT(slre_match("tel:\\+(\\d+[\\d-]+\\d)",
                    "tel:+1-201-555-0123;a=b", 23, caps, 10) == 19);
  ASSERT(caps[0].len == 14);
  ASSERT(memcmp(caps[0].ptr, "1-201-555-0123", 14) == 0);

  /* Character sets */
  ASSERT(slre_match("[abc]", "1c2", 3, NULL, 0) == 2);
  ASSERT(slre_match("[abc]", "1C2", 3, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match("(?i)[abc]", "1C2", 3, NULL, 0) == 2);
  ASSERT(slre_match("[.2]", "1C2", 3, NULL, 0) == 1);
  ASSERT(slre_match("[\\S]+", "ab cd", 5, NULL, 0) == 2);
  ASSERT(slre_match("[\\S]+\\s+[tyc]*", "ab cd", 5, NULL, 0) == 4);
  ASSERT(slre_match("[\\d]", "ab cd", 5, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match("[^\\d]", "ab cd", 5, NULL, 0) == 1);
  ASSERT(slre_match("[^\\d]+", "abc123", 6, NULL, 0) == 3);
  ASSERT(slre_match("[1-5]+", "123456789", 9, NULL, 0) == 5);
  ASSERT(slre_match("[1-5a-c]+", "123abcdef", 9, NULL, 0) == 6);
  ASSERT(slre_match("[1-5a-]+", "123abcdef", 9, NULL, 0) == 4);
  ASSERT(slre_match("[1-5a-]+", "123a--2oo", 9, NULL, 0) == 7);
  ASSERT(slre_match("[htps]+://", "https://", 8, NULL, 0) == 8);
  ASSERT(slre_match("[^\\s]+", "abc def", 7, NULL, 0) == 3);
  ASSERT(slre_match("[^fc]+", "abc def", 7, NULL, 0) == 2);
  ASSERT(slre_match("[^d\\sf]+", "abc def", 7, NULL, 0) == 3);

  /* Flags - case sensitivity */
  ASSERT(slre_match("FO", "foo", 3, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match("(?i)FO", "foo", 3, NULL, 0) == 2);
  ASSERT(slre_match("(?m)FO", "foo", 3, NULL, 0) == SLRE_UNEXPECTED_QUANTIFIER);
  ASSERT(slre_match("(?m)x", "foo", 3, NULL, 0) == SLRE_UNEXPECTED_QUANTIFIER);

  ASSERT(slre_match("fo", "foo", 3, NULL, 0) == 2);
  ASSERT(slre_match(".+", "foo", 3, NULL, 0) == 3);
  ASSERT(slre_match(".+k", "fooklmn", 7, NULL, 0) == 4);
  ASSERT(slre_match(".+k.", "fooklmn", 7, NULL, 0) == 5);
  ASSERT(slre_match("p+", "fooklmn", 7, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match("ok", "fooklmn", 7, NULL, 0) == 4);
  ASSERT(slre_match("lmno", "fooklmn", 7, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match("mn.", "fooklmn", 7, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match("o", "fooklmn", 7, NULL, 0) == 2);
  ASSERT(slre_match("^o", "fooklmn", 7, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match("^", "fooklmn", 7, NULL, 0) == 0);
  ASSERT(slre_match("n$", "fooklmn", 7, NULL, 0) == 7);
  ASSERT(slre_match("n$k", "fooklmn", 7, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match("l$", "fooklmn", 7, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match(".$", "fooklmn", 7, NULL, 0) == 7);
  ASSERT(slre_match("a?", "fooklmn", 7, NULL, 0) == 0);
  ASSERT(slre_match("^a*CONTROL", "CONTROL", 7, NULL, 0) == 7);
  ASSERT(slre_match("^[a]*CONTROL", "CONTROL", 7, NULL, 0) == 7);
  ASSERT(slre_match("^(a*)CONTROL", "CONTROL", 7, NULL, 0) == 7);
  ASSERT(slre_match("^(a*)?CONTROL", "CONTROL", 7, NULL, 0) == 7);

  ASSERT(slre_match("\\_", "abc", 3, NULL, 0) == SLRE_INVALID_METACHARACTER);
  ASSERT(slre_match("+", "fooklmn", 7, NULL, 0) == SLRE_UNEXPECTED_QUANTIFIER);
  ASSERT(slre_match("()+", "fooklmn", 7, NULL, 0) == SLRE_NO_MATCH);
  ASSERT(slre_match("\\x", "12", 2, NULL, 0) == SLRE_INVALID_METACHARACTER);
  ASSERT(slre_match("\\xhi", "12", 2, NULL, 0) == SLRE_INVALID_METACHARACTER);
  ASSERT(slre_match("\\x20", "_ J", 3, NULL, 0) == 2);
  ASSERT(slre_match("\\x4A", "_ J", 3, NULL, 0) == 3);
  ASSERT(slre_match("\\d+", "abc123def", 9, NULL, 0) == 6);

  /* Balancing brackets */
  ASSERT(slre_match("(x))", "fooklmn", 7, NULL, 0) == SLRE_UNBALANCED_BRACKETS);
  ASSERT(slre_match("(", "fooklmn", 7, NULL, 0) == SLRE_UNBALANCED_BRACKETS);

  ASSERT(slre_match("klz?mn", "fooklmn", 7, NULL, 0) == 7);
  ASSERT(slre_match("fa?b", "fooklmn", 7, NULL, 0) == SLRE_NO_MATCH);

  /* Brackets & capturing */
  ASSERT(slre_match("^(te)", "tenacity subdues all", 20, caps, 10) == 2);
  ASSERT(slre_match("(bc)", "abcdef", 6, caps, 10) == 3);
  ASSERT(slre_match(".(d.)", "abcdef", 6, caps, 10) == 5);
  ASSERT(slre_match(".(d.)\\)?", "abcdef", 6, caps, 10) == 5);
  ASSERT(caps[0].len == 2);
  ASSERT(memcmp(caps[0].ptr, "de", 2) == 0);
  ASSERT(slre_match("(.+)", "123", 3, caps, 10) == 3);
  ASSERT(slre_match("(2.+)", "123", 3, caps, 10) == 3);
  ASSERT(caps[0].len == 2);
  ASSERT(memcmp(caps[0].ptr, "23", 2) == 0);
  ASSERT(slre_match("(.+2)", "123", 3, caps, 10) == 2);
  ASSERT(caps[0].len == 2);
  ASSERT(memcmp(caps[0].ptr, "12", 2) == 0);
  ASSERT(slre_match("(.*(2.))", "123", 3, caps, 10) == 3);
  ASSERT(slre_match("(.)(.)", "123", 3, caps, 10) == 2);
  ASSERT(slre_match("(\\d+)\\s+(\\S+)", "12 hi", 5, caps, 10) == 5);
  ASSERT(slre_match("ab(cd)+ef", "abcdcdef", 8, NULL, 0) == 8);
  ASSERT(slre_match("ab(cd)*ef", "abcdcdef", 8, NULL, 0) == 8);
  ASSERT(slre_match("ab(cd)+?ef", "abcdcdef", 8, NULL, 0) == 8);
  ASSERT(slre_match("ab(cd)+?.", "abcdcdef", 8, NULL, 0) == 5);
  ASSERT(slre_match("ab(cd)?", "abcdcdef", 8, NULL, 0) == 4);
  ASSERT(slre_match("a(b)(cd)", "abcdcdef", 8, caps, 1) ==
      SLRE_CAPS_ARRAY_TOO_SMALL);
  ASSERT(slre_match("(.+/\\d+\\.\\d+)\\.jpg$", "/foo/bar/12.34.jpg", 18,
                    caps, 1) == 18);
  ASSERT(slre_match("(ab|cd).*\\.(xx|yy)", "ab.yy", 5, NULL, 0) == 5);
  ASSERT(slre_match(".*a", "abcdef", 6, NULL, 0) == 1);
  ASSERT(slre_match("(.+)c", "abcdef", 6, NULL, 0) == 3);

  /* Greedy vs non-greedy */
  ASSERT(slre_match(".+c", "abcabc", 6, NULL, 0) == 6);
  ASSERT(slre_match(".+?c", "abcabc", 6, NULL, 0) == 3);
  ASSERT(slre_match(".*?c", "abcabc", 6, NULL, 0) == 3);
  ASSERT(slre_match(".*c", "abcabc", 6, NULL, 0) == 6);
  ASSERT(slre_match("bc.d?k?b+", "abcabc", 6, NULL, 0) == 5);

  /* Branching */
  ASSERT(slre_match("|", "abc", 3, NULL, 0) == 0);
  ASSERT(slre_match("|.", "abc", 3, NULL, 0) == 1);
  ASSERT(slre_match("x|y|b", "abc", 3, NULL, 0) == 2);
  ASSERT(slre_match("k(xx|yy)|ca", "abcabc", 6, NULL, 0) == 4);
  ASSERT(slre_match("k(xx|yy)|ca|bc", "abcabc", 6, NULL, 0) == 3);
  ASSERT(slre_match("(|.c)", "abc", 3, caps, 10) == 3);
  ASSERT(caps[0].len == 2);
  ASSERT(memcmp(caps[0].ptr, "bc", 2) == 0);
  ASSERT(slre_match("a|b|c", "a", 1, NULL, 0) == 1);
  ASSERT(slre_match("a|b|c", "b", 1, NULL, 0) == 1);
  ASSERT(slre_match("a|b|c", "c", 1, NULL, 0) == 1);
  ASSERT(slre_match("a|b|c", "d", 1, NULL, 0) == SLRE_NO_MATCH);

  /* Optional match at the end of the string */
  ASSERT(slre_match("^.*c.?$", "abc", 3, NULL, 0) == 3);
  ASSERT(slre_match("(?i)^.*C.?$", "abc", 3, NULL, 0) == 3);
  ASSERT(slre_match("bk?", "ab", 2, NULL, 0) == 2);
  ASSERT(slre_match("b(k?)", "ab", 2, NULL, 0) == 2);
  ASSERT(slre_match("b[k-z]*", "ab", 2, NULL, 0) == 2);
  ASSERT(slre_match("ab(k|z|y)*", "ab", 2, NULL, 0) == 2);
  ASSERT(slre_match("[b-z].*", "ab", 2, NULL, 0) == 2);
  ASSERT(slre_match("(b|z|u).*", "ab", 2, NULL, 0) == 2);
  ASSERT(slre_match("ab(k|z|y)?", "ab", 2, NULL, 0) == 2);
  ASSERT(slre_match(".*", "ab", 2, NULL, 0) == 2);
  ASSERT(slre_match(".*$", "ab", 2, NULL, 0) == 2);
  ASSERT(slre_match("a+$", "aa", 2, NULL, 0) == 2);
  ASSERT(slre_match("a*$", "aa", 2, NULL, 0) == 2);
  ASSERT(slre_match( "a+$" ,"Xaa", 3, NULL, 0) == 3);
  ASSERT(slre_match( "a*$" ,"Xaa", 3, NULL, 0) == 3);

  {
    /* Example: HTTP request */
    const char *request = " GET /index.html HTTP/1.0\r\n\r\n";
    struct slre_cap caps[4];

    if (slre_match("^\\s*(\\S+)\\s+(\\S+)\\s+HTTP/(\\d)\\.(\\d)",
                   request, strlen(request), caps, 4) > 0) {
      printf("Method: [%.*s], URI: [%.*s]\n",
             caps[0].len, caps[0].ptr,
             caps[1].len, caps[1].ptr);
    } else {
      printf("Error parsing [%s]\n", request);
    }

    ASSERT(caps[1].len == 11);
    ASSERT(memcmp(caps[1].ptr, "/index.html", caps[1].len) == 0);
  }

  {
    /* Example: string replacement */
    char *s = slre_replace("({{.+?}})",
                           "Good morning, {{foo}}. How are you, {{bar}}?",
                           "Bob");
    printf("%s\n", s);
    ASSERT(strcmp(s, "Good morning, Bob. How are you, Bob?") == 0);
    free(s);
  }

  {
    /* Example: find all URLs in a string */
    static const char *str =
      "<img src=\"HTTPS://FOO.COM/x?b#c=tab1\"/> "
      "  <a href=\"http://cesanta.com\">some link</a>";

    static const char *regex = "(?i)((https?://)[^\\s/'\"<>]+/?[^\\s'\"<>]*)";
    struct slre_cap caps[2];
    int i, j = 0, str_len = strlen(str);

    while (j < str_len &&
           (i = slre_match(regex, str + j, str_len - j, caps, 2)) > 0) {
      printf("Found URL: [%.*s]\n", caps[0].len, caps[0].ptr);
      j += i;
    }
  }

  printf("Unit test %s (total test: %d, failed tests: %d)\n",
         static_failed_tests > 0 ? "FAILED" : "PASSED",
         static_total_tests, static_failed_tests);

  return static_failed_tests == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
Пример #26
0
bool static isSingleFragmentShader(char const* str) {
  return slre_match(&moduleData.fragmentSingleShaderDetectRegex, str, strlen(str), NULL);
}
Пример #27
0
Файл: slre.c Проект: mamod/Lugex
int main(void) {
  const char *msg = "";
  struct slre_cap caps[10];

  /* Character sets */
  ASSERT(slre_match("[abc]", "1c2", 3, NULL, &msg) == 2);
  ASSERT(slre_match("[abc]", "1C2", 3, NULL, &msg) == 0);
  ASSERT(slre_match("(?i)[abc]", "1C2", 3, NULL, &msg) == 2);
  ASSERT(slre_match("[.2]", "1C2", 3, NULL, &msg) == 1);
  ASSERT(slre_match("[\\S]+", "ab cd", 5, NULL, &msg) == 2);
  ASSERT(slre_match("[\\S]+\\s+[tyc]*", "ab cd", 5, NULL, &msg) == 4);
  ASSERT(slre_match("[\\d]", "ab cd", 5, NULL, &msg) == 0);
  ASSERT(slre_match("[^\\d]", "ab cd", 5, NULL, &msg) == 1);
  ASSERT(slre_match("[^\\d]+", "abc123", 6, NULL, &msg) == 3);
  ASSERT(slre_match("[1-5]+", "123456789", 9, NULL, &msg) == 5);
  ASSERT(slre_match("[1-5a-c]+", "123abcdef", 9, NULL, &msg) == 6);
  ASSERT(slre_match("[1-5a-]+", "123abcdef", 9, NULL, &msg) == 4);
  ASSERT(slre_match("[1-5a-]+", "123a--2oo", 9, NULL, &msg) == 7);
  ASSERT(slre_match("[htps]+://", "https://", 8, NULL, &msg) == 8);

  /* Flags - case sensitivity */
  ASSERT(slre_match("FO", "foo", 3, NULL, &msg) == 0);
  ASSERT(slre_match("(?i)FO", "foo", 3, NULL, &msg) == 2);
  ASSERT(slre_match("(?m)FO", "foo", 3, NULL, &msg) == 0);
  ASSERT(slre_match("(?m)x", "foo", 3, NULL, &msg) == 0);
  ASSERT(strcmp(msg, static_error_unexpected_quantifier) == 0);

  ASSERT(slre_match("fo", "foo", 3, NULL, &msg) == 2);
  ASSERT(slre_match(".+", "foo", 3, NULL, &msg) == 3);
  ASSERT(slre_match(".+k", "fooklmn", 7, NULL, &msg) == 4);
  ASSERT(slre_match(".+k.", "fooklmn", 7, NULL, &msg) == 5);
  ASSERT(slre_match("p+", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(slre_match("ok", "fooklmn", 7, NULL, &msg) == 4);
  ASSERT(slre_match("lmno", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(slre_match("mn.", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(slre_match("o", "fooklmn", 7, NULL, &msg) == 2);
  ASSERT(slre_match("^o", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(slre_match("^", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(slre_match("n$", "fooklmn", 7, NULL, &msg) == 7);
  ASSERT(slre_match("n$k", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(slre_match("l$", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(slre_match(".$", "fooklmn", 7, NULL, &msg) == 7);
  ASSERT(slre_match("a?", "fooklmn", 7, NULL, &msg) == 0);

  ASSERT(slre_match("\\_", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(strcmp(msg, static_error_invalid_metacharacter) == 0);
  ASSERT(slre_match("+", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(strcmp(msg, static_error_unexpected_quantifier) == 0);
  ASSERT(slre_match("()+", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(strcmp(msg, static_error_no_match) == 0);
  ASSERT(slre_match("\\x", "12", 2, NULL, &msg) == 0);
  ASSERT(strcmp(msg, static_error_invalid_metacharacter) == 0);
  ASSERT(slre_match("\\xhi", "12", 2, NULL, &msg) == 0);
  ASSERT(strcmp(msg, static_error_invalid_metacharacter) == 0);
  ASSERT(slre_match("\\x20", "_ J", 3, NULL, &msg) == 2);
  ASSERT(slre_match("\\x4A", "_ J", 3, NULL, &msg) == 3);
  ASSERT(slre_match("\\d+", "abc123def", 9, NULL, &msg) == 6);

  /* Balancing brackets */
  ASSERT(slre_match("(x))", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(strcmp(msg, static_error_unbalanced_brackets) == 0);
  ASSERT(slre_match("(", "fooklmn", 7, NULL, &msg) == 0);
  ASSERT(strcmp(msg, static_error_unbalanced_brackets) == 0);

  ASSERT(slre_match("klz?mn", "fooklmn", 7, NULL, &msg) == 7);
  ASSERT(slre_match("fa?b", "fooklmn", 7, NULL, &msg) == 0);

  /* Brackets & capturing */
  ASSERT(slre_match("^(te)", "tenacity subdues all", 20, caps, &msg) == 2);
  ASSERT(slre_match("(bc)", "abcdef", 6, caps, &msg) == 3);
  ASSERT(slre_match(".(d.)", "abcdef", 6, caps, &msg) == 5);
  ASSERT(slre_match(".(d.)\\)?", "abcdef", 6, caps, &msg) == 5);
  ASSERT(caps[0].len == 2);
  ASSERT(memcmp(caps[0].ptr, "de", 2) == 0);
  ASSERT(slre_match("(.+)", "123", 3, caps, &msg) == 3);
  ASSERT(slre_match("(2.+)", "123", 3, caps, &msg) == 3);
  ASSERT(caps[0].len == 2);
  ASSERT(memcmp(caps[0].ptr, "23", 2) == 0);
  ASSERT(slre_match("(.+2)", "123", 3, caps, &msg) == 2);
  ASSERT(caps[0].len == 2);
  ASSERT(memcmp(caps[0].ptr, "12", 2) == 0);
  ASSERT(slre_match("(.*(2.))", "123", 3, caps, &msg) == 3);
  ASSERT(slre_match("(.)(.)", "123", 3, caps, &msg) == 2);
  ASSERT(slre_match("(\\d+)\\s+(\\S+)", "12 hi", 5, caps, &msg) == 5);
  ASSERT(slre_match("ab(cd)+ef", "abcdcdef", 8, NULL, &msg) == 8);
  ASSERT(slre_match("ab(cd)*ef", "abcdcdef", 8, NULL, &msg) == 8);
  ASSERT(slre_match("ab(cd)+?ef", "abcdcdef", 8, NULL, &msg) == 8);
  ASSERT(slre_match("ab(cd)+?.", "abcdcdef", 8, NULL, &msg) == 5);
  ASSERT(slre_match("ab(cd)?", "abcdcdef", 8, NULL, &msg) == 4);

  /* Greedy vs non-greedy */
  ASSERT(slre_match(".+c", "abcabc", 6, NULL, &msg) == 6);
  ASSERT(slre_match(".+?c", "abcabc", 6, NULL, &msg) == 3);
  ASSERT(slre_match(".*?c", "abcabc", 6, NULL, &msg) == 3);
  ASSERT(slre_match(".*c", "abcabc", 6, NULL, &msg) == 6);
  ASSERT(slre_match("bc.d?k?b+", "abcabc", 6, NULL, &msg) == 5);

  /* Branching */
  ASSERT(slre_match("|", "abc", 3, NULL, &msg) == 0);
  ASSERT(slre_match("|.", "abc", 3, NULL, &msg) == 1);
  ASSERT(slre_match("x|y|b", "abc", 3, NULL, &msg) == 2);
  ASSERT(slre_match("k(xx|yy)|ca", "abcabc", 6, NULL, &msg) == 4);
  ASSERT(slre_match("k(xx|yy)|ca|bc", "abcabc", 6, NULL, &msg) == 3);
  ASSERT(slre_match("(|.c)", "abc", 3, caps, &msg) == 3);
  ASSERT(caps[0].len == 2);
  ASSERT(memcmp(caps[0].ptr, "bc", 2) == 0);


  /* Example: HTTP request */
  {
    const char *error_msg, *request = " GET /index.html HTTP/1.0\r\n\r\n";
    struct slre_cap caps[4];

    if (slre_match("^\\s*(\\S+)\\s+(\\S+)\\s+HTTP/(\\d)\\.(\\d)",
                   request, strlen(request), caps, &error_msg)) {
      printf("Method: [%.*s], URI: [%.*s]\n",
             caps[0].len, caps[0].ptr,
             caps[1].len, caps[1].ptr);
    } else {
      printf("Error parsing [%s]: [%s]\n", request, error_msg);
    }

    ASSERT(caps[1].len == 11);
    ASSERT(memcmp(caps[1].ptr, "/index.html", caps[1].len) == 0);
  }

  {
    char *s = slre_replace("({{.+?}})",
                           "Good morning, {{foo}}. How are you, {{bar}}?",
                           "Bob");
    printf("%s\n", s);
    ASSERT(strcmp(s, "Good morning, Bob. How are you, Bob?") == 0);
    free(s);
  }

  printf("Unit test %s (total test: %d, failed tests: %d)\n",
         static_failed_tests > 0 ? "FAILED" : "PASSED",
         static_total_tests, static_failed_tests);

  return static_failed_tests == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}