using System; using System.Text; using M17N.Core; namespace M17N.Core { #if false public enum MTextFormat { MTEXT_FORMAT_US_ASCII, MTEXT_FORMAT_UTF_8, MTEXT_FORMAT_UTF_16BE, MTEXT_FORMAT_UTF_16LE, MTEXT_FORMAT_UTF_32BE, MTEXT_FORMAT_UTF_32LE, } #endif public class MText { #if false public enum MTextFormat format; #endif private class MTextPlist : MPlist { public class MInterval { MPlist stack; int nprops; public int start, end; public MInterval prev, next; } MInterval head, tail; public MTextPlist (MText mt) { head = tail = new MInterval (); head.start = 0; head.end = mt.sb.Length; } } private StringBuilder sb; private int nchars; private int cache_pos; private int cache_idx; private MTextPlist plist; private bool unmodifiable; private static UTF8Encoding utf8 = new UTF8Encoding (); private static int count_chars (String str) { int len = str.Length, n = 0; for (int i = 0; i < len; i++) n += surrogate_high_p (str[i]) ? 2 : 1; return n; } private static int count_chars (StringBuilder str) { int len = str.Length, n = 0; for (int i = 0; i < len; i++) n += surrogate_high_p (str[i]) ? 2 : 1; return n; } public MText () { sb = new StringBuilder (); } public MText (byte[] str) { sb = new StringBuilder (utf8.GetString (str)); nchars = count_chars (sb); } public MText (String str) { sb = new StringBuilder (str); nchars = count_chars (str); } public MText (StringBuilder str) { sb = str; nchars = count_chars (str); } public static MText operator+ (MText mt1, MText mt2) { MText mt = new MText (mt1.sb); mt.sb.Append (mt2.sb); mt.nchars = mt1.nchars + mt2.nchars; return mt; } public override string ToString () { return sb.ToString (); } private static bool surrogate_high_p (char c) { return (c >= 0xD800 && c < 0xDC00); } private static bool surrogate_low_p (char c) { return (c >= 0xDC00 && c < 0xE000); } private static int inc_idx (StringBuilder sb, int i) { return (i + (surrogate_high_p (sb[i]) ? 2 : 1)); } private static int dec_idx (StringBuilder sb, int i) { return (i - (surrogate_low_p (sb[i - 1]) ? 2 : 1)); } private static int pos_to_idx (MText mt, int pos) { if (pos == mt.cache_pos) return mt.cache_idx; int p, i; bool forward; if (pos < mt.cache_pos) { if (mt.cache_pos == mt.cache_idx) return mt.cache_idx; if (pos < mt.cache_pos - pos) { p = i = 0; forward = true; } else { p = mt.cache_pos; i = mt.cache_idx; forward = false; } } else { if (mt.nchars - mt.cache_pos == mt.sb.Length - mt.cache_idx) return (mt.cache_idx + pos - mt.cache_pos); if (pos - mt.cache_pos < mt.nchars - pos) { p = mt.cache_pos; i = mt.cache_idx; forward = true; } else { p = mt.nchars; i = mt.sb.Length; forward = false; } } if (forward) for (; p < pos; i = inc_idx (mt.sb, i), p++); else for (; p > pos; i = dec_idx (mt.sb, i), p--); mt.cache_pos = p; mt.cache_idx = i; return i; } private void insert (int pos, MText mt2, int from, int to) { int pos_idx = pos_to_idx (this, pos); int from_idx = pos_to_idx (mt2, from); int to_idx = pos_to_idx (mt2, to); sb.Insert (pos_idx, mt2.sb.ToString (from_idx, to_idx - from_idx)); nchars += to - from; } public int this[int i] { set { i = pos_to_idx (this, i); if (value < 0x10000) { if (surrogate_high_p (sb[i])) sb.Remove (i, 1); sb[i] = (char) value; } else { char high = (char) (0xD800 + ((value - 0x10000) >> 10)); char low = (char) (0xDC00 + ((value - 0x10000) & 0x3FF)); if (! surrogate_high_p (sb[i])) sb.Insert (i, 0); sb[i] = high; sb[i + 1] = low; } } get { i = pos_to_idx (this, i); return (surrogate_high_p (sb[i]) ? ((sb[i] - 0xD800) << 10) + (sb[i + 1] - 0xDC00) + 0x10000 : sb[i]); } } public MText dup () { return (new MText (sb.ToString ())); } public MText ins (int pos, ref MText mt) { insert (pos, mt, 0, mt.nchars); return this; } public MText ins (int pos, ref MText mt, int from, int to) { insert (pos, mt, from, to); return this; } public MText del (int from, int to) { sb.Remove (from, pos_to_idx (this, to) - pos_to_idx (this, from)); nchars -= to - from; return this; } } public class MTextProperty { } }