| 44 | | } |
|---|
| 45 | | |
|---|
| 46 | | alias ValueWrapperT!(bool) ValueWrapperBool; |
|---|
| 47 | | alias ValueWrapperT!(int) ValueWrapperInt; |
|---|
| 48 | | alias ValueWrapperT!(long) ValueWrapperLong; |
|---|
| | 63 | public int opEquals( T other ){ |
|---|
| | 64 | return value == other; |
|---|
| | 65 | } |
|---|
| | 66 | } |
|---|
| | 67 | |
|---|
| | 68 | class Boolean : ValueWrapperT!(bool) { |
|---|
| | 69 | public static Boolean TRUE; |
|---|
| | 70 | public static Boolean FALSE; |
|---|
| | 71 | public this( bool v ){ |
|---|
| | 72 | super(v); |
|---|
| | 73 | } |
|---|
| | 74 | |
|---|
| | 75 | alias ValueWrapperT!(bool).opEquals opEquals; |
|---|
| | 76 | public int opEquals( int other ){ |
|---|
| | 77 | return value == ( other !is 0 ); |
|---|
| | 78 | } |
|---|
| | 79 | public int opEquals( Object other ){ |
|---|
| | 80 | if( auto o = cast(Boolean)other ){ |
|---|
| | 81 | return value == o.value; |
|---|
| | 82 | } |
|---|
| | 83 | return false; |
|---|
| | 84 | } |
|---|
| | 85 | public bool booleanValue(){ |
|---|
| | 86 | return value; |
|---|
| | 87 | } |
|---|
| | 88 | } |
|---|
| | 89 | |
|---|
| | 90 | alias Boolean ValueWrapperBool; |
|---|
| | 91 | |
|---|
| | 92 | |
|---|
| | 93 | class Byte : ValueWrapperT!(byte) { |
|---|
| | 94 | public static byte parseByte( char[] s ){ |
|---|
| | 95 | try{ |
|---|
| | 96 | int res = tango.text.convert.Integer.parse( s ); |
|---|
| | 97 | if( res < byte.min || res > byte.max ){ |
|---|
| | 98 | throw new NumberFormatException( "out of range" ); |
|---|
| | 99 | } |
|---|
| | 100 | return res; |
|---|
| | 101 | } |
|---|
| | 102 | catch( IllegalArgumentException e ){ |
|---|
| | 103 | throw new NumberFormatException( e ); |
|---|
| | 104 | } |
|---|
| | 105 | } |
|---|
| | 106 | this( byte value ){ |
|---|
| | 107 | super( value ); |
|---|
| | 108 | } |
|---|
| | 109 | } |
|---|
| | 110 | alias Byte ValueWrapperByte; |
|---|
| | 111 | |
|---|
| | 112 | |
|---|
| | 113 | class Integer : ValueWrapperT!(int) { |
|---|
| | 114 | |
|---|
| | 115 | public static int MIN_VALUE = 0x80000000; |
|---|
| | 116 | public static int MAX_VALUE = 0x7fffffff; |
|---|
| | 117 | public static int SIZE = 32; |
|---|
| | 118 | |
|---|
| | 119 | public this ( int value ){ |
|---|
| | 120 | super( value ); |
|---|
| | 121 | } |
|---|
| | 122 | |
|---|
| | 123 | public this ( char[] s ){ |
|---|
| | 124 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 125 | super(0); |
|---|
| | 126 | } |
|---|
| | 127 | |
|---|
| | 128 | public static char[] toString( int i, int radix ){ |
|---|
| | 129 | switch( radix ){ |
|---|
| | 130 | case 2: |
|---|
| | 131 | return toBinaryString(i); |
|---|
| | 132 | case 8: |
|---|
| | 133 | return toOctalString(i); |
|---|
| | 134 | case 10: |
|---|
| | 135 | return toString(i); |
|---|
| | 136 | case 16: |
|---|
| | 137 | return toHexString(i); |
|---|
| | 138 | default: |
|---|
| | 139 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 140 | return null; |
|---|
| | 141 | } |
|---|
| | 142 | } |
|---|
| | 143 | |
|---|
| | 144 | public static char[] toHexString( int i ){ |
|---|
| | 145 | return tango.text.convert.Integer.toString(i, tango.text.convert.Integer.Style.Hex ); |
|---|
| | 146 | } |
|---|
| | 147 | |
|---|
| | 148 | public static char[] toOctalString( int i ){ |
|---|
| | 149 | return tango.text.convert.Integer.toString(i, tango.text.convert.Integer.Style.Octal ); |
|---|
| | 150 | } |
|---|
| | 151 | |
|---|
| | 152 | public static char[] toBinaryString( int i ){ |
|---|
| | 153 | return tango.text.convert.Integer.toString(i, tango.text.convert.Integer.Style.Binary ); |
|---|
| | 154 | } |
|---|
| | 155 | |
|---|
| | 156 | public static char[] toString( int i ){ |
|---|
| | 157 | return tango.text.convert.Integer.toString(i); |
|---|
| | 158 | } |
|---|
| | 159 | |
|---|
| | 160 | public static int parseInt( char[] s, int radix ){ |
|---|
| | 161 | try{ |
|---|
| | 162 | return tango.text.convert.Integer.parse( s, cast(uint)radix ); |
|---|
| | 163 | } |
|---|
| | 164 | catch( IllegalArgumentException e ){ |
|---|
| | 165 | throw new NumberFormatException( e ); |
|---|
| | 166 | } |
|---|
| | 167 | } |
|---|
| | 168 | |
|---|
| | 169 | public static int parseInt( char[] s ){ |
|---|
| | 170 | try{ |
|---|
| | 171 | return tango.text.convert.Integer.parse( s ); |
|---|
| | 172 | } |
|---|
| | 173 | catch( IllegalArgumentException e ){ |
|---|
| | 174 | throw new NumberFormatException( e ); |
|---|
| | 175 | } |
|---|
| | 176 | } |
|---|
| | 177 | |
|---|
| | 178 | public static Integer valueOf( char[] s, int radix ){ |
|---|
| | 179 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 180 | return null; |
|---|
| | 181 | } |
|---|
| | 182 | |
|---|
| | 183 | public static Integer valueOf( char[] s ){ |
|---|
| | 184 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 185 | return null; |
|---|
| | 186 | } |
|---|
| | 187 | |
|---|
| | 188 | public static Integer valueOf( int i ){ |
|---|
| | 189 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 190 | return null; |
|---|
| | 191 | } |
|---|
| | 192 | |
|---|
| | 193 | public byte byteValue(){ |
|---|
| | 194 | return cast(byte)value; |
|---|
| | 195 | } |
|---|
| | 196 | |
|---|
| | 197 | public short shortValue(){ |
|---|
| | 198 | return cast(short)value; |
|---|
| | 199 | } |
|---|
| | 200 | |
|---|
| | 201 | public int intValue(){ |
|---|
| | 202 | return value; |
|---|
| | 203 | } |
|---|
| | 204 | |
|---|
| | 205 | public long longValue(){ |
|---|
| | 206 | return cast(long)value; |
|---|
| | 207 | } |
|---|
| | 208 | |
|---|
| | 209 | public float floatValue(){ |
|---|
| | 210 | return cast(float)value; |
|---|
| | 211 | } |
|---|
| | 212 | |
|---|
| | 213 | public double doubleValue(){ |
|---|
| | 214 | return cast(double)value; |
|---|
| | 215 | } |
|---|
| | 216 | |
|---|
| | 217 | public override hash_t toHash(){ |
|---|
| | 218 | return intValue(); |
|---|
| | 219 | } |
|---|
| | 220 | |
|---|
| | 221 | public override int opEquals( Object obj ){ |
|---|
| | 222 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 223 | return false; |
|---|
| | 224 | } |
|---|
| | 225 | |
|---|
| | 226 | public override char[] toString(){ |
|---|
| | 227 | return tango.text.convert.Integer.toString( value ); |
|---|
| | 228 | } |
|---|
| | 229 | } |
|---|
| | 230 | alias Integer ValueWrapperInt; |
|---|
| | 231 | |
|---|
| | 232 | class Double : ValueWrapperT!(double) { |
|---|
| | 233 | this( double value ){ |
|---|
| | 234 | super(value); |
|---|
| | 235 | } |
|---|
| | 236 | this( char[] str ){ |
|---|
| | 237 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 238 | super(0.0); |
|---|
| | 239 | } |
|---|
| | 240 | public double doubleValue(){ |
|---|
| | 241 | return value; |
|---|
| | 242 | } |
|---|
| | 243 | public static char[] toString( double value ){ |
|---|
| | 244 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 245 | return null; |
|---|
| | 246 | } |
|---|
| | 247 | } |
|---|
| | 248 | |
|---|
| | 249 | class Float : ValueWrapperT!(float) { |
|---|
| | 250 | this( float value ){ |
|---|
| | 251 | super(value); |
|---|
| | 252 | } |
|---|
| | 253 | this( char[] str ){ |
|---|
| | 254 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 255 | super(0.0); |
|---|
| | 256 | } |
|---|
| | 257 | public float floatValue(){ |
|---|
| | 258 | return value; |
|---|
| | 259 | } |
|---|
| | 260 | public static char[] toString( float value ){ |
|---|
| | 261 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 262 | return null; |
|---|
| | 263 | } |
|---|
| | 264 | } |
|---|
| | 265 | class Long : ValueWrapperT!(long) { |
|---|
| | 266 | this( long value ){ |
|---|
| | 267 | super(value); |
|---|
| | 268 | } |
|---|
| | 269 | this( char[] str ){ |
|---|
| | 270 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 271 | super(0); |
|---|
| | 272 | } |
|---|
| | 273 | public long longValue(){ |
|---|
| | 274 | return value; |
|---|
| | 275 | } |
|---|
| | 276 | public static long parseLong(char[] s){ |
|---|
| | 277 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 278 | return 0; |
|---|
| | 279 | } |
|---|
| | 280 | public static char[] toString( double value ){ |
|---|
| | 281 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 282 | return null; |
|---|
| | 283 | } |
|---|
| | 284 | } |
|---|
| | 285 | alias Long ValueWrapperLong; |
|---|
| | 286 | |
|---|
| | 287 | |
|---|
| | 288 | // alias ValueWrapperT!(int) ValueWrapperInt; |
|---|
| | 746 | // import tango.core.Runtime; |
|---|
| | 747 | private uint calcKey( void* key ){ |
|---|
| | 748 | uint k = cast(uint)cast(void*)key; |
|---|
| | 749 | k ^= 0x8000_0000; |
|---|
| | 750 | return k; |
|---|
| | 751 | } |
|---|
| | 752 | |
|---|
| | 753 | // private bool collectHandler(Object o){ |
|---|
| | 754 | // uint key = calcKey( cast(void*)o ); |
|---|
| | 755 | // if( auto p = key in mKeyCollectedNotifiers ){ |
|---|
| | 756 | // (*p)( key ); |
|---|
| | 757 | // mKeyCollectedNotifiers.remove( key ); |
|---|
| | 758 | // } |
|---|
| | 759 | // ClassInfo ci = o.classinfo; |
|---|
| | 760 | // while(ci !is null ){ |
|---|
| | 761 | // foreach( i; ci.interfaces ){ |
|---|
| | 762 | // uint key = calcKey( cast(void*)o + i.offset ); |
|---|
| | 763 | // if( auto p = key in mKeyCollectedNotifiers ){ |
|---|
| | 764 | // (*p)( key ); |
|---|
| | 765 | // mKeyCollectedNotifiers.remove( key ); |
|---|
| | 766 | // } |
|---|
| | 767 | // } |
|---|
| | 768 | // ci = ci.base; |
|---|
| | 769 | // } |
|---|
| | 770 | // return true; |
|---|
| | 771 | // } |
|---|
| | 772 | // |
|---|
| | 773 | // static this(){ |
|---|
| | 774 | // Runtime.collectHandler( & collectHandler ); |
|---|
| | 775 | // } |
|---|
| | 776 | // |
|---|
| | 777 | // void delegate( uint k ) KeyCollectedNotifier; |
|---|
| | 778 | // KeyCollectedNotifier[ uint ] mKeyCollectedNotifiers; |
|---|
| | 779 | // |
|---|
| | 780 | // private synchronized void addKeyCollectedNotifier( uint key, KeyCollectedNotifier del ){ |
|---|
| | 781 | // mKeyCollectedNotifiers[ key ] = del; |
|---|
| | 782 | // } |
|---|
| | 783 | |
|---|
| | 784 | class WeakHashMap(K,T) { |
|---|
| | 785 | static assert( is(K==class) || is(K==interface) ); |
|---|
| | 786 | T[uint] data; |
|---|
| | 787 | |
|---|
| | 788 | private void removeInternalKey( uint key ){ |
|---|
| | 789 | data.remove( key ); |
|---|
| | 790 | } |
|---|
| | 791 | |
|---|
| | 792 | public void add (K key, T element){ |
|---|
| | 793 | data[ calcKey(cast(void*)key) ] = element; |
|---|
| | 794 | // addKeyCollectedNotifier( calcKey(key), &removeInternalKey ); |
|---|
| | 795 | } |
|---|
| | 796 | public void removeKey (K key){ |
|---|
| | 797 | data.remove( calcKey(cast(void*)key) ); |
|---|
| | 798 | } |
|---|
| | 799 | public T get(K key){ |
|---|
| | 800 | if( auto p = calcKey(cast(void*)key) in data ){ |
|---|
| | 801 | return *p; |
|---|
| | 802 | } |
|---|
| | 803 | return null; |
|---|
| | 804 | } |
|---|
| | 805 | } |
|---|
| | 806 | |
|---|
| | 807 | import dwt.dwthelper.InputStream; |
|---|
| | 808 | InputStream ClassInfoGetResourceAsStream( ClassInfo ci, char[] aName ){ |
|---|
| | 809 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 810 | return null; |
|---|
| | 811 | } |
|---|
| | 812 | |
|---|
| | 813 | void ExceptionPrintStackTrace( Exception e ){ |
|---|
| | 814 | ExceptionPrintStackTrace( e, Stderr ); |
|---|
| | 815 | } |
|---|
| | 816 | void ExceptionPrintStackTrace( Exception e, Print!(char) print ){ |
|---|
| | 817 | print.formatln( "Exception in {}({}): {}", e.file, e.line, e.msg ); |
|---|
| | 818 | } |
|---|
| | 819 | |
|---|
| | 820 | bool ArrayEquals(T)( T[] a, T[] b ){ |
|---|
| | 821 | if( a.length !is b.length ){ |
|---|
| | 822 | return false; |
|---|
| | 823 | } |
|---|
| | 824 | for( int i = 0; i < a.length; i++ ){ |
|---|
| | 825 | static if( is( T==class) || is(T==interface)){ |
|---|
| | 826 | if( a[i] !is null && b[i] !is null ){ |
|---|
| | 827 | if( a[i] != b[i] ){ |
|---|
| | 828 | return false; |
|---|
| | 829 | } |
|---|
| | 830 | } |
|---|
| | 831 | else if( a[i] is null && b[i] is null ){ |
|---|
| | 832 | } |
|---|
| | 833 | else{ |
|---|
| | 834 | return false; |
|---|
| | 835 | } |
|---|
| | 836 | } |
|---|
| | 837 | else{ |
|---|
| | 838 | if( a[i] != b[i] ){ |
|---|
| | 839 | return false; |
|---|
| | 840 | } |
|---|
| | 841 | } |
|---|
| | 842 | } |
|---|
| | 843 | } |
|---|
| | 844 | |
|---|
| | 845 | interface Reader{ |
|---|
| | 846 | } |
|---|
| | 847 | interface Writer{ |
|---|
| | 848 | } |
|---|
| | 849 | |
|---|
| | 850 | |
|---|
| | 851 | class Collator : Comparator { |
|---|
| | 852 | public static Collator getInstance(){ |
|---|
| | 853 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 854 | return null; |
|---|
| | 855 | } |
|---|
| | 856 | private this(){ |
|---|
| | 857 | } |
|---|
| | 858 | int compare(Object o1, Object o2){ |
|---|
| | 859 | implMissing( __FILE__, __LINE__ ); |
|---|
| | 860 | return 0; |
|---|
| | 861 | } |
|---|
| | 862 | } |
|---|
| | 863 | |
|---|
| | 864 | interface Enumeration { |
|---|
| | 865 | public bool hasMoreElements(); |
|---|
| | 866 | public Object nextElement(); |
|---|
| | 867 | } |
|---|
| | 868 | |
|---|
| | 869 | |
|---|
| | 870 | template arraycast(T) { |
|---|
| | 871 | T[] arraycast(U) (U[] u) { |
|---|
| | 872 | static if ( |
|---|
| | 873 | (is (T == interface ) && is (U == interface )) || |
|---|
| | 874 | (is (T == class ) && is (U == class ))) { |
|---|
| | 875 | return(cast(T[])u); |
|---|
| | 876 | } |
|---|
| | 877 | else { |
|---|
| | 878 | int l = u.length; |
|---|
| | 879 | T[] res; |
|---|
| | 880 | res.length = l; |
|---|
| | 881 | for (int i = 0; i < l; i++) { |
|---|
| | 882 | res[i] = cast(T)u[i]; |
|---|
| | 883 | } |
|---|
| | 884 | return(res); |
|---|
| | 885 | } |
|---|
| | 886 | } |
|---|
| | 887 | } |
|---|
| | 888 | |
|---|
| | 889 | char[] stringcast( Object o ){ |
|---|
| | 890 | if( auto str = cast(ArrayWrapperString) o ){ |
|---|
| | 891 | return str.array; |
|---|
| | 892 | } |
|---|
| | 893 | return null; |
|---|
| | 894 | } |
|---|
| | 895 | char[][] stringcast( Object[] objs ){ |
|---|
| | 896 | char[][] res = new char[][](objs.length); |
|---|
| | 897 | foreach( idx, obj; objs ){ |
|---|
| | 898 | res[idx] = stringcast(obj); |
|---|
| | 899 | } |
|---|
| | 900 | return res; |
|---|
| | 901 | } |
|---|
| | 902 | ArrayWrapperString stringcast( char[] str ){ |
|---|
| | 903 | return new ArrayWrapperString( str ); |
|---|
| | 904 | } |
|---|
| | 905 | ArrayWrapperString[] stringcast( char[][] strs ){ |
|---|
| | 906 | ArrayWrapperString[] res = new ArrayWrapperString[ strs.length ]; |
|---|
| | 907 | foreach( idx, str; strs ){ |
|---|
| | 908 | res[idx] = stringcast(str); |
|---|
| | 909 | } |
|---|
| | 910 | return res; |
|---|
| | 911 | } |
|---|
| | 912 | |
|---|
| | 913 | |
|---|
| | 914 | class Arrays{ |
|---|
| | 915 | public static bool equals(Object[] a, Object[] b){ |
|---|
| | 916 | if( a.length !is b.length ){ |
|---|
| | 917 | return false; |
|---|
| | 918 | } |
|---|
| | 919 | for( int i = 0; i < a.length; i++ ){ |
|---|
| | 920 | if( a[i] is null && b[i] is null ){ |
|---|
| | 921 | continue; |
|---|
| | 922 | } |
|---|
| | 923 | if( a[i] !is null && b[i] !is null && a[i] == b[i] ){ |
|---|
| | 924 | continue; |
|---|
| | 925 | } |
|---|
| | 926 | return false; |
|---|
| | 927 | } |
|---|
| | 928 | return true; |
|---|
| | 929 | } |
|---|
| | 930 | } |
|---|
| | 931 | |
|---|
| | 932 | int SeqIndexOf(T)( tango.util.collection.model.Seq.Seq!(T) s, T src ){ |
|---|
| | 933 | int idx; |
|---|
| | 934 | foreach( e; s ){ |
|---|
| | 935 | if( e == src ){ |
|---|
| | 936 | return idx; |
|---|
| | 937 | } |
|---|
| | 938 | idx++; |
|---|
| | 939 | } |
|---|
| | 940 | return -1; |
|---|
| | 941 | } |
|---|
| | 942 | |
|---|
| | 943 | /++ |
|---|
| | 944 | + Decode XML entities into UTF8 string. |
|---|
| | 945 | + Eg. "&" -> "&", "&" -> "&", "&" -> "&" |
|---|
| | 946 | + Throws TextException on failure |
|---|
| | 947 | + The given string is modified. |
|---|
| | 948 | +/ |
|---|
| | 949 | char[] xmlUnescape( char[] str ){ |
|---|
| | 950 | |
|---|
| | 951 | void error(){ |
|---|
| | 952 | throw new TextException( "xmlUnescape" ); |
|---|
| | 953 | } |
|---|
| | 954 | // < ... |
|---|
| | 955 | // Ӓ |
|---|
| | 956 | // ኯ |
|---|
| | 957 | char[] src = str; |
|---|
| | 958 | char[] trg = str; |
|---|
| | 959 | while( src.length ){ |
|---|
| | 960 | if( src[0] !is '&' ){ |
|---|
| | 961 | trg[0] = src[0]; |
|---|
| | 962 | trg = trg[1..$]; |
|---|
| | 963 | src = src[1..$]; |
|---|
| | 964 | } |
|---|
| | 965 | else{ |
|---|
| | 966 | src = src[1..$]; // go past '&' |
|---|
| | 967 | if( src.length < 2 ) error(); |
|---|
| | 968 | |
|---|
| | 969 | // search semi |
|---|
| | 970 | int len = Math.min( src.length, 10 ); // limit semi search to possible longest entityname |
|---|
| | 971 | int semi = tango.text.Util.locate( src[0 .. len ], ';' ); |
|---|
| | 972 | if( semi is len ) error(); // no semi found |
|---|
| | 973 | |
|---|
| | 974 | char[] entityName = src[ 0 .. semi ]; // name without semi |
|---|
| | 975 | dchar entityValue = 0; |
|---|
| | 976 | switch( entityName ){ |
|---|
| | 977 | case "lt": entityValue = '<'; break; |
|---|
| | 978 | case "gt": entityValue = '>'; break; |
|---|
| | 979 | case "amp": entityValue = '&'; break; |
|---|
| | 980 | case "quot": entityValue = '\"'; break; |
|---|
| | 981 | case "apos": entityValue = '\''; break; |
|---|
| | 982 | default: |
|---|
| | 983 | if( entityName[0] is 'x' ){ |
|---|
| | 984 | if( semi < 2 ) error(); |
|---|
| | 985 | if( semi > 9 ) error(); |
|---|
| | 986 | foreach( hex; entityName[1..$] ){ |
|---|
| | 987 | entityValue <<= 4; |
|---|
| | 988 | if( hex >= '0' && hex <= '9' ){ |
|---|
| | 989 | entityValue |= ( hex - '0' ); |
|---|
| | 990 | } |
|---|
| | 991 | else if( hex >= 'a' && hex <= 'f' ){ |
|---|
| | 992 | entityValue |= ( hex - 'a' ); |
|---|
| | 993 | } |
|---|
| | 994 | else if( hex >= 'A' && hex <= 'F' ){ |
|---|
| | 995 | entityValue |= ( hex - 'A' ); |
|---|
| | 996 | } |
|---|
| | 997 | else{ |
|---|
| | 998 | error(); |
|---|
| | 999 | } |
|---|
| | 1000 | } |
|---|
| | 1001 | } |
|---|
| | 1002 | else{ |
|---|
| | 1003 | if( semi < 1 ) error(); |
|---|
| | 1004 | if( semi > 9 ) error(); |
|---|
| | 1005 | foreach( dec; entityName[1..$] ){ |
|---|
| | 1006 | if( dec >= '0' && dec <= '9' ){ |
|---|
| | 1007 | entityValue *= 10; |
|---|
| | 1008 | entityValue += ( dec - '0' ); |
|---|
| | 1009 | } |
|---|
| | 1010 | else{ |
|---|
| | 1011 | error(); |
|---|
| | 1012 | } |
|---|
| | 1013 | } |
|---|
| | 1014 | } |
|---|
| | 1015 | } |
|---|
| | 1016 | dchar[1] arr; |
|---|
| | 1017 | arr[0] = entityValue; |
|---|
| | 1018 | uint ate = 0; |
|---|
| | 1019 | char[] res = tango.text.convert.Utf.toString( arr, trg, &ate ); |
|---|
| | 1020 | trg = trg[ res.length .. $ ]; |
|---|
| | 1021 | src = src[ semi +1 .. $ ]; // go past semi |
|---|
| | 1022 | } |
|---|
| | 1023 | } |
|---|
| | 1024 | return str[ 0 .. trg.ptr-str.ptr ]; |
|---|
| | 1025 | } |
|---|
| | 1026 | |
|---|
| | 1027 | |
|---|
| | 1028 | /++ |
|---|
| | 1029 | + Encode XML entities into UTF8 string. |
|---|
| | 1030 | + First checks if processing is needed. |
|---|
| | 1031 | + If not, the original string is returned. |
|---|
| | 1032 | + If processing is needed, a new string is allocated. |
|---|
| | 1033 | +/ |
|---|
| | 1034 | char[] xmlEscape( char[] xml ){ |
|---|
| | 1035 | bool needsReplacement( dchar c ){ |
|---|
| | 1036 | switch( c ){ |
|---|
| | 1037 | case '<': |
|---|
| | 1038 | case '>': |
|---|
| | 1039 | case '&': |
|---|
| | 1040 | case '\"': |
|---|
| | 1041 | case '\'': |
|---|
| | 1042 | case '\r': |
|---|
| | 1043 | case '\n': |
|---|
| | 1044 | case '\u0009': |
|---|
| | 1045 | return true; |
|---|
| | 1046 | default: |
|---|
| | 1047 | return c > 0x7F; |
|---|
| | 1048 | } |
|---|
| | 1049 | } |
|---|
| | 1050 | |
|---|
| | 1051 | // Check if processing is needed |
|---|
| | 1052 | foreach( char c; xml ){ |
|---|
| | 1053 | if( needsReplacement( c )){ |
|---|
| | 1054 | goto Lprocess; |
|---|
| | 1055 | } |
|---|
| | 1056 | } |
|---|
| | 1057 | return xml; |
|---|
| | 1058 | Lprocess: |
|---|
| | 1059 | |
|---|
| | 1060 | // yes, do a new string, start with +20 chars |
|---|
| | 1061 | char[] res = new char[ xml.length + 20 ]; |
|---|
| | 1062 | res.length = 0; |
|---|
| | 1063 | |
|---|
| | 1064 | foreach( dchar c; xml ){ |
|---|
| | 1065 | |
|---|
| | 1066 | if( !needsReplacement( c )){ |
|---|
| | 1067 | res ~= c; |
|---|
| | 1068 | } |
|---|
| | 1069 | else{ |
|---|
| | 1070 | res ~= '&'; |
|---|
| | 1071 | switch( c ){ |
|---|
| | 1072 | case '<': res ~= "lt"; break; |
|---|
| | 1073 | case '>': res ~= "gt"; break; |
|---|
| | 1074 | case '&': res ~= "amp"; break; |
|---|
| | 1075 | case '\"': res ~= "quot"; break; |
|---|
| | 1076 | case '\'': res ~= "apos"; break; |
|---|
| | 1077 | case '\r': case '\n': case '\u0009': |
|---|
| | 1078 | default: |
|---|
| | 1079 | char toHexDigit( int i ){ |
|---|
| | 1080 | if( i < 10 ) return '0'+i; |
|---|
| | 1081 | return 'A'+i-10; |
|---|
| | 1082 | } |
|---|
| | 1083 | res ~= "#x"; |
|---|
| | 1084 | if( c <= 0xFF ){ |
|---|
| | 1085 | res ~= toHexDigit(( c >> 4 ) & 0x0F ); |
|---|
| | 1086 | res ~= toHexDigit(( c >> 0 ) & 0x0F ); |
|---|
| | 1087 | } |
|---|
| | 1088 | else if( c <= 0xFFFF ){ |
|---|
| | 1089 | res ~= toHexDigit(( c >> 12 ) & 0x0F ); |
|---|
| | 1090 | res ~= toHexDigit(( c >> 8 ) & 0x0F ); |
|---|
| | 1091 | res ~= toHexDigit(( c >> 4 ) & 0x0F ); |
|---|
| | 1092 | res ~= toHexDigit(( c >> 0 ) & 0x0F ); |
|---|
| | 1093 | } |
|---|
| | 1094 | else if( c <= 0xFFFFFF ){ |
|---|
| | 1095 | res ~= toHexDigit(( c >> 20 ) & 0x0F ); |
|---|
| | 1096 | res ~= toHexDigit(( c >> 16 ) & 0x0F ); |
|---|
| | 1097 | res ~= toHexDigit(( c >> 12 ) & 0x0F ); |
|---|
| | 1098 | res ~= toHexDigit(( c >> 8 ) & 0x0F ); |
|---|
| | 1099 | res ~= toHexDigit(( c >> 4 ) & 0x0F ); |
|---|
| | 1100 | res ~= toHexDigit(( c >> 0 ) & 0x0F ); |
|---|
| | 1101 | } |
|---|
| | 1102 | else { |
|---|
| | 1103 | res ~= toHexDigit(( c >> 28 ) & 0x0F ); |
|---|
| | 1104 | res ~= toHexDigit(( c >> 24 ) & 0x0F ); |
|---|
| | 1105 | res ~= toHexDigit(( c >> 20 ) & 0x0F ); |
|---|
| | 1106 | res ~= toHexDigit(( c >> 16 ) & 0x0F ); |
|---|
| | 1107 | res ~= toHexDigit(( c >> 12 ) & 0x0F ); |
|---|
| | 1108 | res ~= toHexDigit(( c >> 8 ) & 0x0F ); |
|---|
| | 1109 | res ~= toHexDigit(( c >> 4 ) & 0x0F ); |
|---|
| | 1110 | res ~= toHexDigit(( c >> 0 ) & 0x0F ); |
|---|
| | 1111 | } |
|---|
| | 1112 | break; |
|---|
| | 1113 | } |
|---|
| | 1114 | res ~= ';'; |
|---|
| | 1115 | } |
|---|
| | 1116 | } |
|---|
| | 1117 | } |
|---|
| | 1118 | |
|---|
| | 1119 | int arrayIndexOf(T)( T[] arr, T v ){ |
|---|
| | 1120 | int res = -1; |
|---|
| | 1121 | int idx = 0; |
|---|
| | 1122 | foreach( p; arr ){ |
|---|
| | 1123 | if( p == v){ |
|---|
| | 1124 | res = idx; |
|---|
| | 1125 | break; |
|---|
| | 1126 | } |
|---|
| | 1127 | idx++; |
|---|
| | 1128 | } |
|---|
| | 1129 | return res; |
|---|
| | 1130 | } |
|---|
| | 1131 | |
|---|
| | 1132 | int seqIndexOf( tango.util.collection.model.Seq.Seq!(Object) seq, Object v ){ |
|---|
| | 1133 | int res = -1; |
|---|
| | 1134 | int idx = 0; |
|---|
| | 1135 | foreach( p; seq ){ |
|---|
| | 1136 | if( p == v){ |
|---|
| | 1137 | res = idx; |
|---|
| | 1138 | break; |
|---|
| | 1139 | } |
|---|
| | 1140 | idx++; |
|---|
| | 1141 | } |
|---|
| | 1142 | return res; |
|---|
| | 1143 | } |
|---|
| | 1144 | |
|---|
| | 1145 | |
|---|