/**@constructor*/ BaseStemmer = function() { this.setCurrent = function(value) { this.current = value; this.cursor = 0; this.limit = this.current.length; this.limit_backward = 0; this.bra = this.cursor; this.ket = this.limit; }; this.getCurrent = function() { return this.current; }; this.copy_from = function(other) { this.current = other.current; this.cursor = other.cursor; this.limit = other.limit; this.limit_backward = other.limit_backward; this.bra = other.bra; this.ket = other.ket; }; this.in_grouping = function(s, min, max) { if (this.cursor >= this.limit) return false; var ch = this.current.charCodeAt(this.cursor); if (ch > max || ch < min) return false; ch -= min; if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false; this.cursor++; return true; }; this.in_grouping_b = function(s, min, max) { if (this.cursor <= this.limit_backward) return false; var ch = this.current.charCodeAt(this.cursor - 1); if (ch > max || ch < min) return false; ch -= min; if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false; this.cursor--; return true; }; this.out_grouping = function(s, min, max) { if (this.cursor >= this.limit) return false; var ch = this.current.charCodeAt(this.cursor); if (ch > max || ch < min) { this.cursor++; return true; } ch -= min; if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) == 0) { this.cursor++; return true; } return false; }; this.out_grouping_b = function(s, min, max) { if (this.cursor <= this.limit_backward) return false; var ch = this.current.charCodeAt(this.cursor - 1); if (ch > max || ch < min) { this.cursor--; return true; } ch -= min; if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) { this.cursor--; return true; } return false; }; this.eq_s = function(s) { if (this.limit - this.cursor < s.length) return false; if (this.current.slice(this.cursor, this.cursor + s.length) != s) { return false; } this.cursor += s.length; return true; }; this.eq_s_b = function(s) { if (this.cursor - this.limit_backward < s.length) return false; if (this.current.slice(this.cursor - s.length, this.cursor) != s) { return false; } this.cursor -= s.length; return true; }; /** @return {number} */ this.find_among = function(v) { var i = 0; var j = v.length; var c = this.cursor; var l = this.limit; var common_i = 0; var common_j = 0; var first_key_inspected = false; while (true) { var k = i + ((j - i) >>> 1); var diff = 0; var common = common_i < common_j ? common_i : common_j; // smaller // w[0]: string, w[1]: substring_i, w[2]: result, w[3]: function (optional) var w = v[k]; var i2; for (i2 = common; i2 < w[0].length; i2++) { if (c + common == l) { diff = -1; break; } diff = this.current.charCodeAt(c + common) - w[0].charCodeAt(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; } } do { var w = v[i]; if (common_i >= w[0].length) { this.cursor = c + w[0].length; if (w.length < 4) return w[2]; var res = w[3](this); this.cursor = c + w[0].length; if (res) return w[2]; } i = w[1]; } while (i >= 0); return 0; }; // find_among_b is for backwards processing. Same comments apply this.find_among_b = function(v) { var i = 0; var j = v.length var c = this.cursor; var lb = this.limit_backward; var common_i = 0; var common_j = 0; var first_key_inspected = false; while (true) { var k = i + ((j - i) >> 1); var diff = 0; var common = common_i < common_j ? common_i : common_j; var w = v[k]; var i2; for (i2 = w[0].length - 1 - common; i2 >= 0; i2--) { if (c - common == lb) { diff = -1; break; } diff = this.current.charCodeAt(c - 1 - common) - w[0].charCodeAt(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; } } do { var w = v[i]; if (common_i >= w[0].length) { this.cursor = c - w[0].length; if (w.length < 4) return w[2]; var res = w[3](this); this.cursor = c - w[0].length; if (res) return w[2]; } i = w[1]; } while (i >= 0); return 0; }; /* to replace chars between c_bra and c_ket in this.current by the * chars in s. */ this.replace_s = function(c_bra, c_ket, s) { var adjustment = s.length - (c_ket - c_bra); this.current = this.current.slice(0, c_bra) + s + this.current.slice(c_ket); this.limit += adjustment; if (this.cursor >= c_ket) this.cursor += adjustment; else if (this.cursor > c_bra) this.cursor = c_bra; return adjustment; }; this.slice_check = function() { if (this.bra < 0 || this.bra > this.ket || this.ket > this.limit || this.limit > this.current.length) { return false; } return true; }; this.slice_from = function(s) { var result = false; if (this.slice_check()) { this.replace_s(this.bra, this.ket, s); result = true; } return result; }; this.slice_del = function() { return this.slice_from(""); }; this.insert = function(c_bra, c_ket, s) { var adjustment = this.replace_s(c_bra, c_ket, s); if (c_bra <= this.bra) this.bra += adjustment; if (c_bra <= this.ket) this.ket += adjustment; }; this.slice_to = function() { var result = ''; if (this.slice_check()) { result = this.current.slice(this.bra, this.ket); } return result; }; this.assign_to = function() { return this.current.slice(0, this.limit); }; };