+/* * * * * * * * * * * * * *
+ * Converters
+ * * * * * * * * * * * * * */
+
+static yaz_nfa_converter *create_null_converter ( yaz_nfa *n) {
+ yaz_nfa_converter *c;
+ c=nmem_malloc(n->nmem, sizeof(yaz_nfa_converter));
+ c->next=0;
+ c->type=conv_none;
+ c->string=0;
+ c->strlen=0;
+ c->backref_no=0;
+ c->char_diff=0;
+ return c;
+}
+
+yaz_nfa_converter *yaz_nfa_create_string_converter (
+ yaz_nfa *n,
+ yaz_nfa_char *string,
+ size_t length){
+ yaz_nfa_converter *c;
+ size_t i;
+ c=create_null_converter(n);
+ c->type=conv_string;
+ c->string=nmem_malloc(n->nmem, length*sizeof(yaz_nfa_char));
+ for (i=0;i<length;i++)
+ c->string[i]=string[i];
+ c->strlen=length;
+ return c;
+}
+
+yaz_nfa_converter *yaz_nfa_create_backref_converter (
+ yaz_nfa *n, int backref_no ) {
+ yaz_nfa_converter *c;
+ c=create_null_converter(n);
+ c->type=conv_backref;
+ c->backref_no=backref_no;
+ return c;
+}
+
+yaz_nfa_converter *yaz_nfa_create_range_converter (
+ yaz_nfa *n, int backref_no,
+ yaz_nfa_char from_char,
+ yaz_nfa_char to_char){
+ yaz_nfa_converter *c;
+ c=create_null_converter(n);
+ c->type=conv_range;
+ c->backref_no=backref_no;
+ c->char_diff=to_char - from_char;
+ return c;
+
+}
+
+
+void yaz_nfa_append_converter (
+ yaz_nfa *n,
+ yaz_nfa_converter *startpoint,
+ yaz_nfa_converter *newconverter) {
+ while (startpoint->next)
+ startpoint=startpoint->next;
+ startpoint->next=newconverter;
+}
+
+static int string_convert (
+ yaz_nfa *n,
+ yaz_nfa_converter *c,
+ yaz_nfa_char **outbuff,
+ size_t *outcharsleft){
+ size_t sz=c->strlen;
+ yaz_nfa_char *p=c->string;
+ while (sz--) {
+ if ((*outcharsleft)-- <= 0)
+ return YAZ_NFA_NOSPACE;
+ **outbuff=*p++;
+ (*outbuff)++;
+ }
+ return YAZ_NFA_SUCCESS;
+}
+static int backref_convert (
+ yaz_nfa *n,
+ yaz_nfa_converter *c,
+ yaz_nfa_char **outbuff,
+ size_t *outcharsleft){
+ yaz_nfa_char *cp1,*cp2;
+ int i;
+ i = yaz_nfa_get_backref(n,c->backref_no, &cp1, &cp2);
+ if ( i == YAZ_NFA_NOSUCHBACKREF) /* no backref, produce no output */
+ return YAZ_NFA_SUCCESS;
+ if ( i == YAZ_NFA_NOMATCH ) /* no match in dfa */
+ return 1; /* should not happen */
+ while (cp2 >= cp1) {
+ if ((*outcharsleft)-- <= 0)
+ return YAZ_NFA_NOSPACE;
+ **outbuff=*cp1++;
+ (*outbuff)++;
+ }
+ return YAZ_NFA_SUCCESS;
+}
+
+static int range_convert (
+ yaz_nfa *n,
+ yaz_nfa_converter *c,
+ yaz_nfa_char **outbuff,
+ size_t *outcharsleft){
+ yaz_nfa_char *cp1=0, *cp2=0;
+ int i;
+ i = yaz_nfa_get_backref(n,c->backref_no, &cp1, &cp2);
+ if (i == YAZ_NFA_NOSUCHBACKREF) /* no backref, produce no output, not ok */
+ return YAZ_NFA_NOSUCHBACKREF; /* should not happen */
+ if (i == YAZ_NFA_NOMATCH) /* no match in dfa */
+ return YAZ_NFA_NOMATCH; /* should not happen */
+ while (cp2 >= cp1) {
+ if ((*outcharsleft)-- <= 0)
+ return YAZ_NFA_NOSPACE;
+ **outbuff=(*cp1++) + c->char_diff ;
+ (*outbuff)++;
+ }
+ return YAZ_NFA_SUCCESS;
+}
+
+
+int yaz_nfa_run_converters(
+ yaz_nfa *n,
+ yaz_nfa_converter *c,
+ yaz_nfa_char **outbuff,
+ size_t *outcharsleft){
+ int rc=0;
+ while (c && !rc) {
+ switch(c->type) {
+ case conv_string:
+ rc=string_convert(n,c,outbuff,outcharsleft);
+ break;
+ case conv_backref:
+ rc=backref_convert(n,c,outbuff,outcharsleft);
+ break;
+ case conv_range:
+ rc=range_convert(n,c,outbuff,outcharsleft);
+ break;
+ default:
+ rc=YAZ_NFA_INTERNAL; /* should never happen */
+ }
+ c=c->next;
+ }
+ return rc;
+}
+
+/* * * * * * * *
+ * High-level interface
+ * These routines build the nfa and add converters, all
+ * in one go.
+ * * * * * * * */
+
+int yaz_nfa_add_string_rule( yaz_nfa *n,
+ yaz_nfa_char *from_string,
+ size_t from_length,
+ yaz_nfa_char *to_string,
+ size_t to_length ) {
+ yaz_nfa_state *s=
+ yaz_nfa_add_sequence(n, 0, from_string,from_length);
+ yaz_nfa_converter *c=
+ yaz_nfa_create_string_converter(n,to_string,to_length);
+ return yaz_nfa_set_result(n,s,c);
+}
+
+int yaz_nfa_add_ascii_string_rule( yaz_nfa *n,
+ char *from_string,
+ char *to_string) {
+ size_t from_len = strlen(from_string);
+ size_t to_len = strlen(to_string);
+ yaz_nfa_char *from_buf=
+ nmem_malloc(n->nmem, from_len*sizeof(yaz_nfa_char));
+ yaz_nfa_char *to_buf=
+ nmem_malloc(n->nmem, to_len*sizeof(yaz_nfa_char));
+ size_t i;
+ for (i=0;i<from_len;i++)
+ from_buf[i]=from_string[i];
+ for (i=0;i<to_len;i++)
+ to_buf[i]=to_string[i];
+ return yaz_nfa_add_string_rule(n,from_buf, from_len,
+ to_buf, to_len);
+}
+
+int yaz_nfa_add_char_range_rule (yaz_nfa *n,
+ yaz_nfa_char range_start,
+ yaz_nfa_char range_end,
+ yaz_nfa_char output_range_start) {
+ yaz_nfa_state *s=
+ yaz_nfa_add_range(n, 0, range_start, range_end);
+ yaz_nfa_converter *c=
+ yaz_nfa_create_range_converter(n,0,range_start, output_range_start);
+ return yaz_nfa_set_result(n,s,c);
+}
+
+int yaz_nfa_add_char_string_rule (yaz_nfa *n,
+ yaz_nfa_char range_start,
+ yaz_nfa_char range_end,
+ yaz_nfa_char* to_string,
+ size_t to_length) {
+ yaz_nfa_state *s=
+ yaz_nfa_add_range(n, 0, range_start, range_end);
+ yaz_nfa_converter *c=
+ yaz_nfa_create_string_converter(n,to_string,to_length);
+ return yaz_nfa_set_result(n,s,c);
+}
+
+
+int yaz_nfa_convert_slice (yaz_nfa *n,
+ yaz_nfa_char **inbuff,
+ size_t *incharsleft,
+ yaz_nfa_char **outbuff,
+ size_t *outcharsleft) {
+ void *resptr;
+ yaz_nfa_converter *conv;
+ int rc;
+
+ if (*outcharsleft==0)
+ rc=YAZ_NFA_NOSPACE; /* no room in outbuff */
+ else if (*incharsleft==0)
+ rc = YAZ_NFA_SUCCESS; /* all done */
+ else {
+ rc=yaz_nfa_match(n, inbuff, incharsleft, &resptr);
+ if (rc==YAZ_NFA_SUCCESS) {
+ conv= (yaz_nfa_converter *)resptr;
+ rc=yaz_nfa_run_converters(n,conv,outbuff,outcharsleft);
+ } else if (rc==YAZ_NFA_NOMATCH) {
+ **outbuff = **inbuff;
+ (*outbuff)++;
+ (*inbuff)++;
+ (*outcharsleft)--;
+ (*incharsleft)--;
+ rc=YAZ_NFA_SUCCESS;
+ }
+ /* else just return the error code */
+ }
+ return rc;
+}