package org.tartarus.snowball; import java.lang.reflect.InvocationTargetException; public class SnowballProgram { protected SnowballProgram() { current = new StringBuffer(); setCurrent(""); } /** * Set the current string. */ public void setCurrent(String value) { current.replace(0, current.length(), value); cursor = 0; limit = current.length(); limit_backward = 0; bra = cursor; ket = limit; } /** * Get the current string. */ public String getCurrent() { String result = current.toString(); // Make a new StringBuffer. If we reuse the old one, and a user of // the library keeps a reference to the buffer returned (for example, // by converting it to a String in a way which doesn't force a copy), // the buffer size will not decrease, and we will risk wasting a large // amount of memory. // Thanks to Wolfram Esser for spotting this problem. current = new StringBuffer(); return result; } // current string protected StringBuffer current; protected int cursor; protected int limit; protected int limit_backward; protected int bra; protected int ket; protected void copy_from(SnowballProgram other) { current = other.current; cursor = other.cursor; limit = other.limit; limit_backward = other.limit_backward; bra = other.bra; ket = other.ket; } protected boolean in_grouping(char [] s, int min, int max) { if (cursor >= limit) return false; char ch = current.charAt(cursor); if (ch > max || ch < min) return false; ch -= min; if ((s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return false; cursor++; return true; } protected boolean in_grouping_b(char [] s, int min, int max) { if (cursor <= limit_backward) return false; char ch = current.charAt(cursor - 1); if (ch > max || ch < min) return false; ch -= min; if ((s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return false; cursor--; return true; } protected boolean out_grouping(char [] s, int min, int max) { if (cursor >= limit) return false; char ch = current.charAt(cursor); if (ch > max || ch < min) { cursor++; return true; } ch -= min; if ((s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) { cursor ++; return true; } return false; } protected boolean out_grouping_b(char [] s, int min, int max) { if (cursor <= limit_backward) return false; char ch = current.charAt(cursor - 1); if (ch > max || ch < min) { cursor--; return true; } ch -= min; if ((s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) { cursor--; return true; } return false; } protected boolean in_range(int min, int max) { if (cursor >= limit) return false; char ch = current.charAt(cursor); if (ch > max || ch < min) return false; cursor++; return true; } protected boolean in_range_b(int min, int max) { if (cursor <= limit_backward) return false; char ch = current.charAt(cursor - 1); if (ch > max || ch < min) return false; cursor--; return true; } protected boolean out_range(int min, int max) { if (cursor >= limit) return false; char ch = current.charAt(cursor); if (!(ch > max || ch < min)) return false; cursor++; return true; } protected boolean out_range_b(int min, int max) { if (cursor <= limit_backward) return false; char ch = current.charAt(cursor - 1); if(!(ch > max || ch < min)) return false; cursor--; return true; } protected boolean eq_s(int s_size, String s) { if (limit - cursor < s_size) return false; int i; for (i = 0; i != s_size; i++) { if (current.charAt(cursor + i) != s.charAt(i)) return false; } cursor += s_size; return true; } protected boolean eq_s_b(int s_size, String s) { if (cursor - limit_backward < s_size) return false; int i; for (i = 0; i != s_size; i++) { if (current.charAt(cursor - s_size + i) != s.charAt(i)) return false; } cursor -= s_size; return true; } protected boolean eq_v(CharSequence s) { return eq_s(s.length(), s.toString()); } protected boolean eq_v_b(CharSequence s) { return eq_s_b(s.length(), s.toString()); } protected int find_among(Among v[], int v_size) { int i = 0; int j = v_size; int c = cursor; int l = limit; int common_i = 0; int common_j = 0; boolean first_key_inspected = false; while(true) { int k = i + ((j - i) >> 1); int diff = 0; int common = common_i < common_j ? common_i : common_j; // smaller Among w = v[k]; int i2; for (i2 = common; i2 < w.s_size; i2++) { if (c + common == l) { diff = -1; break; } diff = current.charAt(c + common) - w.s[i2]; if (diff != 0) break; common++; } if (diff < 0) { j = k; common_j = common; } else { i = k; common_i = common; } if (j - i <= 1) { if (i > 0) break; // v->s has been inspected if (j == i) break; // only one item in v // - but now we need to go round once more to get // v->s inspected. This looks messy, but is actually // the optimal approach. if (first_key_inspected) break; first_key_inspected = true; } } while(true) { Among w = v[i]; if (common_i >= w.s_size) { cursor = c + w.s_size; if (w.method == null) return w.result; boolean res; try { Object resobj = w.method.invoke(w.methodobject, new Object[0]); res = resobj.toString().equals("true"); } catch (InvocationTargetException e) { res = false; // FIXME - debug message } catch (IllegalAccessException e) { res = false; // FIXME - debug message } cursor = c + w.s_size; if (res) return w.result; } i = w.substring_i; if (i < 0) return 0; } } // find_among_b is for backwards processing. Same comments apply protected int find_among_b(Among v[], int v_size) { int i = 0; int j = v_size; int c = cursor; int lb = limit_backward; int common_i = 0; int common_j = 0; boolean first_key_inspected = false; while(true) { int k = i + ((j - i) >> 1); int diff = 0; int common = common_i < common_j ? common_i : common_j; Among w = v[k]; int i2; for (i2 = w.s_size - 1 - common; i2 >= 0; i2--) { if (c - common == lb) { diff = -1; break; } diff = current.charAt(c - 1 - common) - w.s[i2]; if (diff != 0) break; common++; } if (diff < 0) { j = k; common_j = common; } else { i = k; common_i = common; } if (j - i <= 1) { if (i > 0) break; if (j == i) break; if (first_key_inspected) break; first_key_inspected = true; } } while(true) { Among w = v[i]; if (common_i >= w.s_size) { cursor = c - w.s_size; if (w.method == null) return w.result; boolean res; try { Object resobj = w.method.invoke(w.methodobject, new Object[0]); res = resobj.toString().equals("true"); } catch (InvocationTargetException e) { res = false; // FIXME - debug message } catch (IllegalAccessException e) { res = false; // FIXME - debug message } cursor = c - w.s_size; if (res) return w.result; } i = w.substring_i; if (i < 0) return 0; } } /* to replace chars between c_bra and c_ket in current by the * chars in s. */ protected int replace_s(int c_bra, int c_ket, String s) { int adjustment = s.length() - (c_ket - c_bra); current.replace(c_bra, c_ket, s); limit += adjustment; if (cursor >= c_ket) cursor += adjustment; else if (cursor > c_bra) cursor = c_bra; return adjustment; } protected void slice_check() { if (bra < 0 || bra > ket || ket > limit || limit > current.length()) // this line could be removed { System.err.println("faulty slice operation"); // FIXME: report error somehow. /* fprintf(stderr, "faulty slice operation:\n"); debug(z, -1, 0); exit(1); */ } } protected void slice_from(String s) { slice_check(); replace_s(bra, ket, s); } protected void slice_from(CharSequence s) { slice_from(s.toString()); } protected void slice_del() { slice_from(""); } protected void insert(int c_bra, int c_ket, String s) { int adjustment = replace_s(c_bra, c_ket, s); if (c_bra <= bra) bra += adjustment; if (c_bra <= ket) ket += adjustment; } protected void insert(int c_bra, int c_ket, CharSequence s) { insert(c_bra, c_ket, s.toString()); } /* Copy the slice into the supplied StringBuffer */ protected StringBuffer slice_to(StringBuffer s) { slice_check(); int len = ket - bra; s.replace(0, s.length(), current.substring(bra, ket)); return s; } /* Copy the slice into the supplied StringBuilder */ protected StringBuilder slice_to(StringBuilder s) { slice_check(); int len = ket - bra; s.replace(0, s.length(), current.substring(bra, ket)); return s; } protected StringBuffer assign_to(StringBuffer s) { s.replace(0, s.length(), current.substring(0, limit)); return s; } protected StringBuilder assign_to(StringBuilder s) { s.replace(0, s.length(), current.substring(0, limit)); return s; } /* extern void debug(struct SN_env * z, int number, int line_count) { int i; int limit = SIZE(z->p); //if (number >= 0) printf("%3d (line %4d): '", number, line_count); if (number >= 0) printf("%3d (line %4d): [%d]'", number, line_count,limit); for (i = 0; i <= limit; i++) { if (z->lb == i) printf("{"); if (z->bra == i) printf("["); if (z->c == i) printf("|"); if (z->ket == i) printf("]"); if (z->l == i) printf("}"); if (i < limit) { int ch = z->p[i]; if (ch == 0) ch = '#'; printf("%c", ch); } } printf("'\n"); } */ };