1#include <stdlib.h>
  2#include <stdio.h>
  3#include <string.h>
  4#ifdef BENCHMARK_CHELP
  5#include <sys/time.h>
  6#endif
  7#include "chelper.h"
  8
  9int NewOnigRegex( char *pattern, int pattern_length, int option,
 10                  OnigRegex *regex, OnigEncoding *encoding, OnigErrorInfo **error_info, char **error_buffer) {
 11    int ret = ONIG_NORMAL;
 12    int error_msg_len = 0;
 13
 14    OnigUChar *pattern_start = (OnigUChar *) pattern;
 15    OnigUChar *pattern_end = (OnigUChar *) (pattern + pattern_length);
 16
 17    *error_info = (OnigErrorInfo *) malloc(sizeof(OnigErrorInfo));
 18    memset(*error_info, 0, sizeof(OnigErrorInfo));
 19
 20    onig_initialize_encoding(*encoding);
 21
 22    *error_buffer = (char*) malloc(ONIG_MAX_ERROR_MESSAGE_LEN * sizeof(char));
 23
 24    memset(*error_buffer, 0, ONIG_MAX_ERROR_MESSAGE_LEN * sizeof(char));
 25
 26    ret = onig_new(regex, pattern_start, pattern_end, (OnigOptionType)(option), *encoding, OnigDefaultSyntax, *error_info);
 27
 28    if (ret != ONIG_NORMAL) {
 29        error_msg_len = onig_error_code_to_str((unsigned char*)(*error_buffer), ret, *error_info);
 30        if (error_msg_len >= ONIG_MAX_ERROR_MESSAGE_LEN) {
 31            error_msg_len = ONIG_MAX_ERROR_MESSAGE_LEN - 1;
 32        }
 33        (*error_buffer)[error_msg_len] = '\0';
 34    }
 35    return ret;
 36}
 37
 38int SearchOnigRegex( void *str, int str_length, int offset, int option,
 39                  OnigRegex regex, OnigErrorInfo *error_info, char *error_buffer, int *captures, int *numCaptures) {
 40    int ret = ONIG_MISMATCH;
 41    int error_msg_len = 0;
 42    OnigRegion *region;
 43#ifdef BENCHMARK_CHELP
 44    struct timeval tim1, tim2;
 45    long t;
 46#endif
 47
 48    OnigUChar *str_start = (OnigUChar *) str;
 49    OnigUChar *str_end = (OnigUChar *) (str_start + str_length);
 50    OnigUChar *search_start = (OnigUChar *)(str_start + offset);
 51    OnigUChar *search_end = str_end;
 52
 53#ifdef BENCHMARK_CHELP
 54    gettimeofday(&tim1, NULL);
 55#endif
 56
 57    region = onig_region_new();
 58
 59    ret = onig_search(regex, str_start, str_end, search_start, search_end, region, option);
 60    if (ret < 0 && error_buffer != NULL) {
 61        error_msg_len = onig_error_code_to_str((unsigned char*)(error_buffer), ret, error_info);
 62        if (error_msg_len >= ONIG_MAX_ERROR_MESSAGE_LEN) {
 63            error_msg_len = ONIG_MAX_ERROR_MESSAGE_LEN - 1;
 64        }
 65        error_buffer[error_msg_len] = '\0';
 66    }
 67    else if (captures != NULL) {
 68        int i;
 69        int count = 0;
 70        for (i = 0; i < region->num_regs; i++) {
 71            captures[2*count] = region->beg[i];
 72            captures[2*count+1] = region->end[i];
 73            count ++;
 74        }
 75        *numCaptures = count;
 76    }
 77
 78    onig_region_free(region, 1);
 79
 80#ifdef BENCHMARK_CHELP
 81    gettimeofday(&tim2, NULL);
 82    t = (tim2.tv_sec - tim1.tv_sec) * 1000000 + tim2.tv_usec - tim1.tv_usec;
 83    printf("%ld microseconds elapsed\n", t);
 84#endif
 85    return ret;
 86}
 87
 88int MatchOnigRegex(void *str, int str_length, int offset, int option,
 89                  OnigRegex regex) {
 90    int ret = ONIG_MISMATCH;
 91    int error_msg_len = 0;
 92    OnigRegion *region;
 93#ifdef BENCHMARK_CHELP
 94    struct timeval tim1, tim2;
 95    long t;
 96#endif
 97
 98    OnigUChar *str_start = (OnigUChar *) str;
 99    OnigUChar *str_end = (OnigUChar *) (str_start + str_length);
100    OnigUChar *search_start = (OnigUChar *)(str_start + offset);
101
102#ifdef BENCHMARK_CHELP
103    gettimeofday(&tim1, NULL);
104#endif
105    region = onig_region_new();
106    ret = onig_match(regex, str_start, str_end, search_start, region, option);
107    onig_region_free(region, 1);
108#ifdef BENCHMARK_CHELP
109    gettimeofday(&tim2, NULL);
110    t = (tim2.tv_sec - tim1.tv_sec) * 1000000 + tim2.tv_usec - tim1.tv_usec;
111    printf("%ld microseconds elapsed\n", t);
112#endif
113    return ret;
114}
115
116int LookupOnigCaptureByName(char *name, int name_length,
117                  OnigRegex regex) {
118    int ret = ONIGERR_UNDEFINED_NAME_REFERENCE;
119    OnigRegion *region;
120#ifdef BENCHMARK_CHELP
121    struct timeval tim1, tim2;
122    long t;
123#endif
124    OnigUChar *name_start = (OnigUChar *) name;
125    OnigUChar *name_end = (OnigUChar *) (name_start + name_length);
126#ifdef BENCHMARK_CHELP
127    gettimeofday(&tim1, NULL);
128#endif
129    region = onig_region_new();
130    ret = onig_name_to_backref_number(regex, name_start, name_end, region);
131    onig_region_free(region, 1);
132#ifdef BENCHMARK_CHELP
133    gettimeofday(&tim2, NULL);
134    t = (tim2.tv_sec - tim1.tv_sec) * 1000000 + tim2.tv_usec - tim1.tv_usec;
135    printf("%ld microseconds elapsed\n", t);
136#endif
137    return ret;
138}
139
140typedef struct {
141    char *nameBuffer;
142    int bufferOffset;
143    int bufferSize;
144    int *numbers;
145    int numIndex;
146} group_info_t;
147
148int name_callback(const UChar* name, const UChar* name_end,
149          int ngroup_num, int* group_nums,
150          regex_t* reg, void* arg)
151{
152    int nameLen, offset, newOffset;
153    group_info_t *groupInfo;
154
155    groupInfo = (group_info_t*) arg;
156    offset = groupInfo->bufferOffset;
157    nameLen = name_end - name;
158    newOffset = offset + nameLen;
159
160    //if there are already names, add a ";"
161    if (offset > 0) {
162        newOffset += 1;
163    }
164
165    if (newOffset <= groupInfo->bufferSize) {
166        if (offset > 0) {
167            groupInfo->nameBuffer[offset] = ';';
168            offset += 1;
169        }
170        memcpy(&groupInfo->nameBuffer[offset], name, nameLen);
171    }
172    groupInfo->bufferOffset = newOffset;
173    if (ngroup_num > 0) {
174        groupInfo->numbers[groupInfo->numIndex] = group_nums[ngroup_num-1];
175    } else {
176        groupInfo->numbers[groupInfo->numIndex] = -1;
177    }
178    groupInfo->numIndex += 1;
179    return 0;  /* 0: continue */
180}
181
182int GetCaptureNames(OnigRegex reg, void *buffer, int bufferSize, int* groupNumbers) {
183    int ret;
184    group_info_t groupInfo;
185    groupInfo.nameBuffer = (char*)buffer;
186    groupInfo.bufferOffset = 0;
187    groupInfo.bufferSize = bufferSize;
188    groupInfo.numbers = groupNumbers;
189    groupInfo.numIndex = 0;
190    onig_foreach_name(reg, name_callback, (void* )&groupInfo);
191    return groupInfo.bufferOffset;
192}