| | 896 | * Append dchar to char[] |
|---|
| | 897 | */ |
|---|
| | 898 | extern (C) char[] _d_arrayappendcd(ref char[] x, dchar c) |
|---|
| | 899 | { |
|---|
| | 900 | const sizeelem = c.sizeof; // array element size |
|---|
| | 901 | auto info = gc_query(x.ptr); |
|---|
| | 902 | auto length = x.length; |
|---|
| | 903 | |
|---|
| | 904 | // c could encode into from 1 to 4 characters |
|---|
| | 905 | int nchars; |
|---|
| | 906 | if (c <= 0x7F) |
|---|
| | 907 | nchars = 1; |
|---|
| | 908 | else if (c <= 0x7FF) |
|---|
| | 909 | nchars = 2; |
|---|
| | 910 | else if (c <= 0xFFFF) |
|---|
| | 911 | nchars = 3; |
|---|
| | 912 | else if (c <= 0x10FFFF) |
|---|
| | 913 | nchars = 4; |
|---|
| | 914 | else |
|---|
| | 915 | assert(0); // invalid utf character - should we throw an exception instead? |
|---|
| | 916 | |
|---|
| | 917 | auto newlength = length + nchars; |
|---|
| | 918 | auto newsize = newlength * sizeelem; |
|---|
| | 919 | |
|---|
| | 920 | assert(info.size == 0 || length * sizeelem <= info.size); |
|---|
| | 921 | |
|---|
| | 922 | debug(PRINTF) printf("_d_arrayappendcd(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, info.size); |
|---|
| | 923 | |
|---|
| | 924 | if (info.size <= newsize || info.base != x.ptr) |
|---|
| | 925 | { byte* newdata; |
|---|
| | 926 | |
|---|
| | 927 | if (info.size >= PAGESIZE && info.base == x.ptr) |
|---|
| | 928 | { // Try to extend in-place |
|---|
| | 929 | auto u = gc_extend(x.ptr, (newsize + 1) - info.size, (newsize + 1) - info.size); |
|---|
| | 930 | if (u) |
|---|
| | 931 | { |
|---|
| | 932 | goto L1; |
|---|
| | 933 | } |
|---|
| | 934 | } |
|---|
| | 935 | debug(PRINTF) printf("_d_arrayappendcd(length = %d, newlength = %d, cap = %d)\n", length, newlength, info.size); |
|---|
| | 936 | auto newcap = newCapacity(newlength, sizeelem); |
|---|
| | 937 | assert(newcap >= newlength * sizeelem); |
|---|
| | 938 | newdata = cast(byte *)gc_malloc(newcap + 1, BlkAttr.NO_SCAN); |
|---|
| | 939 | memcpy(newdata, x.ptr, length * sizeelem); |
|---|
| | 940 | (cast(void**)(&x))[1] = newdata; |
|---|
| | 941 | } |
|---|
| | 942 | L1: |
|---|
| | 943 | *cast(size_t *)&x = newlength; |
|---|
| | 944 | char* ptr = &x.ptr[length]; |
|---|
| | 945 | |
|---|
| | 946 | if (c <= 0x7F) |
|---|
| | 947 | { |
|---|
| | 948 | ptr[0] = cast(char) c; |
|---|
| | 949 | } |
|---|
| | 950 | else if (c <= 0x7FF) |
|---|
| | 951 | { |
|---|
| | 952 | ptr[0] = cast(char)(0xC0 | (c >> 6)); |
|---|
| | 953 | ptr[1] = cast(char)(0x80 | (c & 0x3F)); |
|---|
| | 954 | } |
|---|
| | 955 | else if (c <= 0xFFFF) |
|---|
| | 956 | { |
|---|
| | 957 | ptr[0] = cast(char)(0xE0 | (c >> 12)); |
|---|
| | 958 | ptr[1] = cast(char)(0x80 | ((c >> 6) & 0x3F)); |
|---|
| | 959 | ptr[2] = cast(char)(0x80 | (c & 0x3F)); |
|---|
| | 960 | } |
|---|
| | 961 | else if (c <= 0x10FFFF) |
|---|
| | 962 | { |
|---|
| | 963 | ptr[0] = cast(char)(0xF0 | (c >> 18)); |
|---|
| | 964 | ptr[1] = cast(char)(0x80 | ((c >> 12) & 0x3F)); |
|---|
| | 965 | ptr[2] = cast(char)(0x80 | ((c >> 6) & 0x3F)); |
|---|
| | 966 | ptr[3] = cast(char)(0x80 | (c & 0x3F)); |
|---|
| | 967 | } |
|---|
| | 968 | else |
|---|
| | 969 | assert(0); |
|---|
| | 970 | |
|---|
| | 971 | assert((cast(size_t)x.ptr & 15) == 0); |
|---|
| | 972 | assert(gc_sizeOf(x.ptr) > x.length * sizeelem); |
|---|
| | 973 | return x; |
|---|
| | 974 | } |
|---|
| | 975 | |
|---|
| | 976 | |
|---|
| | 977 | /** |
|---|
| | 978 | * Append dchar to wchar[] |
|---|
| | 979 | */ |
|---|
| | 980 | extern (C) wchar[] _d_arrayappendwd(ref wchar[] x, dchar c) |
|---|
| | 981 | { |
|---|
| | 982 | const sizeelem = c.sizeof; // array element size |
|---|
| | 983 | auto info = gc_query(x.ptr); |
|---|
| | 984 | auto length = x.length; |
|---|
| | 985 | |
|---|
| | 986 | // c could encode into from 1 to 2 w characters |
|---|
| | 987 | int nchars; |
|---|
| | 988 | if (c <= 0xFFFF) |
|---|
| | 989 | nchars = 1; |
|---|
| | 990 | else |
|---|
| | 991 | nchars = 2; |
|---|
| | 992 | |
|---|
| | 993 | auto newlength = length + nchars; |
|---|
| | 994 | auto newsize = newlength * sizeelem; |
|---|
| | 995 | |
|---|
| | 996 | assert(info.size == 0 || length * sizeelem <= info.size); |
|---|
| | 997 | |
|---|
| | 998 | debug(PRINTF) printf("_d_arrayappendwd(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, info.size); |
|---|
| | 999 | |
|---|
| | 1000 | if (info.size <= newsize || info.base != x.ptr) |
|---|
| | 1001 | { byte* newdata; |
|---|
| | 1002 | |
|---|
| | 1003 | if (info.size >= PAGESIZE && info.base == x.ptr) |
|---|
| | 1004 | { // Try to extend in-place |
|---|
| | 1005 | auto u = gc_extend(x.ptr, (newsize + 1) - info.size, (newsize + 1) - info.size); |
|---|
| | 1006 | if (u) |
|---|
| | 1007 | { |
|---|
| | 1008 | goto L1; |
|---|
| | 1009 | } |
|---|
| | 1010 | } |
|---|
| | 1011 | debug(PRINTF) printf("_d_arrayappendwd(length = %d, newlength = %d, cap = %d)\n", length, newlength, info.size); |
|---|
| | 1012 | auto newcap = newCapacity(newlength, sizeelem); |
|---|
| | 1013 | assert(newcap >= newlength * sizeelem); |
|---|
| | 1014 | newdata = cast(byte *)gc_malloc(newcap + 1, BlkAttr.NO_SCAN); |
|---|
| | 1015 | memcpy(newdata, x.ptr, length * sizeelem); |
|---|
| | 1016 | (cast(void**)(&x))[1] = newdata; |
|---|
| | 1017 | } |
|---|
| | 1018 | L1: |
|---|
| | 1019 | *cast(size_t *)&x = newlength; |
|---|
| | 1020 | wchar* ptr = &x.ptr[length]; |
|---|
| | 1021 | |
|---|
| | 1022 | if (c <= 0xFFFF) |
|---|
| | 1023 | { |
|---|
| | 1024 | ptr[0] = cast(wchar) c; |
|---|
| | 1025 | } |
|---|
| | 1026 | else |
|---|
| | 1027 | { |
|---|
| | 1028 | ptr[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); |
|---|
| | 1029 | ptr[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00); |
|---|
| | 1030 | } |
|---|
| | 1031 | |
|---|
| | 1032 | assert((cast(size_t)x.ptr & 15) == 0); |
|---|
| | 1033 | assert(gc_sizeOf(x.ptr) > x.length * sizeelem); |
|---|
| | 1034 | return x; |
|---|
| | 1035 | } |
|---|
| | 1036 | |
|---|
| | 1037 | |
|---|
| | 1038 | /** |
|---|