FreeBASIC  0.91.0
str_instrrev.c
Go to the documentation of this file.
1 /* instrrev function */
2 
3 #include "fb.h"
4 
5 #if 0 /* FIXME: implementation is bugged somewhere, missing some matches */
6 static ssize_t fb_hFindBM
7  (
8  ssize_t start,
9  const char *pachText,
10  ssize_t len_text,
11  const char *pachPattern,
12  ssize_t len_pattern
13  )
14 {
15  ssize_t i, j, len_max = len_text - len_pattern;
16  ssize_t bm_bc[256];
17  ssize_t *bm_gc, *suffixes;
18 
19  bm_gc = (ssize_t*) alloca(sizeof(ssize_t) * (len_pattern + 1));
20  suffixes = (ssize_t*) alloca(sizeof(ssize_t) * (len_pattern + 1));
21 
22  memset( bm_gc, 0, sizeof(ssize_t) * (len_pattern+1) );
23  memset( suffixes, 0, sizeof(ssize_t) * (len_pattern+1) );
24 
25  /* create "bad character" shifts */
26  memset(bm_bc, -1, sizeof(bm_bc));
27  for( i=0; i!=len_pattern; ++i )
28  bm_bc[ FB_CHAR_TO_INT(pachPattern[i]) ] = i;
29 
30  /* preprocessing for "good end strategy" case 1 */
31  i = len_pattern;
32  j = len_pattern + 1;
33  suffixes[ i ] = j;
34  while ( i != 0 )
35  {
36  char ch1 = pachPattern[len_pattern-i];
37  while ( j <= len_pattern && ch1 != pachPattern[len_pattern-j] )
38  {
39  if( bm_gc[j]==0 )
40  bm_gc[j] = j - i;
41  j = suffixes[j];
42  }
43  --i;
44  --j;
45  suffixes[i] = j;
46  }
47 
48  /* preprocessing for "good end strategy" case 2 */
49  j = suffixes[0];
50  for( i=0; i<=len_pattern; ++i )
51  {
52  if( bm_gc[i]==0 )
53  bm_gc[i] = j;
54  if( i==j )
55  j = suffixes[j];
56  }
57 
58  /* search */
59  i = len_max - start;
60  while( i <= len_max )
61  {
62  j = len_pattern;
63  while( j != 0 && pachPattern[len_pattern-j] == pachText[len_text - i - j] )
64  --j;
65  if( j==0 ) {
66  return len_text - len_pattern - i + 1;
67  } else {
68  char chText = pachText[len_text - i - j];
69  ssize_t shift_gc = bm_gc[j];
70  ssize_t shift_bc = j - 1 - bm_bc[ FB_CHAR_TO_INT(chText) ];
71  i += ( (shift_gc > shift_bc) ? shift_gc : shift_bc );
72  }
73  }
74  return 0;
75 }
76 #endif
77 
78 #if 1
79 static ssize_t fb_hFindNaive
80  (
81  ssize_t start,
82  const char *pachText,
83  ssize_t len_text,
84  const char *pachPattern,
85  ssize_t len_pattern
86  )
87 {
88  ssize_t i;
89  pachText += start;
90  for( i=0; i<=start; ++i ) {
91  ssize_t j;
92  for( j=0; j!=len_pattern; ++j ) {
93  if( pachText[j]!=pachPattern[j] )
94  break;
95  }
96  if( j==len_pattern )
97  return start - i + 1;
98  --pachText;
99  }
100  return 0;
101 }
102 #endif
103 
104 FBCALL ssize_t fb_StrInstrRev( FBSTRING *src, FBSTRING *patt, ssize_t start )
105 {
106  ssize_t r = 0;
107 
108  if( (src != NULL) && (src->data != NULL) && (patt != NULL) && (patt->data != NULL) )
109  {
110  ssize_t size_src = FB_STRSIZE(src);
111  ssize_t size_patt = FB_STRSIZE(patt);
112 
113  if( (size_src != 0) && (size_patt != 0) && (size_patt <= size_src) && (start != 0))
114  {
115  /* handle signed/unsigned comparisons of start and size_* vars */
116  if( start < 0 )
117  start = size_src - size_patt + 1;
118  else if( start > size_src )
119  start = 0;
120  else if( start > size_src - size_patt )
121  start = size_src - size_patt + 1;
122 
123  if( start > 0 )
124  {
125 #if 1
126  r = fb_hFindNaive( start - 1,
127  src->data, size_src,
128  patt->data, size_patt );
129 #else
130  r = fb_hFindBM( start - 1,
131  src->data, size_src,
132  patt->data, size_patt );
133 #endif
134  }
135  }
136  }
137 
138  FB_STRLOCK();
139 
140  /* del if temp */
141  fb_hStrDelTemp_NoLock( src );
142  fb_hStrDelTemp_NoLock( patt );
143 
144  FB_STRUNLOCK();
145 
146  return r;
147 }