1/* -*- c -*-
2 * File: pstring.h
3 * Author: Igor Vlasenko <vlasenko@imath.kiev.ua>
4 * Created: Fri Jul  1 20:11:51 2005
5 *
6 * $Id$
7 */
8
9#ifdef HAVE_CONFIG_H
10#include "config.h"
11#endif
12#include <stdio.h>
13#include <string.h>
14#include "pstring.h"
15#include "tmpllog.h"
16#include "exprval.h"
17#include "pmiscdef.h" /*for snprintf */
18
19static
20PSTRING
21double_to_pstring (double number, char buffer[], size_t bufsize) {
22  size_t len=0;
23  size_t tmplen=0;
24  PSTRING retval;
25  snprintf(buffer,bufsize,"%f",number);
26  len=strlen(buffer);
27  tmplen=len;
28  /* removing trailing 0 as 2.00000... */
29  while (buffer[tmplen-1]=='0' && tmplen-->0);
30  if (buffer[tmplen-1]=='.') {
31    tmplen--;
32    len=tmplen;
33  }
34  retval.begin=buffer;
35  retval.endnext=buffer+len;
36  return retval;
37}
38
39static
40PSTRING
41int_to_pstring (EXPR_int64 number, char buffer[], size_t bufsize) {
42  size_t len=0;
43  PSTRING retval;
44  snprintf(buffer, bufsize,"%" EXPR_PRId64 , number);
45  len=strlen(buffer);
46  retval.begin=buffer;
47  retval.endnext=buffer+len;
48  return retval;
49}
50
51static
52int
53pstring_ge(PSTRING a, PSTRING b) {
54  const char* in_a=a.begin;
55  const char* in_b=b.begin;
56  if (in_b==NULL) return 1;
57  if (in_a==NULL) return 0;
58  while (in_a<a.endnext && in_b < b.endnext && *in_a++==*in_b++);
59  if ((in_a==a.endnext && in_b==b.endnext) || *(--in_a) >= *(--in_b) ) return 1; else return 0;
60}
61
62static
63int
64pstring_le(PSTRING a, PSTRING b) {
65  const char* in_a=a.begin;
66  const char* in_b=b.begin;
67  if (in_a==NULL) return 1;
68  if (in_b==NULL) return 0;
69  while (in_a<a.endnext && in_b < b.endnext && *in_a++==*in_b++);
70  if ((in_a==a.endnext && in_b==b.endnext) || *(--in_a) <= *(--in_b) ) return 1; else return 0;
71}
72
73static
74int
75pstring_ne(PSTRING a, PSTRING b) {
76  const char* in_a=a.begin;
77  const char* in_b=b.begin;
78  if (in_a==NULL || in_b==NULL) return in_a != in_b;
79  while (in_a<a.endnext && in_b < b.endnext && *in_a++==*in_b++);
80  if (in_a==a.endnext && in_b==b.endnext && *(--in_a) == *(--in_b)) return 0; else return 1;
81}
82
83static
84int
85pstring_eq(PSTRING a, PSTRING b) {
86  const char* in_a=a.begin;
87  const char* in_b=b.begin;
88  if (in_a==NULL || in_b==NULL) return in_a == in_b;
89  if (in_a==a.endnext) return in_b==b.endnext;
90  while (in_a<a.endnext && in_b < b.endnext && *in_a++==*in_b++);
91  if (in_a==a.endnext && in_b==b.endnext && *(--in_a) == *(--in_b)) return 1; else return 0;
92}
93
94static
95int
96pstring_gt(PSTRING a, PSTRING b) {
97  const char* in_a=a.begin;
98  const char* in_b=b.begin;
99  if (in_a==NULL) return 0;
100  if (in_b==NULL) return 1;
101  while (in_a<a.endnext && in_b < b.endnext && *in_a++==*in_b++);
102  if ((in_b==b.endnext && in_a!=a.endnext)
103      || (*(--in_a) > *(--in_b)) ) return 1; else return 0;
104}
105
106static
107int
108pstring_lt(PSTRING a, PSTRING b) {
109  const char* in_a=a.begin;
110  const char* in_b=b.begin;
111  if (in_b==NULL) return 0;
112  if (in_a==NULL) return 1;
113  while (in_a<a.endnext && in_b < b.endnext && *in_a++==*in_b++);
114  if ((in_b!=b.endnext && in_a==a.endnext)
115      ||  *(--in_a) < *(--in_b) ) return 1; else return 0;
116}
117
118static
119int
120re_notlike(struct expr_parser* exprobj, PSTRING a, PSTRING b) {
121  return ! re_like(exprobj, a,b);
122}
123
124#ifndef HAVE_PCRE
125static
126int
127re_like(struct expr_parser* exprobj, PSTRING a, PSTRING b) {
128  log_expr(exprobj,TMPL_LOG_ERROR,"can't parse the regular expression (sorry, Stanislav Yadykin regexp extension is disabled at compile time) \n");
129  return 0;
130}
131#else
132#include <pcre.h>
133static
134int
135re_like(struct expr_parser* exprobj, PSTRING a, PSTRING b) {
136  pcre* re;
137  int ovector[30];
138  int rc, erroffset;
139  const char* error;
140  const char* subject=a.begin;
141  int subject_length=(int)(a.endnext-a.begin);
142  char* pattern;
143  if (subject==NULL) {
144    log_expr(exprobj,TMPL_LOG_INFO, "regular expression: applied to undefined value.\n");
145    return 0;
146  }
147  if (b.begin==NULL || (b.endnext-b.begin)==0) {
148    log_expr(exprobj,TMPL_LOG_INFO, "regular expression: the pattern is empty or undefined.\n");
149    return 1;
150  }
151  pattern=(char*)malloc(b.endnext-b.begin);
152  if (pattern==NULL) {
153    log_expr(exprobj,TMPL_LOG_ERROR, "regular expression: memory allocation failed.\n");
154    return 0;
155  }
156  strncpy(pattern, b.begin, (b.endnext-b.begin));
157  *(pattern+(b.endnext-b.begin))=0;
158  re = pcre_compile(pattern, 0, &error, &erroffset, NULL); /* default character set */
159  free(pattern);
160  if (re==NULL) {
161      log_expr(exprobj,TMPL_LOG_ERROR, "regular expression: PCRE compilation failed at offset %d: %s\n",
162      erroffset, error);
163    return 0;
164  }
165  rc=pcre_exec(re, NULL, subject, subject_length, 0, 0, ovector, 30);
166  return (rc<0)?0:1;
167}
168#endif
169