diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2023-03-05 01:47:19 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2023-03-16 17:29:57 +0100 |
commit | 8da8c7d337123b28fdeb539a283d00732118712e (patch) | |
tree | 74096a23b9e2f64a7e25ec1e8d4d3b1d8934842e /libphobos | |
parent | c5e2c3dd6afcf9b152df72b30e205b0180c0afd5 (diff) | |
download | gcc-8da8c7d337123b28fdeb539a283d00732118712e.zip gcc-8da8c7d337123b28fdeb539a283d00732118712e.tar.gz gcc-8da8c7d337123b28fdeb539a283d00732118712e.tar.bz2 |
d: Merge upstream dmd, druntime 4ca4140e58, phobos 454dff14d.
D front-end changes:
- Import dmd v2.103.0-beta.1.
- Using `alias this' for classes has been deprecated.
- The feature `-fpreview=dip25` is now enabled by default.
- The compile-time traits `isVirtualFunction' and
`getVirtualFunctions' have been deprecated.
D runtime changes:
- Import druntime v2.103.0-beta.1.
Phobos changes:
- Import phobos v2.103.0-beta.1.
- Updated unicode grapheme walking updated to conform to Unicode
version 15.
- Improved friendliness of error messages when instantiating
`std.algorithm.iteration.joiner' and
`std.algorithm.sorting.sort' with wrong inputs.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd 4ca4140e58.
* dmd/VERSION: Bump version to v2.103.0-beta.1.
* Make-lang.in (D_FRONTEND_OBJS): Add d/errorsink.o.
* d-ctfloat.cc (CTFloat::sprint): Update signature for new front-end
interface.
* d-frontend.cc (getTypeInfoType): Likewise.
* d-lang.cc (d_handle_option): Remove handling of -fpreview=dip25 and
-frevert=dip25.
(d_post_options): Remove enabling of sealed references language
feature when scoped pointers is enabled.
* d-tree.h (create_typeinfo): Update signature.
* decl.cc (DeclVisitor::finish_vtable): Update for new front-end
interface.
(DeclVisitor::visit (VarDeclaration *)): Likewise.
(DeclVisitor::visit (FuncDeclaration *)): Check skipCodegen to see if
front-end explicitly requested not to generate code.
* expr.cc (ExprVisitor::visit (NewExp *)): Update for new front-end
interface.
* lang.opt (fpreview=dip25): Remove.
(frevert=dip25): Remove.
* modules.cc (layout_moduleinfo_fields): Update for new front-end
interface.
(layout_moduleinfo): Likewise.
* runtime.def (NEWCLASS): Remove.
* toir.cc (IRVisitor::visit (IfStatement *)): Don't generate IR for if
statement list when condition is `__ctfe'.
* typeinfo.cc (create_typeinfo): Add generate parameter.
* types.cc (layout_aggregate_members): Update for new front-end
interface.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime 4ca4140e58.
* libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add core/factory.d.
* libdruntime/Makefile.in: Regenerate.
* src/MERGE: Merge upstream phobos 454dff14d.
* testsuite/libphobos.hash/test_hash.d: Update test.
* testsuite/libphobos.shared/finalize.d: Update test.
* libdruntime/core/factory.d: New file.
gcc/testsuite/ChangeLog:
* gdc.dg/torture/simd23084.d: New test.
* gdc.dg/torture/simd23085.d: New test.
* gdc.dg/torture/simd23218.d: New test.
Diffstat (limited to 'libphobos')
65 files changed, 1814 insertions, 896 deletions
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index ac3dd12..269eebf 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -09faa4eacd4fb147107e94eeebf56b3a73fdcc05 +4ca4140e584c055a8a9bc727e56a97ebcecd61e0 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am index 18154de..8225ba4 100644 --- a/libphobos/libdruntime/Makefile.am +++ b/libphobos/libdruntime/Makefile.am @@ -169,7 +169,7 @@ DRUNTIME_CSOURCES = core/stdc/errno_.c DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \ - core/exception.d core/gc/config.d core/gc/gcinterface.d \ + core/exception.d core/factory.d core/gc/config.d core/gc/gcinterface.d \ core/gc/registry.d core/int128.d core/internal/abort.d \ core/internal/array/appending.d core/internal/array/arrayassign.d \ core/internal/array/capacity.d core/internal/array/casting.d \ diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in index 3f04496..797d643 100644 --- a/libphobos/libdruntime/Makefile.in +++ b/libphobos/libdruntime/Makefile.in @@ -189,9 +189,10 @@ am__DEPENDENCIES_1 = am__dirstamp = $(am__leading_dot)dirstamp am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \ core/builtins.lo core/checkedint.lo core/cpuid.lo \ - core/demangle.lo core/exception.lo core/gc/config.lo \ - core/gc/gcinterface.lo core/gc/registry.lo core/int128.lo \ - core/internal/abort.lo core/internal/array/appending.lo \ + core/demangle.lo core/exception.lo core/factory.lo \ + core/gc/config.lo core/gc/gcinterface.lo core/gc/registry.lo \ + core/int128.lo core/internal/abort.lo \ + core/internal/array/appending.lo \ core/internal/array/arrayassign.lo \ core/internal/array/capacity.lo core/internal/array/casting.lo \ core/internal/array/comparison.lo \ @@ -838,7 +839,7 @@ libgdruntime_convenience_la_LINK = $(libgdruntime_la_LINK) DRUNTIME_CSOURCES = core/stdc/errno_.c DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \ - core/exception.d core/gc/config.d core/gc/gcinterface.d \ + core/exception.d core/factory.d core/gc/config.d core/gc/gcinterface.d \ core/gc/registry.d core/int128.d core/internal/abort.d \ core/internal/array/appending.d core/internal/array/arrayassign.d \ core/internal/array/capacity.d core/internal/array/casting.d \ @@ -1188,6 +1189,7 @@ core/checkedint.lo: core/$(am__dirstamp) core/cpuid.lo: core/$(am__dirstamp) core/demangle.lo: core/$(am__dirstamp) core/exception.lo: core/$(am__dirstamp) +core/factory.lo: core/$(am__dirstamp) core/gc/$(am__dirstamp): @$(MKDIR_P) core/gc @: > core/gc/$(am__dirstamp) diff --git a/libphobos/libdruntime/core/attribute.d b/libphobos/libdruntime/core/attribute.d index 8a1dc8a..c2a7c33 100644 --- a/libphobos/libdruntime/core/attribute.d +++ b/libphobos/libdruntime/core/attribute.d @@ -236,9 +236,9 @@ version (UdaGNUAbiTag) struct gnuAbiTag { string[] tags; - this(string[] tags...) + this(string[] tags...) @safe pure nothrow { - this.tags = tags; + this.tags = tags.dup; } } diff --git a/libphobos/libdruntime/core/cpuid.d b/libphobos/libdruntime/core/cpuid.d index 1c2ac06..b79bd1d 100644 --- a/libphobos/libdruntime/core/cpuid.d +++ b/libphobos/libdruntime/core/cpuid.d @@ -1080,7 +1080,7 @@ void cpuidSparc() } */ -shared static this() +pragma(crt_constructor) void cpuid_initialization() { auto cf = getCpuFeatures(); diff --git a/libphobos/libdruntime/core/demangle.d b/libphobos/libdruntime/core/demangle.d index fe27331..3fcb266 100644 --- a/libphobos/libdruntime/core/demangle.d +++ b/libphobos/libdruntime/core/demangle.d @@ -801,7 +801,7 @@ pure @safe: TypeTuple: B Number Arguments */ - char[] parseType( char[] name = null ) return scope + char[] parseType() return scope { static immutable string[23] primitives = [ "char", // a @@ -830,7 +830,7 @@ pure @safe: ]; static if (__traits(hasMember, Hooks, "parseType")) - if (auto n = hooks.parseType(this, name)) + if (auto n = hooks.parseType(this, null)) return n; debug(trace) printf( "parseType+\n" ); @@ -861,27 +861,24 @@ pure @safe: switch ( t ) { case 'Q': // Type back reference - return parseBackrefType( () => parseType( name ) ); + return parseBackrefType(() => parseType()); case 'O': // Shared (O Type) popFront(); put( "shared(" ); parseType(); put( ')' ); - pad( name ); return dst[beg .. len]; case 'x': // Const (x Type) popFront(); put( "const(" ); parseType(); put( ')' ); - pad( name ); return dst[beg .. len]; case 'y': // Immutable (y Type) popFront(); put( "immutable(" ); parseType(); put( ')' ); - pad( name ); return dst[beg .. len]; case 'N': popFront(); @@ -912,7 +909,6 @@ pure @safe: popFront(); parseType(); put( "[]" ); - pad( name ); return dst[beg .. len]; case 'G': // TypeStaticArray (G Number Type) popFront(); @@ -921,7 +917,6 @@ pure @safe: put( '[' ); put( num ); put( ']' ); - pad( name ); return dst[beg .. len]; case 'H': // TypeAssocArray (H Type Type) popFront(); @@ -931,31 +926,28 @@ pure @safe: put( '[' ); put( tx ); put( ']' ); - pad( name ); return dst[beg .. len]; case 'P': // TypePointer (P Type) popFront(); parseType(); put( '*' ); - pad( name ); return dst[beg .. len]; case 'F': case 'U': case 'W': case 'V': case 'R': // TypeFunction - return parseTypeFunction( name ); + return parseTypeFunction(); case 'C': // TypeClass (C LName) case 'S': // TypeStruct (S LName) case 'E': // TypeEnum (E LName) case 'T': // TypeTypedef (T LName) popFront(); parseQualifiedName(); - pad( name ); return dst[beg .. len]; case 'D': // TypeDelegate (D TypeFunction) popFront(); auto modifiers = parseModifier(); if ( front == 'Q' ) - parseBackrefType( () => parseTypeFunction( name, IsDelegate.yes ) ); + parseBackrefType(() => parseTypeFunction(IsDelegate.yes)); else - parseTypeFunction( name, IsDelegate.yes ); + parseTypeFunction(IsDelegate.yes); if (modifiers) { // write modifiers behind the function arguments @@ -989,7 +981,6 @@ pure @safe: { popFront(); put( primitives[cast(size_t)(t - 'a')] ); - pad( name ); return dst[beg .. len]; } else if (t == 'z') @@ -1000,12 +991,10 @@ pure @safe: case 'i': popFront(); put( "cent" ); - pad( name ); return dst[beg .. len]; case 'k': popFront(); put( "ucent" ); - pad( name ); return dst[beg .. len]; default: error(); @@ -1358,7 +1347,7 @@ pure @safe: TypeFunction: CallConvention FuncAttrs Arguments ArgClose Type */ - char[] parseTypeFunction( char[] name = null, IsDelegate isdg = IsDelegate.no ) return scope + char[] parseTypeFunction(IsDelegate isdg = IsDelegate.no) return scope { debug(trace) printf( "parseTypeFunction+\n" ); debug(trace) scope(success) printf( "parseTypeFunction-\n" ); @@ -1383,18 +1372,8 @@ pure @safe: auto retbeg = len; parseType(); put( ' ' ); - // append name/delegate/function - if ( name.length ) - { - if ( !contains( dst[0 .. len], name ) ) - put( name ); - else if ( shift( name ).ptr != name.ptr ) - { - argbeg -= name.length; - retbeg -= name.length; - } - } - else if ( IsDelegate.yes == isdg ) + // append delegate/function + if (IsDelegate.yes == isdg) put( "delegate" ); else put( "function" ); @@ -2933,7 +2912,7 @@ CXX_DEMANGLER getCXXDemangler() nothrow @trusted version (linux) import core.sys.linux.dlfcn : RTLD_DEFAULT; version (NetBSD) import core.sys.netbsd.dlfcn : RTLD_DEFAULT; version (OpenBSD) import core.sys.openbsd.dlfcn : RTLD_DEFAULT; - version (OSX) import core.sys.darwin.dlfcn : RTLD_DEFAULT; + version (Darwin) import core.sys.darwin.dlfcn : RTLD_DEFAULT; version (Solaris) import core.sys.solaris.dlfcn : RTLD_DEFAULT; if (auto found = cast(CXX_DEMANGLER) dlsym(RTLD_DEFAULT, "__cxa_demangle")) diff --git a/libphobos/libdruntime/core/factory.d b/libphobos/libdruntime/core/factory.d new file mode 100644 index 0000000..f45a04e --- /dev/null +++ b/libphobos/libdruntime/core/factory.d @@ -0,0 +1,68 @@ +/* Create classes from their modules and names. + * + * Copyright: Copyright (C) D Language Foundation 2023 + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Authors: Walter Bright, Steven Schveighoffer + * Source: $(DRUNTIMESRC core/_factory.d) + */ + +module core.factory; + +/** + * Create instance of class specified by the module symbol and a string + * representing the name of the class. + * The class must either have no constructors or have + * a default constructor. + * Params: + * mod = symbol representing the module that the class is in + * classname = string representing the name of the class + * Returns: + * null if failed + * Example: + * --- + * module foo.bar; + * + * class C + * { + * this() { x = 10; } + * int x; + * } + * + * void main() + * { + * auto c = cast(C)factory!(foo.bar)("C"); + * assert(c !is null && c.x == 10); + * } + * --- + */ +Object factory(alias mod)(string classname) +{ + foreach(cl; _getModuleClasses!mod) + { + if (cl.stringof == classname) + return cl.classinfo.create(); + } + return null; +} + +@system unittest +{ + Object valid_obj = factory!object("Object"); + Object invalid_obj = factory!object("__this_class_doesnt_exist__"); + + assert(valid_obj !is null); + assert(invalid_obj is null); +} + +/************************************** + * Retrieve as a tuple all the types of the top level classes in the module mod. + */ +private template _getModuleClasses(alias mod) { + alias result = _AliasSeq!(); + static foreach(m; __traits(allMembers, mod)) + static if(is(__traits(getMember, mod, m) == class)) + result = _AliasSeq!(result, __traits(getMember, mod, m)); + alias _getModuleClasses = result; +} + +private template _AliasSeq(TList...) { alias _AliasSeq = TList; } diff --git a/libphobos/libdruntime/core/int128.d b/libphobos/libdruntime/core/int128.d index 46eb9b2..20fa7de 100644 --- a/libphobos/libdruntime/core/int128.d +++ b/libphobos/libdruntime/core/int128.d @@ -18,8 +18,23 @@ alias I = long; alias U = ulong; enum Ubits = uint(U.sizeof * 8); -version (X86_64) private enum Cent_alignment = 16; -else private enum Cent_alignment = (size_t.sizeof * 2); +version (DigitalMars) +{ + /* The alignment should follow target.stackAlign(), + * which is `isXmmSupported() ? 16 : (is64bit ? 8 : 4) + */ + version (D_SIMD) + private enum Cent_alignment = 16; + else version (X86_64) + private enum Cent_alignment = 8; + else + private enum Cent_alignment = 4; +} +else +{ + version (X86_64) private enum Cent_alignment = 16; + else private enum Cent_alignment = (size_t.sizeof * 2); +} align(Cent_alignment) struct Cent { diff --git a/libphobos/libdruntime/core/internal/array/appending.d b/libphobos/libdruntime/core/internal/array/appending.d index 616d27c..b609167 100644 --- a/libphobos/libdruntime/core/internal/array/appending.d +++ b/libphobos/libdruntime/core/internal/array/appending.d @@ -17,8 +17,6 @@ private enum isCopyingNothrow(T) = __traits(compiles, (ref T rhs) nothrow { T lh /// Implementation of `_d_arrayappendcTX` and `_d_arrayappendcTXTrace` template _d_arrayappendcTXImpl(Tarr : T[], T) { - import core.internal.array.utils : _d_HookTraceImpl; - private enum errorMessage = "Cannot append to array if compiling without support for runtime type information!"; /** @@ -51,17 +49,22 @@ template _d_arrayappendcTXImpl(Tarr : T[], T) return px; } else - assert(0, "Cannot append arrays if compiling without support for runtime type information!"); + assert(0, errorMessage); } - /** - * TraceGC wrapper around $(REF _d_arrayappendcTX, rt,array,appending,_d_arrayappendcTXImpl). - * Bugs: - * This function template was ported from a much older runtime hook that bypassed safety, - * purity, and throwabilty checks. To prevent breaking existing code, this function template - * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations. - */ - alias _d_arrayappendcTXTrace = _d_HookTraceImpl!(Tarr, _d_arrayappendcTX, errorMessage); + version (D_ProfileGC) + { + import core.internal.array.utils : _d_HookTraceImpl; + + /** + * TraceGC wrapper around $(REF _d_arrayappendcTX, rt,array,appending,_d_arrayappendcTXImpl). + * Bugs: + * This function template was ported from a much older runtime hook that bypassed safety, + * purity, and throwabilty checks. To prevent breaking existing code, this function template + * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations. + */ + alias _d_arrayappendcTXTrace = _d_HookTraceImpl!(Tarr, _d_arrayappendcTX, errorMessage); + } } /// Implementation of `_d_arrayappendT` @@ -71,7 +74,6 @@ ref Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y) @ import core.stdc.string : memcpy; import core.internal.traits : hasElaborateCopyConstructor, Unqual; - import core.lifetime : copyEmplace; enum hasPostblit = __traits(hasPostblit, T); auto length = x.length; @@ -81,6 +83,8 @@ ref Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y) @ // Only call `copyEmplace` if `T` has a copy ctor and no postblit. static if (hasElaborateCopyConstructor!T && !hasPostblit) { + import core.lifetime : copyEmplace; + foreach (i, ref elem; y) copyEmplace(elem, x[length + i]); } @@ -107,20 +111,23 @@ ref Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y) @ return x; } -/** - * TraceGC wrapper around $(REF _d_arrayappendT, core,internal,array,appending). - */ -ref Tarr _d_arrayappendTTrace(Tarr : T[], T)(string file, int line, string funcname, return ref scope Tarr x, scope Tarr y) @trusted +version (D_ProfileGC) { - version (D_TypeInfo) + /** + * TraceGC wrapper around $(REF _d_arrayappendT, core,internal,array,appending). + */ + ref Tarr _d_arrayappendTTrace(Tarr : T[], T)(string file, int line, string funcname, return ref scope Tarr x, scope Tarr y) @trusted { - import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure; - mixin(TraceHook!(Tarr.stringof, "_d_arrayappendT")); + version (D_TypeInfo) + { + import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure; + mixin(TraceHook!(Tarr.stringof, "_d_arrayappendT")); - return _d_arrayappendT(x, y); + return _d_arrayappendT(x, y); + } + else + assert(0, "Cannot append to array if compiling without support for runtime type information!"); } - else - assert(0, "Cannot append to array if compiling without support for runtime type information!"); } @safe unittest diff --git a/libphobos/libdruntime/core/internal/array/capacity.d b/libphobos/libdruntime/core/internal/array/capacity.d index 9440428..254e950 100644 --- a/libphobos/libdruntime/core/internal/array/capacity.d +++ b/libphobos/libdruntime/core/internal/array/capacity.d @@ -22,8 +22,6 @@ private extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlengt /// Implementation of `_d_arraysetlengthT` and `_d_arraysetlengthTTrace` template _d_arraysetlengthTImpl(Tarr : T[], T) { - import core.internal.array.utils : _d_HookTraceImpl; - private enum errorMessage = "Cannot resize arrays if compiling without support for runtime type information!"; /** @@ -54,14 +52,19 @@ template _d_arraysetlengthTImpl(Tarr : T[], T) assert(0, errorMessage); } - /** - * TraceGC wrapper around $(REF _d_arraysetlengthT, core,internal,array,core.internal.array.capacity). - * Bugs: - * This function template was ported from a much older runtime hook that bypassed safety, - * purity, and throwabilty checks. To prevent breaking existing code, this function template - * is temporarily declared `@trusted pure nothrow` until the implementation can be brought up to modern D expectations. - */ - alias _d_arraysetlengthTTrace = _d_HookTraceImpl!(Tarr, _d_arraysetlengthT, errorMessage); + version (D_ProfileGC) + { + import core.internal.array.utils : _d_HookTraceImpl; + + /** + * TraceGC wrapper around $(REF _d_arraysetlengthT, core,internal,array,core.internal.array.capacity). + * Bugs: + * This function template was ported from a much older runtime hook that bypassed safety, + * purity, and throwabilty checks. To prevent breaking existing code, this function template + * is temporarily declared `@trusted pure nothrow` until the implementation can be brought up to modern D expectations. + */ + alias _d_arraysetlengthTTrace = _d_HookTraceImpl!(Tarr, _d_arraysetlengthT, errorMessage); + } } @safe unittest diff --git a/libphobos/libdruntime/core/internal/array/concatenation.d b/libphobos/libdruntime/core/internal/array/concatenation.d index 955e381..99f33da 100644 --- a/libphobos/libdruntime/core/internal/array/concatenation.d +++ b/libphobos/libdruntime/core/internal/array/concatenation.d @@ -14,8 +14,6 @@ private extern (C) void[] _d_arraycatnTX(const TypeInfo ti, scope byte[][] arrs) /// Implementation of `_d_arraycatnTX` and `_d_arraycatnTXTrace` template _d_arraycatnTXImpl(Tarr : ResultArrT[], ResultArrT : T[], T) { - import core.internal.array.utils : _d_HookTraceImpl; - private enum errorMessage = "Cannot concatenate arrays if compiling without support for runtime type information!"; /** @@ -45,14 +43,19 @@ template _d_arraycatnTXImpl(Tarr : ResultArrT[], ResultArrT : T[], T) assert(0, errorMessage); } - /** - * TraceGC wrapper around $(REF _d_arraycatnTX, core,internal,array,concat). - * Bugs: - * This function template was ported from a much older runtime hook that bypassed safety, - * purity, and throwabilty checks. To prevent breaking existing code, this function template - * is temporarily declared `@trusted pure nothrow` until the implementation can be brought up to modern D expectations. - */ - alias _d_arraycatnTXTrace = _d_HookTraceImpl!(ResultArrT, _d_arraycatnTX, errorMessage); + version (D_ProfileGC) + { + import core.internal.array.utils : _d_HookTraceImpl; + + /** + * TraceGC wrapper around $(REF _d_arraycatnTX, core,internal,array,concat). + * Bugs: + * This function template was ported from a much older runtime hook that bypassed safety, + * purity, and throwabilty checks. To prevent breaking existing code, this function template + * is temporarily declared `@trusted pure nothrow` until the implementation can be brought up to modern D expectations. + */ + alias _d_arraycatnTXTrace = _d_HookTraceImpl!(ResultArrT, _d_arraycatnTX, errorMessage); + } } @safe unittest diff --git a/libphobos/libdruntime/core/internal/array/duplication.d b/libphobos/libdruntime/core/internal/array/duplication.d index 41dfab6..21894c2 100644 --- a/libphobos/libdruntime/core/internal/array/duplication.d +++ b/libphobos/libdruntime/core/internal/array/duplication.d @@ -15,10 +15,17 @@ U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T)) if (__ctfe) return _dupCtfe!(T, U)(a); - import core.stdc.string : memcpy; - auto arr = _d_newarrayU(typeid(T[]), a.length); - memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length); - return *cast(U[]*) &arr; + version (D_BetterC) + { + return _dupCtfe!(T, U)(a); + } + else + { + import core.stdc.string : memcpy; + auto arr = _d_newarrayU(typeid(T[]), a.length); + memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length); + return *cast(U[]*) &arr; + } } U[] _dupCtfe(T, U)(scope T[] a) @@ -41,25 +48,32 @@ U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T)) if (__ctfe) return _dupCtfe!(T, U)(a); - import core.lifetime: copyEmplace; - U[] res = () @trusted { - auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length); - size_t i; - scope (failure) - { - import core.internal.lifetime: emplaceInitializer; - // Initialize all remaining elements to not destruct garbage - foreach (j; i .. a.length) - emplaceInitializer(cast() arr[j]); - } - for (; i < a.length; i++) - { - copyEmplace(a.ptr[i], arr[i]); - } - return cast(U[])(arr[0..a.length]); - } (); + version (D_BetterC) + { + return _dupCtfe!(T, U)(a); + } + else + { + import core.lifetime: copyEmplace; + U[] res = () @trusted { + auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length); + size_t i; + scope (failure) + { + import core.internal.lifetime: emplaceInitializer; + // Initialize all remaining elements to not destruct garbage + foreach (j; i .. a.length) + emplaceInitializer(cast() arr[j]); + } + for (; i < a.length; i++) + { + copyEmplace(a.ptr[i], arr[i]); + } + return cast(U[])(arr[0..a.length]); + } (); - return res; + return res; + } } // https://issues.dlang.org/show_bug.cgi?id=22107 diff --git a/libphobos/libdruntime/core/internal/array/utils.d b/libphobos/libdruntime/core/internal/array/utils.d index 41aa57f..a16005e 100644 --- a/libphobos/libdruntime/core/internal/array/utils.d +++ b/libphobos/libdruntime/core/internal/array/utils.d @@ -34,76 +34,79 @@ ulong accumulatePure(string file, int line, string funcname, string name, ulong return func(file, line, funcname, name, size); } -/** - * TraceGC wrapper generator around the runtime hook `Hook`. - * Params: - * Type = The type of hook to report to accumulate - * Hook = The name hook to wrap - */ -template TraceHook(string Type, string Hook) +version (D_ProfileGC) { - const char[] TraceHook = q{ - import core.internal.array.utils : gcStatsPure, accumulatePure; - - pragma(inline, false); - string name = } ~ "`" ~ Type ~ "`;" ~ q{ - - // FIXME: use rt.tracegc.accumulator when it is accessable in the future. - version (tracegc) - } ~ "{\n" ~ q{ - import core.stdc.stdio; - - printf("%sTrace file = '%.*s' line = %d function = '%.*s' type = %.*s\n", - } ~ "\"" ~ Hook ~ "\".ptr," ~ q{ - file.length, file.ptr, - line, - funcname.length, funcname.ptr, - name.length, name.ptr - ); - } ~ "}\n" ~ q{ - ulong currentlyAllocated = gcStatsPure().allocatedInCurrentThread; - - scope(exit) - { - ulong size = gcStatsPure().allocatedInCurrentThread - currentlyAllocated; - if (size > 0) - if (!accumulatePure(file, line, funcname, name, size)) { - // This 'if' and 'assert' is needed to force the compiler to not remove the call to - // `accumulatePure`. It really want to do that while optimizing as the function is - // `pure` and it does not influence the result of this hook. - - // `accumulatePure` returns the value of `size`, which can never be zero due to the - // previous 'if'. So this assert will never be triggered. - assert(0); - } - } - }; -} + /** + * TraceGC wrapper generator around the runtime hook `Hook`. + * Params: + * Type = The type of hook to report to accumulate + * Hook = The name hook to wrap + */ + template TraceHook(string Type, string Hook) + { + const char[] TraceHook = q{ + import core.internal.array.utils : gcStatsPure, accumulatePure; + + pragma(inline, false); + string name = } ~ "`" ~ Type ~ "`;" ~ q{ + + // FIXME: use rt.tracegc.accumulator when it is accessable in the future. + version (tracegc) + } ~ "{\n" ~ q{ + import core.stdc.stdio; + + printf("%sTrace file = '%.*s' line = %d function = '%.*s' type = %.*s\n", + } ~ "\"" ~ Hook ~ "\".ptr," ~ q{ + file.length, file.ptr, + line, + funcname.length, funcname.ptr, + name.length, name.ptr + ); + } ~ "}\n" ~ q{ + ulong currentlyAllocated = gcStatsPure().allocatedInCurrentThread; + + scope(exit) + { + ulong size = gcStatsPure().allocatedInCurrentThread - currentlyAllocated; + if (size > 0) + if (!accumulatePure(file, line, funcname, name, size)) { + // This 'if' and 'assert' is needed to force the compiler to not remove the call to + // `accumulatePure`. It really want to do that while optimizing as the function is + // `pure` and it does not influence the result of this hook. + + // `accumulatePure` returns the value of `size`, which can never be zero due to the + // previous 'if'. So this assert will never be triggered. + assert(0); + } + } + }; + } -/** - * TraceGC wrapper around runtime hook `Hook`. - * Params: - * T = Type of hook to report to accumulate - * Hook = The hook to wrap - * errorMessage = The error message incase `version != D_TypeInfo` - * file = File that called `_d_HookTraceImpl` - * line = Line inside of `file` that called `_d_HookTraceImpl` - * funcname = Function that called `_d_HookTraceImpl` - * parameters = Parameters that will be used to call `Hook` - * Bugs: - * This function template needs be between the compiler and a much older runtime hook that bypassed safety, - * purity, and throwabilty checks. To prevent breaking existing code, this function template - * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations. -*/ -auto _d_HookTraceImpl(T, alias Hook, string errorMessage)(string file, int line, string funcname, Parameters!Hook parameters) @trusted pure -{ - version (D_TypeInfo) + /** + * TraceGC wrapper around runtime hook `Hook`. + * Params: + * T = Type of hook to report to accumulate + * Hook = The hook to wrap + * errorMessage = The error message incase `version != D_TypeInfo` + * file = File that called `_d_HookTraceImpl` + * line = Line inside of `file` that called `_d_HookTraceImpl` + * funcname = Function that called `_d_HookTraceImpl` + * parameters = Parameters that will be used to call `Hook` + * Bugs: + * This function template needs be between the compiler and a much older runtime hook that bypassed safety, + * purity, and throwabilty checks. To prevent breaking existing code, this function template + * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations. + */ + auto _d_HookTraceImpl(T, alias Hook, string errorMessage)(string file, int line, string funcname, Parameters!Hook parameters) @trusted pure { - mixin(TraceHook!(T.stringof, __traits(identifier, Hook))); - return Hook(parameters); + version (D_TypeInfo) + { + mixin(TraceHook!(T.stringof, __traits(identifier, Hook))); + return Hook(parameters); + } + else + assert(0, errorMessage); } - else - assert(0, errorMessage); } /** diff --git a/libphobos/libdruntime/core/internal/traits.d b/libphobos/libdruntime/core/internal/traits.d index 0b4890c..966839f 100644 --- a/libphobos/libdruntime/core/internal/traits.d +++ b/libphobos/libdruntime/core/internal/traits.d @@ -654,7 +654,7 @@ if (func.length == 1 /*&& isCallable!func*/) int test(int); int test() @property; } - alias ov = __traits(getVirtualFunctions, Overloads, "test"); + alias ov = __traits(getVirtualMethods, Overloads, "test"); alias F_ov0 = FunctionTypeOf!(ov[0]); alias F_ov1 = FunctionTypeOf!(ov[1]); alias F_ov2 = FunctionTypeOf!(ov[2]); diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d index 371308d..5e339c0 100644 --- a/libphobos/libdruntime/core/lifetime.d +++ b/libphobos/libdruntime/core/lifetime.d @@ -2385,21 +2385,24 @@ template _d_delstructImpl(T) } } - import core.internal.array.utils : _d_HookTraceImpl; + version (D_ProfileGC) + { + import core.internal.array.utils : _d_HookTraceImpl; - private enum errorMessage = "Cannot delete struct if compiling without support for runtime type information!"; + private enum errorMessage = "Cannot delete struct if compiling without support for runtime type information!"; - /** - * TraceGC wrapper around $(REF _d_delstruct, core,lifetime,_d_delstructImpl). - * - * Bugs: - * This function template was ported from a much older runtime hook that - * bypassed safety, purity, and throwabilty checks. To prevent breaking - * existing code, this function template is temporarily declared - * `@trusted` until the implementation can be brought up to modern D - * expectations. - */ - alias _d_delstructTrace = _d_HookTraceImpl!(T, _d_delstruct, errorMessage); + /** + * TraceGC wrapper around $(REF _d_delstruct, core,lifetime,_d_delstructImpl). + * + * Bugs: + * This function template was ported from a much older runtime hook that + * bypassed safety, purity, and throwabilty checks. To prevent breaking + * existing code, this function template is temporarily declared + * `@trusted` until the implementation can be brought up to modern D + * expectations. + */ + alias _d_delstructTrace = _d_HookTraceImpl!(T, _d_delstruct, errorMessage); + } } @system pure nothrow unittest @@ -2709,3 +2712,108 @@ T _d_newThrowable(T)() @trusted assert(exc.refcount() == 1); assert(e.refcount() == 1); } + +/** + * Create a new class instance. + * Allocates memory and sets fields to their initial value, but does not call a + * constructor. + * --- + * new C() // _d_newclass!(C)() + * --- + * Returns: newly created object + */ +T _d_newclassT(T)() @trusted +if (is(T == class)) +{ + import core.internal.traits : hasIndirections; + import core.exception : onOutOfMemoryError; + import core.memory : GC, pureMalloc; + + alias BlkAttr = GC.BlkAttr; + + auto init = __traits(initSymbol, T); + void* p; + + static if (__traits(getLinkage, T) == "Windows") + { + p = pureMalloc(init.length); + if (!p) + onOutOfMemoryError(); + } + else + { + BlkAttr attr = BlkAttr.NONE; + + /* `extern(C++)`` classes don't have a classinfo pointer in their vtable, + * so the GC can't finalize them. + */ + static if (__traits(hasMember, T, "__dtor") && __traits(getLinkage, T) != "C++") + attr |= BlkAttr.FINALIZE; + static if (!hasIndirections!T) + attr |= BlkAttr.NO_SCAN; + + p = GC.malloc(init.length, attr, typeid(T)); + debug(PRINTF) printf(" p = %p\n", p); + } + + debug(PRINTF) + { + printf("p = %p\n", p); + printf("init.ptr = %p, len = %llu\n", init.ptr, cast(ulong)init.length); + printf("vptr = %p\n", *cast(void**) init); + printf("vtbl[0] = %p\n", (*cast(void***) init)[0]); + printf("vtbl[1] = %p\n", (*cast(void***) init)[1]); + printf("init[0] = %x\n", (cast(uint*) init)[0]); + printf("init[1] = %x\n", (cast(uint*) init)[1]); + printf("init[2] = %x\n", (cast(uint*) init)[2]); + printf("init[3] = %x\n", (cast(uint*) init)[3]); + printf("init[4] = %x\n", (cast(uint*) init)[4]); + } + + // initialize it + p[0 .. init.length] = init[]; + + debug(PRINTF) printf("initialization done\n"); + return cast(T) p; +} + +// Test allocation +@safe unittest +{ + class C { } + C c = _d_newclassT!C(); + + assert(c !is null); +} + +// Test initializers +@safe unittest +{ + { + class C { int x, y; } + C c = _d_newclassT!C(); + + assert(c.x == 0); + assert(c.y == 0); + } + { + class C { int x = 2, y = 3; } + C c = _d_newclassT!C(); + + assert(c.x == 2); + assert(c.y == 3); + } +} + +T _d_newclassTTrace(T)(string file, int line, string funcname) @trusted +{ + version (D_TypeInfo) + { + import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure; + mixin(TraceHook!(T.stringof, "_d_newclassT")); + + return _d_newclassT!T(); + } + else + assert(0, "Cannot create new class if compiling without support for runtime type information!"); +} diff --git a/libphobos/libdruntime/core/memory.d b/libphobos/libdruntime/core/memory.d index 7d1356a..96c2af4 100644 --- a/libphobos/libdruntime/core/memory.d +++ b/libphobos/libdruntime/core/memory.d @@ -202,8 +202,8 @@ unittest // make it more difficult to call the function again, manually. private void initialize(); pragma(crt_constructor) -pragma(mangle, `_D` ~ initialize.mangleof) -private extern (C) void initialize() @system +pragma(mangle, initialize.mangleof) +private extern (C) void _initialize() @system { version (Posix) { diff --git a/libphobos/libdruntime/core/stdc/config.d b/libphobos/libdruntime/core/stdc/config.d index 16bc475..c85682e 100644 --- a/libphobos/libdruntime/core/stdc/config.d +++ b/libphobos/libdruntime/core/stdc/config.d @@ -312,3 +312,28 @@ alias c_complex_float = __c_complex_float; alias c_complex_double = __c_complex_double; alias c_complex_real = __c_complex_real; } + + +// Returns the mangled name for the 64-bit time_t versions of +// functions affected by musl's transition to 64-bit time_t. +// https://musl.libc.org/time64.html +version (CRuntime_Musl) +{ + version (CRuntime_Musl_Pre_Time64) + enum muslRedirTime64 = false; + else + { + // time_t was defined as a C long in older Musl versions. + enum muslRedirTime64 = (c_long.sizeof == 4); + } +} +else + enum muslRedirTime64 = false; + +package(core) template muslRedirTime64Mangle(string name, string redirectedName) +{ + static if (muslRedirTime64) + enum muslRedirTime64Mangle = redirectedName; + else + enum muslRedirTime64Mangle = name; +} diff --git a/libphobos/libdruntime/core/stdc/time.d b/libphobos/libdruntime/core/stdc/time.d index b19c3c7..d7a5765 100644 --- a/libphobos/libdruntime/core/stdc/time.d +++ b/libphobos/libdruntime/core/stdc/time.d @@ -30,19 +30,25 @@ nothrow: @nogc: /// +pragma(mangle, muslRedirTime64Mangle!("difftime", "__difftime64")) pure double difftime(time_t time1, time_t time0); // MT-Safe /// +pragma(mangle, muslRedirTime64Mangle!("mktime", "__mktime64")) @system time_t mktime(scope tm* timeptr); // @system: MT-Safe env locale /// +pragma(mangle, muslRedirTime64Mangle!("time", "__time64")) time_t time(scope time_t* timer); /// @system char* asctime(const scope tm* timeptr); // @system: MT-Unsafe race:asctime locale /// +pragma(mangle, muslRedirTime64Mangle!("ctime", "__ctime64")) @system char* ctime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf race:asctime env locale /// +pragma(mangle, muslRedirTime64Mangle!("gmtime", "__gmtime64")) @system tm* gmtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale /// +pragma(mangle, muslRedirTime64Mangle!("localtime", "__localtime64")) @system tm* localtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale /// @system size_t strftime(scope char* s, size_t maxsize, const scope char* format, const scope tm* timeptr); // @system: MT-Safe env locale diff --git a/libphobos/libdruntime/core/sys/darwin/sys/event.d b/libphobos/libdruntime/core/sys/darwin/sys/event.d index 24f1cbe..53504db 100644 --- a/libphobos/libdruntime/core/sys/darwin/sys/event.d +++ b/libphobos/libdruntime/core/sys/darwin/sys/event.d @@ -46,12 +46,12 @@ enum : short EVFILT_EXCEPT = -15, } -extern(D) void EV_SET(kevent_t* kevp, typeof(kevent_t.tupleof) args) +extern(D) void EV_SET()(kevent_t* kevp, typeof(kevent_t.tupleof) args) { *kevp = kevent_t(args); } -extern(D) void EV_SET64(kevent64_s* kevp, typeof(kevent64_s.tupleof) args) +extern(D) void EV_SET64()(kevent64_s* kevp, typeof(kevent64_s.tupleof) args) { *kevp = kevent64_s(args); } diff --git a/libphobos/libdruntime/core/sys/posix/aio.d b/libphobos/libdruntime/core/sys/posix/aio.d index 3ea7f6a..3a537a4 100644 --- a/libphobos/libdruntime/core/sys/posix/aio.d +++ b/libphobos/libdruntime/core/sys/posix/aio.d @@ -8,6 +8,7 @@ */ module core.sys.posix.aio; +import core.stdc.config; import core.sys.posix.signal; import core.sys.posix.sys.types; @@ -392,6 +393,7 @@ else int aio_fsync(int op, aiocb* aiocbp); int aio_error(const(aiocb)* aiocbp); ssize_t aio_return(aiocb* aiocbp); + pragma(mangle, muslRedirTime64Mangle!("aio_suspend", "__aio_suspend_time64")) int aio_suspend(const(aiocb*)* aiocb_list, int nitems, const(timespec)* timeout); int aio_cancel(int fd, aiocb* aiocbp); int lio_listio(int mode, const(aiocb*)* aiocb_list, int nitems, sigevent* sevp); diff --git a/libphobos/libdruntime/core/sys/posix/dlfcn.d b/libphobos/libdruntime/core/sys/posix/dlfcn.d index 5797b8f..f4bd2d8 100644 --- a/libphobos/libdruntime/core/sys/posix/dlfcn.d +++ b/libphobos/libdruntime/core/sys/posix/dlfcn.d @@ -177,6 +177,38 @@ version (CRuntime_Glibc) void* dli_saddr; } } +else +version (CRuntime_Musl) +{ + enum RTLD_LAZY = 1; + enum RTLD_NOW = 2; + enum RTLD_NOLOAD = 4; + enum RTLD_NODELETE = 4096; + enum RTLD_GLOBAL = 256; + enum RTLD_LOCAL = 0; + + enum RTLD_NEXT = cast(void *)-1; + enum RTLD_DEFAULT = cast(void *)0; + + enum RTLD_DI_LINKMAP = 2; + + int dlclose(void *); + char *dlerror(); + void *dlopen(const(char) *, int); + + pragma(mangle, muslRedirTime64Mangle!("dlsym", "__dlsym_time64")) + void *dlsym(void *__restrict, const(char) *__restrict); + + struct Dl_info + { + const(char)* dli_fname; + void* dli_fbase; + const(char)* dli_sname; + void* dli_saddr; + } + int dladdr(const(void) *, Dl_info *); + int dlinfo(void *, int, void *); +} else version (Darwin) { enum RTLD_LAZY = 0x00001; diff --git a/libphobos/libdruntime/core/sys/posix/mqueue.d b/libphobos/libdruntime/core/sys/posix/mqueue.d index ac697bf..eae50d2 100644 --- a/libphobos/libdruntime/core/sys/posix/mqueue.d +++ b/libphobos/libdruntime/core/sys/posix/mqueue.d @@ -178,6 +178,7 @@ ssize_t mq_receive (mqd_t mqdes, char* msg_ptr, size_t msg_len, uint* msg_prio); * On success, mq_receive() returns the number of bytes in the received * message; on error, -1 is returned, with errno set to indicate the error */ +pragma(mangle, muslRedirTime64Mangle!("mq_timedreceive", "__mq_timedreceive_time64")) ssize_t mq_timedreceive (mqd_t mqdes, char* msg_ptr, size_t msg_len, uint* msg_prio, const(timespec)* abs_timeout); @@ -216,5 +217,6 @@ int mq_send (mqd_t mqdes, const(char)* msg_ptr, size_t msg_len, uint msg_prio); * with errno set to indicate the error. * */ +pragma(mangle, muslRedirTime64Mangle!("mq_timedsend", "__mq_timedsend_time64")) int mq_timedsend (mqd_t mqdes, const(char)* msg_ptr, size_t msg_len, uint msg_prio, const(timespec)* abs_timeout); diff --git a/libphobos/libdruntime/core/sys/posix/netinet/in_.d b/libphobos/libdruntime/core/sys/posix/netinet/in_.d index a58fa85..5818ee6 100644 --- a/libphobos/libdruntime/core/sys/posix/netinet/in_.d +++ b/libphobos/libdruntime/core/sys/posix/netinet/in_.d @@ -547,7 +547,7 @@ version (CRuntime_Glibc) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -555,7 +555,7 @@ version (CRuntime_Glibc) (cast(uint32_t*) addr)[3] == 0; } - extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -563,29 +563,29 @@ version (CRuntime_Glibc) (cast(uint32_t*) addr)[3] == htonl( 1 ); } - extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* addr ) pure { return (cast(uint8_t*) addr)[0] == 0xff; } - extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* addr ) pure { return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfe800000 ); } - extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* addr ) pure { return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfec00000 ); } - extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && (cast(uint32_t*) addr)[2] == htonl( 0xffff ); } - extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -593,31 +593,31 @@ version (CRuntime_Glibc) ntohl( (cast(uint32_t*) addr)[3] ) > 1; } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x1; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x2; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST(addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x5; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x8; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0xe; @@ -670,7 +670,7 @@ else version (Darwin) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -678,7 +678,7 @@ else version (Darwin) (cast(uint32_t*) addr)[3] == 0; } - extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -686,29 +686,29 @@ else version (Darwin) (cast(uint32_t*) addr)[3] == ntohl( 1 ); } - extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* addr ) pure { return addr.s6_addr[0] == 0xff; } - extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* addr ) pure { return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0x80; } - extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* addr ) pure { return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0xc0; } - extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && (cast(uint32_t*) addr)[2] == ntohl( 0x0000ffff ); } - extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -717,31 +717,31 @@ else version (Darwin) (cast(uint32_t*) addr)[3] != ntohl( 1 ); } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x1; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x2; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST(addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x5; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x8; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0xe; diff --git a/libphobos/libdruntime/core/sys/posix/sched.d b/libphobos/libdruntime/core/sys/posix/sched.d index f6f0a58..ba7ab89 100644 --- a/libphobos/libdruntime/core/sys/posix/sched.d +++ b/libphobos/libdruntime/core/sys/posix/sched.d @@ -65,7 +65,10 @@ version (linux) { int sched_priority; int __reserved1; - timespec[2] __reserved2; + static if (muslRedirTime64) + c_long[2] __reserved2; + else + timespec[2] __reserved2; int __reserved3; } } @@ -282,6 +285,7 @@ else version (CRuntime_Musl) { int sched_get_priority_max(int); int sched_get_priority_min(int); + pragma(mangle, muslRedirTime64Mangle!("sched_rr_get_interval", "__sched_rr_get_interval_time64")) int sched_rr_get_interval(pid_t, timespec*); } else version (CRuntime_UClibc) diff --git a/libphobos/libdruntime/core/sys/posix/semaphore.d b/libphobos/libdruntime/core/sys/posix/semaphore.d index d755f86..4f3b6e9 100644 --- a/libphobos/libdruntime/core/sys/posix/semaphore.d +++ b/libphobos/libdruntime/core/sys/posix/semaphore.d @@ -216,6 +216,7 @@ else version (CRuntime_Bionic) } else version (CRuntime_Musl) { + pragma(mangle, muslRedirTime64Mangle!("sem_timedwait", "__sem_timedwait_time64")) int sem_timedwait(sem_t*, const scope timespec*); } else version (CRuntime_UClibc) diff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d index 542e83a..f722bc4 100644 --- a/libphobos/libdruntime/core/sys/posix/signal.d +++ b/libphobos/libdruntime/core/sys/posix/signal.d @@ -2990,6 +2990,7 @@ else version (CRuntime_Bionic) else version (CRuntime_Musl) { int sigqueue(pid_t, int, const sigval); + pragma(mangle, muslRedirTime64Mangle!("sigtimedwait", "__sigtimedwait_time64")) int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*); int sigwaitinfo(const scope sigset_t*, siginfo_t*); } diff --git a/libphobos/libdruntime/core/sys/posix/sys/resource.d b/libphobos/libdruntime/core/sys/posix/sys/resource.d index 1f46f03..b997f11 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/resource.d +++ b/libphobos/libdruntime/core/sys/posix/sys/resource.d @@ -547,6 +547,7 @@ else version (CRuntime_Musl) int setrlimit(int, const scope rlimit*); alias getrlimit getrlimit64; alias setrlimit setrlimit64; + pragma(mangle, muslRedirTime64Mangle!("getrusage", "__getrusage_time64")) int getrusage(int, rusage*); } else version (Solaris) diff --git a/libphobos/libdruntime/core/sys/posix/sys/select.d b/libphobos/libdruntime/core/sys/posix/sys/select.d index 06b0940..dd05d08 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/select.d +++ b/libphobos/libdruntime/core/sys/posix/sys/select.d @@ -501,7 +501,9 @@ else version (CRuntime_Musl) { fdset.fds_bits[0 .. $] = 0; } + pragma(mangle, muslRedirTime64Mangle!("pselect", "__pselect_time64")) int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); + pragma(mangle, muslRedirTime64Mangle!("select", "__select_time64")) int select(int, fd_set*, fd_set*, fd_set*, timeval*); } else version (CRuntime_UClibc) diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d index ecc98cc..ee9e5da 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/stat.d +++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d @@ -1656,7 +1656,6 @@ else version (CRuntime_Bionic) } else version (CRuntime_Musl) { - alias __mode_t = uint; enum { S_IRUSR = 0x100, // octal 0400 S_IWUSR = 0x080, // octal 0200 @@ -1890,8 +1889,11 @@ else version (CRuntime_Bionic) } else version (CRuntime_Musl) { + pragma(mangle, muslRedirTime64Mangle!("stat", "__stat_time64")) int stat(const scope char*, stat_t*); + pragma(mangle, muslRedirTime64Mangle!("fstat", "__fstat_time64")) int fstat(int, stat_t*); + pragma(mangle, muslRedirTime64Mangle!("lstat", "__lstat_time64")) int lstat(const scope char*, stat_t*); alias fstat fstat64; diff --git a/libphobos/libdruntime/core/sys/posix/sys/time.d b/libphobos/libdruntime/core/sys/posix/sys/time.d index b536eed..dda4caf 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/time.d +++ b/libphobos/libdruntime/core/sys/posix/sys/time.d @@ -89,7 +89,9 @@ else version (CRuntime_Musl) time_t tv_sec; suseconds_t tv_usec; } + pragma(mangle, muslRedirTime64Mangle!("gettimeofday", "__gettimeofday_time64")) int gettimeofday(timeval*, void*); + pragma(mangle, muslRedirTime64Mangle!("utimes", "__utimes_time64")) int utimes(const scope char*, ref const(timeval)[2]); } else version (Darwin) diff --git a/libphobos/libdruntime/core/sys/posix/time.d b/libphobos/libdruntime/core/sys/posix/time.d index af52002..f49764d 100644 --- a/libphobos/libdruntime/core/sys/posix/time.d +++ b/libphobos/libdruntime/core/sys/posix/time.d @@ -83,6 +83,7 @@ else version (CRuntime_Bionic) } else version (CRuntime_Musl) { + pragma(mangle, muslRedirTime64Mangle!("timegm", "__timegm_time64")) time_t timegm(tm*); } else version (CRuntime_UClibc) @@ -483,15 +484,21 @@ else version (CRuntime_Musl) int nanosleep(const scope timespec*, timespec*); + pragma(mangle, muslRedirTime64Mangle!("clock_getres", "__clock_getres_time64")) int clock_getres(clockid_t, timespec*); + pragma(mangle, muslRedirTime64Mangle!("clock_gettime", "__clock_gettime64")) int clock_gettime(clockid_t, timespec*); + pragma(mangle, muslRedirTime64Mangle!("clock_settime", "__clock_settime64")) int clock_settime(clockid_t, const scope timespec*); + pragma(mangle, muslRedirTime64Mangle!("clock_nanosleep", "__clock_nanosleep_time64")) int clock_nanosleep(clockid_t, int, const scope timespec*, timespec*); int clock_getcpuclockid(pid_t, clockid_t *); int timer_create(clockid_t, sigevent*, timer_t*); int timer_delete(timer_t); + pragma(mangle, muslRedirTime64Mangle!("timer_gettime", "__timer_gettime64")) int timer_gettime(timer_t, itimerspec*); + pragma(mangle, muslRedirTime64Mangle!("timer_settime", "__timer_settime64")) int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*); int timer_getoverrun(timer_t); } @@ -596,8 +603,11 @@ else version (CRuntime_Bionic) else version (CRuntime_Musl) { char* asctime_r(const scope tm*, char*); + pragma(mangle, muslRedirTime64Mangle!("ctime_r", "__ctime64_r")) char* ctime_r(const scope time_t*, char*); + pragma(mangle, muslRedirTime64Mangle!("gmtime_r", "__gmtime64_r")) tm* gmtime_r(const scope time_t*, tm*); + pragma(mangle, muslRedirTime64Mangle!("localtime_r", "__localtime64_r")) tm* localtime_r(const scope time_t*, tm*); } else version (CRuntime_UClibc) diff --git a/libphobos/libdruntime/core/sys/posix/utime.d b/libphobos/libdruntime/core/sys/posix/utime.d index fcec7af..e7059d7 100644 --- a/libphobos/libdruntime/core/sys/posix/utime.d +++ b/libphobos/libdruntime/core/sys/posix/utime.d @@ -62,6 +62,7 @@ else version (CRuntime_Musl) time_t modtime; } + pragma(mangle, muslRedirTime64Mangle!("utime", "__utime64")) int utime(const scope char*, const scope utimbuf*); } else version (Darwin) diff --git a/libphobos/libdruntime/core/sys/windows/stacktrace.d b/libphobos/libdruntime/core/sys/windows/stacktrace.d index 8df2972..c10a917 100644 --- a/libphobos/libdruntime/core/sys/windows/stacktrace.d +++ b/libphobos/libdruntime/core/sys/windows/stacktrace.d @@ -30,6 +30,7 @@ extern(Windows) DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR pBuffer, DWOR extern(Windows) alias USHORT function(ULONG FramesToSkip, ULONG FramesToCapture, PVOID *BackTrace, PULONG BackTraceHash) @nogc RtlCaptureStackBackTraceFunc; private __gshared RtlCaptureStackBackTraceFunc RtlCaptureStackBackTrace; +private __gshared CRITICAL_SECTION mutex; // cannot use core.sync.mutex.Mutex unfortunately (cyclic dependency...) private __gshared immutable bool initialized; @@ -63,11 +64,11 @@ public: skip += INTERNALFRAMES; } - if ( initialized ) + if (initialized) m_trace = trace(tracebuf[], skip, context); } - int opApply( scope int delegate(ref const(char[])) dg ) const + override int opApply( scope int delegate(ref const(char[])) dg ) const { return opApply( (ref size_t, ref const(char[]) buf) { @@ -76,7 +77,7 @@ public: } - int opApply( scope int delegate(ref size_t, ref const(char[])) dg ) const + override int opApply( scope int delegate(ref size_t, ref const(char[])) dg ) const { int result; foreach ( i, e; resolve(m_trace) ) @@ -118,10 +119,10 @@ public: /// ditto static ulong[] trace(ulong[] buffer, size_t skip = 0, CONTEXT* context = null) @nogc { - synchronized( typeid(StackTrace) ) - { - return traceNoSync(buffer, skip, context); - } + EnterCriticalSection(&mutex); + scope(exit) LeaveCriticalSection(&mutex); + + return traceNoSync(buffer, skip, context); } /** @@ -133,10 +134,15 @@ public: */ @trusted static char[][] resolve(const(ulong)[] addresses) { - synchronized( typeid(StackTrace) ) - { - return resolveNoSync(addresses); - } + // FIXME: make @nogc to avoid having to disable resolution within finalizers + import core.memory : GC; + if (GC.inFinalizer) + return null; + + EnterCriticalSection(&mutex); + scope(exit) LeaveCriticalSection(&mutex); + + return resolveNoSync(addresses); } private: @@ -421,5 +427,6 @@ shared static this() dbghelp.SymRegisterCallback64(hProcess, &FixupDebugHeader, 0); + InitializeCriticalSection(&mutex); initialized = true; } diff --git a/libphobos/libdruntime/core/sys/windows/winbase.d b/libphobos/libdruntime/core/sys/windows/winbase.d index 3b571ad..bbb6e9a 100644 --- a/libphobos/libdruntime/core/sys/windows/winbase.d +++ b/libphobos/libdruntime/core/sys/windows/winbase.d @@ -38,6 +38,7 @@ import core.sys.windows.basetyps, core.sys.windows.w32api, core.sys.windows.winn // FIXME: //alias void va_list; import core.stdc.stdarg : va_list; +import core.stdc.string : memset, memcpy, memmove; // COMMPROP structure, used by GetCommProperties() @@ -1713,23 +1714,15 @@ extern (Windows) nothrow @nogc { BOOL CopyFileExA(LPCSTR, LPCSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL, DWORD); BOOL CopyFileExW(LPCWSTR, LPCWSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL, DWORD); - /+ FIXME - alias memmove RtlMoveMemory; - alias memcpy RtlCopyMemory; + alias RtlMoveMemory = memmove; + alias RtlCopyMemory = memcpy; + pragma(inline, true) void RtlFillMemory(PVOID Destination, SIZE_T Length, BYTE Fill) { memset(Destination, Fill, Length); } + pragma(inline, true) void RtlZeroMemory(PVOID Destination, SIZE_T Length) { memset(Destination, 0, Length); } + alias MoveMemory = RtlMoveMemory; + alias CopyMemory = RtlCopyMemory; + alias FillMemory = RtlFillMemory; + alias ZeroMemory = RtlZeroMemory; - void RtlFillMemory(PVOID dest, SIZE_T len, BYTE fill) { - memset(dest, fill, len); - } - - void RtlZeroMemory(PVOID dest, SIZE_T len) { - RtlFillMemory(dest, len, 0); - } - - alias RtlMoveMemory MoveMemory; - alias RtlCopyMemory CopyMemory; - alias RtlFillMemory FillMemory; - alias RtlZeroMemory ZeroMemory; - +/ BOOL CreateDirectoryA(LPCSTR, LPSECURITY_ATTRIBUTES); BOOL CreateDirectoryW(LPCWSTR, LPSECURITY_ATTRIBUTES); BOOL CreateDirectoryExA(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES); diff --git a/libphobos/libdruntime/core/thread/fiber.d b/libphobos/libdruntime/core/thread/fiber.d index efbad7d..4590ff1 100644 --- a/libphobos/libdruntime/core/thread/fiber.d +++ b/libphobos/libdruntime/core/thread/fiber.d @@ -19,6 +19,8 @@ import core.thread.threadgroup; import core.thread.types; import core.thread.context; +import core.memory : pageSize; + /////////////////////////////////////////////////////////////////////////////// // Fiber Platform Detection /////////////////////////////////////////////////////////////////////////////// @@ -600,7 +602,7 @@ class Fiber version (X86_64) // libunwind on macOS 11 now requires more stack space than 16k, so // default to a larger stack size. This is only applied to X86 as - // the PAGESIZE is still 4k, however on AArch64 it is 16k. + // the pageSize is still 4k, however on AArch64 it is 16k. enum defaultStackPages = 8; else enum defaultStackPages = 4; @@ -623,8 +625,8 @@ class Fiber * In: * fn must not be null. */ - this( void function() fn, size_t sz = PAGESIZE * defaultStackPages, - size_t guardPageSize = PAGESIZE ) nothrow + this( void function() fn, size_t sz = pageSize * defaultStackPages, + size_t guardPageSize = pageSize ) nothrow in { assert( fn ); @@ -651,8 +653,8 @@ class Fiber * In: * dg must not be null. */ - this( void delegate() dg, size_t sz = PAGESIZE * defaultStackPages, - size_t guardPageSize = PAGESIZE ) nothrow + this( void delegate() dg, size_t sz = pageSize * defaultStackPages, + size_t guardPageSize = pageSize ) nothrow { allocStack( sz, guardPageSize ); reset( cast(void delegate() const) dg ); @@ -962,9 +964,9 @@ private: } do { - // adjust alloc size to a multiple of PAGESIZE - sz += PAGESIZE - 1; - sz -= sz % PAGESIZE; + // adjust alloc size to a multiple of pageSize + sz += pageSize - 1; + sz -= sz % pageSize; // NOTE: This instance of Thread.Context is dynamic so Fiber objects // can be collected by the GC so long as no user level references diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d index 7316373..066f39e 100644 --- a/libphobos/libdruntime/core/thread/osthread.d +++ b/libphobos/libdruntime/core/thread/osthread.d @@ -19,7 +19,7 @@ import core.thread.threadbase; import core.thread.context; import core.thread.types; import core.atomic; -import core.memory : GC; +import core.memory : GC, pageSize; import core.time; import core.exception : onOutOfMemoryError; import core.internal.traits : externDFunc; @@ -1115,7 +1115,7 @@ unittest unittest { - // use >PAGESIZE to avoid stack overflow (e.g. in an syscall) + // use >pageSize to avoid stack overflow (e.g. in an syscall) auto thr = new Thread(function{}, 4096 + 1).start(); thr.join(); } @@ -2889,8 +2889,8 @@ private size_t adjustStackSize(size_t sz) nothrow @nogc } } - // stack size must be a multiple of PAGESIZE - sz = ((sz + PAGESIZE - 1) & ~(PAGESIZE - 1)); + // stack size must be a multiple of pageSize + sz = ((sz + pageSize - 1) & ~(pageSize - 1)); return sz; } diff --git a/libphobos/libdruntime/core/thread/types.d b/libphobos/libdruntime/core/thread/types.d index e50399a..eb84ad7 100644 --- a/libphobos/libdruntime/core/thread/types.d +++ b/libphobos/libdruntime/core/thread/types.d @@ -47,31 +47,15 @@ else package { - static immutable size_t PAGESIZE; version (Posix) static immutable size_t PTHREAD_STACK_MIN; } shared static this() { - version (Windows) - { - import core.sys.windows.winbase; - - SYSTEM_INFO info; - GetSystemInfo(&info); - - PAGESIZE = info.dwPageSize; - assert(PAGESIZE < int.max); - } - else version (Posix) + version (Posix) { import core.sys.posix.unistd; - PAGESIZE = cast(size_t)sysconf(_SC_PAGESIZE); PTHREAD_STACK_MIN = cast(size_t)sysconf(_SC_THREAD_STACK_MIN); } - else - { - static assert(0, "unimplemented"); - } } diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d index 0385b51..a77788b 100644 --- a/libphobos/libdruntime/object.d +++ b/libphobos/libdruntime/object.d @@ -246,7 +246,7 @@ class Object * } * --- */ - deprecated static Object factory(string classname) + static Object factory(string classname) { auto ci = TypeInfo_Class.find(classname); if (ci) @@ -256,7 +256,7 @@ class Object return null; } - deprecated @system unittest + @system unittest { Object valid_obj = Object.factory("object.Object"); Object invalid_obj = Object.factory("object.__this_class_doesnt_exist__"); @@ -1417,7 +1417,7 @@ class TypeInfo_Function : TypeInfo int func(int a, int b); } - alias functionTypes = typeof(__traits(getVirtualFunctions, C, "func")); + alias functionTypes = typeof(__traits(getVirtualMethods, C, "func")); assert(typeid(functionTypes[0]).toString() == "void function()"); assert(typeid(functionTypes[1]).toString() == "void function(int)"); assert(typeid(functionTypes[2]).toString() == "int function(int, int)"); @@ -1431,7 +1431,7 @@ class TypeInfo_Function : TypeInfo void func(int a); } - alias functionTypes = typeof(__traits(getVirtualFunctions, C, "func")); + alias functionTypes = typeof(__traits(getVirtualMethods, C, "func")); Object obj = typeid(functionTypes[0]); assert(obj.opEquals(typeid(functionTypes[0]))); @@ -2927,25 +2927,6 @@ void clear(Value, Key)(Value[Key]* aa) assert("k1" !in aa); } -// Issue 20559 -@system unittest -{ - static class Foo - { - int[string] aa; - alias aa this; - } - - auto v = new Foo(); - v["Hello World"] = 42; - v.clear; - assert("Hello World" !in v); - - // Test for T* - static assert(!__traits(compiles, (&v).clear)); - static assert( __traits(compiles, (*(&v)).clear)); -} - /*********************************** * Reorganizes the associative array in place so that lookups are more * efficient. @@ -4280,44 +4261,6 @@ void destroy(bool initialize = true, T)(T obj) if (is(T == interface)) @system unittest { - // class with an `alias this` - class A - { - static int dtorCount; - ~this() - { - dtorCount++; - } - } - - class B - { - A a; - alias a this; - this() - { - a = new A; - } - static int dtorCount; - ~this() - { - dtorCount++; - } - } - auto b = new B; - assert(A.dtorCount == 0); - assert(B.dtorCount == 0); - destroy(b); - assert(A.dtorCount == 0); - assert(B.dtorCount == 1); - - auto a = new A; - destroy(a); - assert(A.dtorCount == 1); -} - -@system unittest -{ interface I { } { class A: I { string s = "A"; this() {} } @@ -4529,43 +4472,6 @@ if (__traits(isStaticArray, T)) } } -// https://issues.dlang.org/show_bug.cgi?id=19218 -@system unittest -{ - static struct S - { - static dtorCount = 0; - ~this() { ++dtorCount; } - } - - static interface I - { - ref S[3] getArray(); - alias getArray this; - } - - static class C : I - { - static dtorCount = 0; - ~this() { ++dtorCount; } - - S[3] a; - alias a this; - - ref S[3] getArray() { return a; } - } - - C c = new C(); - destroy(c); - assert(S.dtorCount == 3); - assert(C.dtorCount == 1); - - I i = new C(); - destroy(i); - assert(S.dtorCount == 6); - assert(C.dtorCount == 2); -} - /// ditto void destroy(bool initialize = true, T)(ref T obj) if (!is(T == struct) && !is(T == interface) && !is(T == class) && !__traits(isStaticArray, T)) @@ -4622,7 +4528,8 @@ they are only intended to be instantiated by the compiler, not the user. public import core.internal.entrypoint : _d_cmain; public import core.internal.array.appending : _d_arrayappendT; -public import core.internal.array.appending : _d_arrayappendTTrace; +version (D_ProfileGC) + public import core.internal.array.appending : _d_arrayappendTTrace; public import core.internal.array.appending : _d_arrayappendcTXImpl; public import core.internal.array.comparison : __cmp; public import core.internal.array.equality : __equals; @@ -4648,6 +4555,8 @@ public import core.internal.switch_: __switch_error; public import core.lifetime : _d_delstructImpl; public import core.lifetime : _d_newThrowable; +public import core.lifetime : _d_newclassT; +public import core.lifetime : _d_newclassTTrace; public @trusted @nogc nothrow pure extern (C) void _d_delThrowable(scope Throwable); diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index 0b4fe45..a2191397 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -e5a521ab2bddfa0a42ecf371910ffe6a2fe0a03a +454dff14dcbd005f9550302c5836ef8e06ab663a The first line of this file holds the git revision number of the last merge done from the dlang/phobos repository. diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d index 967d2a6..8236076 100644 --- a/libphobos/src/std/algorithm/iteration.d +++ b/libphobos/src/std/algorithm/iteration.d @@ -2969,10 +2969,24 @@ iterated from the back to the front, the separator will still be consumed from front to back, even if it is a bidirectional range too. */ auto joiner(RoR, Separator)(RoR r, Separator sep) -if (isInputRange!RoR && isInputRange!(ElementType!RoR) - && isForwardRange!Separator - && is(ElementType!Separator : ElementType!(ElementType!RoR))) { + static assert(isInputRange!RoR, "The type of RoR '", RoR.stringof + , " must be an InputRange (isInputRange!", RoR.stringof, ")."); + static assert(isInputRange!(ElementType!RoR), "The ElementyType of RoR '" + , ElementType!(RoR).stringof, "' must be an InputRange " + , "(isInputRange!(ElementType!(", RoR.stringof , ")))."); + static assert(isForwardRange!Separator, "The type of the Seperator '" + , Seperator.stringof, "' must be a ForwardRange (isForwardRange!(" + , Seperator.stringof, "))."); + static assert(is(ElementType!Separator : ElementType!(ElementType!RoR)) + , "The type of the elements of the separator range does not match " + , "the type of the elements that are joined. Separator type '" + , ElementType!(Separator).stringof, "' is not implicitly" + , "convertible to range element type '" + , ElementType!(ElementType!RoR).stringof, "' (is(ElementType!" + , Separator.stringof, " : ElementType!(ElementType!", RoR.stringof + , ")))."); + static struct Result { private RoR _items; diff --git a/libphobos/src/std/algorithm/package.d b/libphobos/src/std/algorithm/package.d index 6aacd51..71bd1d9 100644 --- a/libphobos/src/std/algorithm/package.d +++ b/libphobos/src/std/algorithm/package.d @@ -103,6 +103,7 @@ $(TR $(SUBREF sorting, multiSort) $(SUBREF sorting, nextEvenPermutation) $(SUBREF sorting, nextPermutation) + $(SUBREF sorting, nthPermutation) $(SUBREF sorting, partialSort) $(SUBREF sorting, partition) $(SUBREF sorting, partition3) diff --git a/libphobos/src/std/algorithm/sorting.d b/libphobos/src/std/algorithm/sorting.d index ddb80b8..c5b085d 100644 --- a/libphobos/src/std/algorithm/sorting.d +++ b/libphobos/src/std/algorithm/sorting.d @@ -1922,14 +1922,8 @@ See_Also: $(REF binaryFun, std,functional) */ SortedRange!(Range, less) -sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, - Range)(Range r) -if (((ss == SwapStrategy.unstable && (hasSwappableElements!Range || - hasAssignableElements!Range)) || - (ss != SwapStrategy.unstable && hasAssignableElements!Range)) && - isRandomAccessRange!Range && - hasSlicing!Range && - hasLength!Range) +sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range) +(Range r) /+ Unstable sorting uses the quicksort algorithm, which uses swapAt, which either uses swap(...), requiring swappable elements, or just swaps using assignment. @@ -1937,21 +1931,46 @@ if (((ss == SwapStrategy.unstable && (hasSwappableElements!Range || requiring assignable elements. +/ { import std.range : assumeSorted; - alias lessFun = binaryFun!(less); - alias LessRet = typeof(lessFun(r.front, r.front)); // instantiate lessFun - static if (is(LessRet == bool)) + static if (ss == SwapStrategy.unstable) { - static if (ss == SwapStrategy.unstable) - quickSortImpl!(lessFun)(r, r.length); - else //use Tim Sort for semistable & stable - TimSortImpl!(lessFun, Range).sort(r, null); - - assert(isSorted!lessFun(r), "Failed to sort range of type " ~ Range.stringof); + static assert(hasSwappableElements!Range || hasAssignableElements!Range, + "When using SwapStrategy.unstable, the passed Range '" + ~ Range.stringof ~ "' must" + ~ " either fulfill hasSwappableElements, or" + ~ " hasAssignableElements, both were not the case"); } else { - static assert(false, "Invalid predicate passed to sort: " ~ less.stringof); + static assert(hasAssignableElements!Range, "When using a SwapStrategy" + ~ " != unstable, the" + ~ " passed Range '" ~ Range.stringof ~ "' must fulfill" + ~ " hasAssignableElements, which it did not"); } + + static assert(isRandomAccessRange!Range, "The passed Range '" + ~ Range.stringof ~ "' must be a Random AccessRange " + ~ "(isRandomAccessRange)"); + + static assert(hasSlicing!Range, "The passed Range '" + ~ Range.stringof ~ "' must allow Slicing (hasSlicing)"); + + static assert(hasLength!Range, "The passed Range '" + ~ Range.stringof ~ "' must have a length (hasLength)"); + + alias lessFun = binaryFun!(less); + alias LessRet = typeof(lessFun(r.front, r.front)); // instantiate lessFun + + static assert(is(LessRet == bool), "The return type of the template" + ~ " argument 'less' when used with the binaryFun!less template" + ~ " must be a bool. This is not the case, the returned type is '" + ~ LessRet.stringof ~ "'"); + + static if (ss == SwapStrategy.unstable) + quickSortImpl!(lessFun)(r, r.length); + else //use Tim Sort for semistable & stable + TimSortImpl!(lessFun, Range).sort(r, null); + + assert(isSorted!lessFun(r), "Failed to sort range of type " ~ Range.stringof); return assumeSorted!less(r); } @@ -2599,8 +2618,16 @@ private template TimSortImpl(alias pred, R) //Test for overflow if (newSize < minCapacity) newSize = minCapacity; - if (__ctfe) temp.length = newSize; - else temp = () @trusted { return uninitializedArray!(T[])(newSize); }(); + // can't use `temp.length` if there's no default constructor + static if (__traits(compiles, { T defaultConstructed; cast(void) defaultConstructed; })) + { + if (__ctfe) temp.length = newSize; + else temp = () @trusted { return uninitializedArray!(T[])(newSize); }(); + } + else + { + temp = () @trusted { return uninitializedArray!(T[])(newSize); }(); + } } return temp; } @@ -3037,6 +3064,18 @@ private template TimSortImpl(alias pred, R) sort!(cmp, SwapStrategy.stable)(makeArray(minMerge + 5)); } +// https://issues.dlang.org/show_bug.cgi?id=23668 +@safe unittest +{ + static struct S + { + int opCmp(const S) const { return 1; } + @disable this(); + } + S[] array; + array.sort!("a < b", SwapStrategy.stable); +} + // schwartzSort /** Alternative sorting method that should be used when comparing keys involves an diff --git a/libphobos/src/std/array.d b/libphobos/src/std/array.d index daa103a..4584dcc 100644 --- a/libphobos/src/std/array.d +++ b/libphobos/src/std/array.d @@ -170,7 +170,7 @@ if (isIterable!Range && !isAutodecodableString!Range && !isInfinite!Range) /// ditto ForeachType!(typeof((*Range).init))[] array(Range)(Range r) -if (is(Range : U*, U) && isIterable!U && !isAutodecodableString!Range && !isInfinite!Range) +if (is(Range == U*, U) && isIterable!U && !isAutodecodableString!Range && !isInfinite!Range) { return array(*r); } @@ -2294,22 +2294,6 @@ if (isInputRange!RoR && } } -// https://issues.dlang.org/show_bug.cgi?id=10895 -@safe unittest -{ - static class A - { - string name; - alias name this; - this(string name) { this.name = name; } - } - auto a = [new A(`foo`)]; - assert(a[0].length == 3); - auto temp = join(a, " "); - assert(a[0].length == 3); - assert(temp.length == 3); -} - // https://issues.dlang.org/show_bug.cgi?id=14230 @safe unittest { diff --git a/libphobos/src/std/bitmanip.d b/libphobos/src/std/bitmanip.d index 559f8da..b84a676 100644 --- a/libphobos/src/std/bitmanip.d +++ b/libphobos/src/std/bitmanip.d @@ -89,22 +89,21 @@ private template createAccessors( } else { - enum ulong - maskAllElse = ((~0uL) >> (64 - len)) << offset, - signBitCheck = 1uL << (len - 1); + enum ulong maskAllElse = ((~0uL) >> (64 - len)) << offset; + enum TSize = 8 * T.sizeof; + enum SignShift = TSize - len; static if (T.min < 0) { enum long minVal = -(1uL << (len - 1)); enum ulong maxVal = (1uL << (len - 1)) - 1; - alias UT = Unsigned!(T); - enum UT extendSign = cast(UT)~((~0uL) >> (64 - len)); + enum RightShiftOp = ">>="; } else { enum ulong minVal = 0; enum ulong maxVal = (~0uL) >> (64 - len); - enum extendSign = 0; + enum RightShiftOp = ">>>="; } static if (is(T == bool)) @@ -121,15 +120,11 @@ private template createAccessors( else { // getter - enum createAccessors = "@property "~T.stringof~" "~name~"() @safe pure nothrow @nogc const { auto result = " - ~"("~store~" & " - ~ myToString(maskAllElse) ~ ") >>" - ~ myToString(offset) ~ ";" - ~ (T.min < 0 - ? "if (result >= " ~ myToString(signBitCheck) - ~ ") result |= " ~ myToString(extendSign) ~ ";" - : "") - ~ " return cast("~T.stringof~") result;}\n" + enum createAccessors = "@property "~T.stringof~" "~name~"() @safe pure nothrow @nogc const {" + ~ "auto result = cast("~T.stringof~") (" ~ store ~ " >>" ~ myToString(offset) ~ ");" + ~ "result <<= " ~ myToString(SignShift) ~ ";" + ~ "result " ~ RightShiftOp ~ myToString(SignShift) ~ ";" + ~ " return result;}\n" // setter ~"@property void "~name~"("~T.stringof~" v) @safe pure nothrow @nogc { " ~"assert(v >= "~name~`_min, "Value is smaller than the minimum value of bitfield '`~name~`'"); ` diff --git a/libphobos/src/std/concurrency.d b/libphobos/src/std/concurrency.d index 323926a..7fe52ba 100644 --- a/libphobos/src/std/concurrency.d +++ b/libphobos/src/std/concurrency.d @@ -46,7 +46,7 @@ * * This is a low-level messaging API upon which more structured or restrictive * APIs may be built. The general idea is that every messageable entity is - * represented by a common handle type called a Tid, which allows messages to + * represented by a common handle type called a `Tid`, which allows messages to * be sent to logical threads that are executing in both the current process * and in external processes using the same interface. This is an important * aspect of scalability because it allows the components of a program to be @@ -55,11 +55,11 @@ * * A logical thread is an execution context that has its own stack and which * runs asynchronously to other logical threads. These may be preemptively - * scheduled kernel threads, fibers (cooperative user-space threads), or some - * other concept with similar behavior. + * scheduled kernel threads, $(MREF_ALTTEXT fibers, core, thread, fiber) + * (cooperative user-space threads), or some other concept with similar behavior. * * The type of concurrency used when logical threads are created is determined - * by the Scheduler selected at initialization time. The default behavior is + * by the $(LREF Scheduler) selected at initialization time. The default behavior is * currently to create a new kernel thread per call to spawn, but other * schedulers are available that multiplex fibers across the main thread or * use some combination of the two approaches. @@ -274,7 +274,7 @@ static ~this() // Exceptions /** - * Thrown on calls to `receiveOnly` if a message other than the type + * Thrown on calls to $(LREF receiveOnly) if a message other than the type * the receiving thread expected is sent. */ class MessageMismatch : Exception @@ -287,7 +287,7 @@ class MessageMismatch : Exception } /** - * Thrown on calls to `receive` if the thread that spawned the receiving + * Thrown on calls to $(LREF receive) if the thread that spawned the receiving * thread has terminated and no more messages exist. */ class OwnerTerminated : Exception @@ -354,7 +354,7 @@ class MailboxFull : Exception } /** - * Thrown when a Tid is missing, e.g. when `ownerTid` doesn't + * Thrown when a `Tid` is missing, e.g. when $(LREF ownerTid) doesn't * find an owner thread. */ class TidMissingException : Exception @@ -384,11 +384,11 @@ private: public: /** - * Generate a convenient string for identifying this Tid. This is only - * useful to see if Tid's that are currently executing are the same or + * Generate a convenient string for identifying this `Tid`. This is only + * useful to see if `Tid`'s that are currently executing are the same or * different, e.g. for logging and debugging. It is potentially possible - * that a Tid executed in the future will have the same toString() output - * as another Tid that has already terminated. + * that a `Tid` executed in the future will have the same `toString()` output + * as another `Tid` that has already terminated. */ void toString(W)(ref W w) const { @@ -420,7 +420,7 @@ public: } /** - * Returns: The $(LREF Tid) of the caller's thread. + * Returns: The `Tid` of the caller's thread. */ @property Tid thisTid() @safe { @@ -437,7 +437,7 @@ public: } /** - * Return the Tid of the thread which spawned the caller's thread. + * Return the `Tid` of the thread which spawned the caller's thread. * * Throws: A `TidMissingException` exception if * there is no owner thread. @@ -493,7 +493,7 @@ private template isSpawnable(F, T...) } /** - * Starts fn(args) in a new logical thread. + * Starts `fn(args)` in a new logical thread. * * Executes the supplied function in a new logical thread represented by * `Tid`. The calling thread is designated as the owner of the new thread. @@ -506,7 +506,7 @@ private template isSpawnable(F, T...) * args = Arguments to the function. * * Returns: - * A Tid representing the new logical thread. + * A `Tid` representing the new logical thread. * * Notes: * `args` must not have unshared aliasing. In other words, all arguments @@ -573,16 +573,16 @@ if (isSpawnable!(F, T)) } /** - * Starts fn(args) in a logical thread and will receive a LinkTerminated + * Starts `fn(args)` in a logical thread and will receive a `LinkTerminated` * message when the operation terminates. * * Executes the supplied function in a new logical thread represented by - * Tid. This new thread is linked to the calling thread so that if either - * it or the calling thread terminates a LinkTerminated message will be sent - * to the other, causing a LinkTerminated exception to be thrown on receive(). - * The owner relationship from spawn() is preserved as well, so if the link + * `Tid`. This new thread is linked to the calling thread so that if either + * it or the calling thread terminates a `LinkTerminated` message will be sent + * to the other, causing a `LinkTerminated` exception to be thrown on `receive()`. + * The owner relationship from `spawn()` is preserved as well, so if the link * between threads is broken, owner termination will still result in an - * OwnerTerminated exception to be thrown on receive(). + * `OwnerTerminated` exception to be thrown on `receive()`. * * Params: * fn = The function to execute. @@ -1021,7 +1021,7 @@ do enum OnCrowding { block, /// Wait until room is available. - throwException, /// Throw a MailboxFull exception. + throwException, /// Throw a $(LREF MailboxFull) exception. ignore /// Abort the send and return. } @@ -1178,13 +1178,13 @@ bool unregister(string name) } /** - * Gets the Tid associated with name. + * Gets the `Tid` associated with name. * * Params: * name = The name to locate within the registry. * * Returns: - * The associated Tid or Tid.init if name is not registered. + * The associated `Tid` or `Tid.init` if name is not registered. */ Tid locate(string name) { @@ -1199,7 +1199,7 @@ Tid locate(string name) /** * Encapsulates all implementation-level data needed for scheduling. * - * When defining a Scheduler, an instance of this struct must be associated + * When defining a $(LREF Scheduler), an instance of this struct must be associated * with each logical thread. It contains all implementation-level information * needed by the internal API. */ @@ -1210,11 +1210,11 @@ struct ThreadInfo Tid owner; /** - * Gets a thread-local instance of ThreadInfo. + * Gets a thread-local instance of `ThreadInfo`. * - * Gets a thread-local instance of ThreadInfo, which should be used as the + * Gets a thread-local instance of `ThreadInfo`, which should be used as the * default instance when info is requested for a thread not created by the - * Scheduler. + * `Scheduler`. */ static @property ref thisInfo() nothrow { @@ -1253,15 +1253,15 @@ struct ThreadInfo } /** - * A Scheduler controls how threading is performed by spawn. + * A `Scheduler` controls how threading is performed by spawn. * - * Implementing a Scheduler allows the concurrency mechanism used by this + * Implementing a `Scheduler` allows the concurrency mechanism used by this * module to be customized according to different needs. By default, a call * to spawn will create a new kernel thread that executes the supplied routine - * and terminates when finished. But it is possible to create Schedulers that - * reuse threads, that multiplex Fibers (coroutines) across a single thread, - * or any number of other approaches. By making the choice of Scheduler a - * user-level option, std.concurrency may be used for far more types of + * and terminates when finished. But it is possible to create `Scheduler`s that + * reuse threads, that multiplex `Fiber`s (coroutines) across a single thread, + * or any number of other approaches. By making the choice of `Scheduler` a + * user-level option, `std.concurrency` may be used for far more types of * application than if this behavior were predefined. * * Example: @@ -1280,25 +1280,25 @@ struct ThreadInfo * --- * * Some schedulers have a dispatching loop that must run if they are to work - * properly, so for the sake of consistency, when using a scheduler, start() - * must be called within main(). This yields control to the scheduler and + * properly, so for the sake of consistency, when using a scheduler, `start()` + * must be called within `main()`. This yields control to the scheduler and * will ensure that any spawned threads are executed in an expected manner. */ interface Scheduler { /** - * Spawns the supplied op and starts the Scheduler. + * Spawns the supplied op and starts the `Scheduler`. * * This is intended to be called at the start of the program to yield all - * scheduling to the active Scheduler instance. This is necessary for + * scheduling to the active `Scheduler` instance. This is necessary for * schedulers that explicitly dispatch threads rather than simply relying * on the operating system to do so, and so start should always be called - * within main() to begin normal program execution. + * within `main()` to begin normal program execution. * * Params: * op = A wrapper for whatever the main thread would have done in the * absence of a custom scheduler. It will be automatically executed - * via a call to spawn by the Scheduler. + * via a call to spawn by the `Scheduler`. */ void start(void delegate() op); @@ -1307,8 +1307,8 @@ interface Scheduler * * This routine is called by spawn. It is expected to instantiate a new * logical thread and run the supplied operation. This thread must call - * thisInfo.cleanup() when the thread terminates if the scheduled thread - * is not a kernel thread--all kernel threads will have their ThreadInfo + * `thisInfo.cleanup()` when the thread terminates if the scheduled thread + * is not a kernel thread--all kernel threads will have their `ThreadInfo` * cleaned up automatically by a thread-local destructor. * * Params: @@ -1329,36 +1329,36 @@ interface Scheduler void yield() nothrow; /** - * Returns an appropriate ThreadInfo instance. + * Returns an appropriate `ThreadInfo` instance. * - * Returns an instance of ThreadInfo specific to the logical thread that + * Returns an instance of `ThreadInfo` specific to the logical thread that * is calling this routine or, if the calling thread was not create by - * this scheduler, returns ThreadInfo.thisInfo instead. + * this scheduler, returns `ThreadInfo.thisInfo` instead. */ @property ref ThreadInfo thisInfo() nothrow; /** - * Creates a Condition variable analog for signaling. + * Creates a `Condition` variable analog for signaling. * - * Creates a new Condition variable analog which is used to check for and + * Creates a new `Condition` variable analog which is used to check for and * to signal the addition of messages to a thread's message queue. Like * yield, some schedulers may need to define custom behavior so that calls - * to Condition.wait() yield to another thread when no new messages are + * to `Condition.wait()` yield to another thread when no new messages are * available instead of blocking. * * Params: - * m = The Mutex that will be associated with this condition. It will be + * m = The `Mutex` that will be associated with this condition. It will be * locked prior to any operation on the condition, and so in some - * cases a Scheduler may need to hold this reference and unlock the + * cases a `Scheduler` may need to hold this reference and unlock the * mutex before yielding execution to another logical thread. */ Condition newCondition(Mutex m) nothrow; } /** - * An example Scheduler using kernel threads. + * An example `Scheduler` using kernel threads. * - * This is an example Scheduler that mirrors the default scheduling behavior + * This is an example `Scheduler` that mirrors the default scheduling behavior * of creating one kernel thread per call to spawn. It is fully functional * and may be instantiated and used, but is not a necessary part of the * default functioning of this module. @@ -1392,8 +1392,8 @@ class ThreadScheduler : Scheduler } /** - * Returns ThreadInfo.thisInfo, since it is a thread-local instance of - * ThreadInfo, which is the correct behavior for this scheduler. + * Returns `ThreadInfo.thisInfo`, since it is a thread-local instance of + * `ThreadInfo`, which is the correct behavior for this scheduler. */ @property ref ThreadInfo thisInfo() nothrow { @@ -1401,7 +1401,7 @@ class ThreadScheduler : Scheduler } /** - * Creates a new Condition variable. No custom behavior is needed here. + * Creates a new `Condition` variable. No custom behavior is needed here. */ Condition newCondition(Mutex m) nothrow { @@ -1410,15 +1410,15 @@ class ThreadScheduler : Scheduler } /** - * An example Scheduler using Fibers. + * An example `Scheduler` using $(MREF_ALTTEXT `Fiber`s, core, thread, fiber). * - * This is an example scheduler that creates a new Fiber per call to spawn + * This is an example scheduler that creates a new `Fiber` per call to spawn * and multiplexes the execution of all fibers within the main thread. */ class FiberScheduler : Scheduler { /** - * This creates a new Fiber for the supplied op and then starts the + * This creates a new `Fiber` for the supplied op and then starts the * dispatcher. */ void start(void delegate() op) @@ -1428,7 +1428,7 @@ class FiberScheduler : Scheduler } /** - * This created a new Fiber for the supplied op and adds it to the + * This created a new `Fiber` for the supplied op and adds it to the * dispatch list. */ void spawn(void delegate() op) nothrow @@ -1438,8 +1438,8 @@ class FiberScheduler : Scheduler } /** - * If the caller is a scheduled Fiber, this yields execution to another - * scheduled Fiber. + * If the caller is a scheduled `Fiber`, this yields execution to another + * scheduled `Fiber`. */ void yield() nothrow { @@ -1451,11 +1451,11 @@ class FiberScheduler : Scheduler } /** - * Returns an appropriate ThreadInfo instance. + * Returns an appropriate `ThreadInfo` instance. * - * Returns a ThreadInfo instance specific to the calling Fiber if the - * Fiber was created by this dispatcher, otherwise it returns - * ThreadInfo.thisInfo. + * Returns a `ThreadInfo` instance specific to the calling `Fiber` if the + * `Fiber` was created by this dispatcher, otherwise it returns + * `ThreadInfo.thisInfo`. */ @property ref ThreadInfo thisInfo() nothrow { @@ -1467,10 +1467,10 @@ class FiberScheduler : Scheduler } /** - * Returns a Condition analog that yields when wait or notify is called. + * Returns a `Condition` analog that yields when wait or notify is called. * * Bug: - * For the default implementation, `notifyAll`will behave like `notify`. + * For the default implementation, `notifyAll` will behave like `notify`. * * Params: * m = A `Mutex` to use for locking if the condition needs to be waited on @@ -1485,7 +1485,7 @@ class FiberScheduler : Scheduler protected: /** - * Creates a new Fiber which calls the given delegate. + * Creates a new `Fiber` which calls the given delegate. * * Params: * op = The delegate the fiber should call @@ -1505,7 +1505,7 @@ protected: } /** - * Fiber which embeds a ThreadInfo + * `Fiber` which embeds a `ThreadInfo` */ static class InfoFiber : Fiber { @@ -1650,10 +1650,10 @@ private: } /** - * Sets the Scheduler behavior within the program. + * Sets the `Scheduler` behavior within the program. * - * This variable sets the Scheduler behavior within this program. Typically, - * when setting a Scheduler, scheduler.start() should be called in main. This + * This variable sets the `Scheduler` behavior within this program. Typically, + * when setting a `Scheduler`, `scheduler.start()` should be called in `main`. This * routine will not return until program execution is complete. */ __gshared Scheduler scheduler; @@ -1661,8 +1661,8 @@ __gshared Scheduler scheduler; // Generator /** - * If the caller is a Fiber and is not a Generator, this function will call - * scheduler.yield() or Fiber.yield(), as appropriate. + * If the caller is a `Fiber` and is not a $(LREF Generator), this function will call + * `scheduler.yield()` or `Fiber.yield()`, as appropriate. */ void yield() nothrow { @@ -1684,8 +1684,9 @@ private interface IsGenerator {} /** - * A Generator is a Fiber that periodically returns values of type T to the - * caller via yield. This is represented as an InputRange. + * A Generator is a $(MREF_ALTTEXT Fiber, core, thread, fiber) + * that periodically returns values of type `T` to the + * caller via `yield`. This is represented as an InputRange. */ class Generator(T) : Fiber, IsGenerator, InputRange!T @@ -1829,7 +1830,7 @@ class Generator(T) : /** * Returns the most recently generated value without executing a * copy contructor. Will not compile for element types defining a - * postblit, because Generator does not return by reference. + * postblit, because `Generator` does not return by reference. */ final T moveFront() { diff --git a/libphobos/src/std/container/binaryheap.d b/libphobos/src/std/container/binaryheap.d index 7ff14fc..0fd3452 100644 --- a/libphobos/src/std/container/binaryheap.d +++ b/libphobos/src/std/container/binaryheap.d @@ -597,3 +597,43 @@ BinaryHeap!(Store, less) heapify(alias less = "a < b", Store)(Store s, heap.insert(6); assert(equal(heap, [6, 5])); } + +/** +Example for unintuitive behaviour +It is important not to use the Store after a Heap has been instantiated from +it, at least in the cases of Dynamic Arrays. For example, inserting a new element +in a Heap, which is using a Dyamic Array as a Store, will cause a reallocation of +the Store, if the Store is already full. The Heap will not point anymore to the +original Dyamic Array, but point to a new Dynamic Array. + */ + +// https://issues.dlang.org/show_bug.cgi?id=18333 +@system unittest +{ + import std.stdio; + import std.algorithm.comparison : equal; + import std.container.binaryheap; + + int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ]; + auto h = heapify(a); + + // Internal representation of Binary Heap tree + assert(a.equal([16, 14, 10, 8, 7, 9, 3, 2, 4, 1])); + + h.replaceFront(30); + // Value 16 was replaced by 30 + assert(a.equal([30, 14, 10, 8, 7, 9, 3, 2, 4, 1])); + + // Making changes to the Store will be seen in the Heap + a[0] = 40; + assert(h.front() == 40); + + // Inserting a new element will reallocate the Store, leaving + // the original Store unchanged. + h.insert(20); + assert(a.equal([40, 14, 10, 8, 7, 9, 3, 2, 4, 1])); + + // Making changes to the original Store will not affect the Heap anymore + a[0] = 60; + assert(h.front() == 40); +} diff --git a/libphobos/src/std/exception.d b/libphobos/src/std/exception.d index b699a8e..6ffc0f7 100644 --- a/libphobos/src/std/exception.d +++ b/libphobos/src/std/exception.d @@ -1069,9 +1069,9 @@ as the language is free to assume objects don't have internal pointers */ bool doesPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @nogc @trusted pure nothrow if (__traits(isRef, source) || isDynamicArray!S || - is(S : U*, U) || is(S == class)) + is(S == U*, U) || is(S == class)) { - static if (is(S : U*, U) || is(S == class) || is(S == interface)) + static if (is(S == U*, U) || is(S == class) || is(S == interface)) { const m = *cast(void**) &source; const b = cast(void*) ⌖ @@ -1115,9 +1115,9 @@ bool doesPointTo(S, T)(auto ref const shared S source, ref const shared T target /// ditto bool mayPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @trusted pure nothrow if (__traits(isRef, source) || isDynamicArray!S || - is(S : U*, U) || is(S == class)) + is(S == U*, U) || is(S == class)) { - static if (is(S : U*, U) || is(S == class) || is(S == interface)) + static if (is(S == U*, U) || is(S == class) || is(S == interface)) { const m = *cast(void**) &source; const b = cast(void*) ⌖ @@ -1533,21 +1533,6 @@ version (StdUnittest) assert( doesPointTo(cast(int*) s, i)); assert(!doesPointTo(cast(int*) s, j)); } -@safe unittest //more alias this opCast -{ - void* p; - class A - { - void* opCast(T)() if (is(T == void*)) - { - return p; - } - alias foo = opCast!(void*); - alias foo this; - } - assert(!doesPointTo(A.init, p)); - assert(!mayPointTo(A.init, p)); -} /+ Returns true if the field at index `i` in ($D T) shares its address with another field. diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d index d031096..b7bd3fc 100644 --- a/libphobos/src/std/file.d +++ b/libphobos/src/std/file.d @@ -1575,7 +1575,7 @@ private void setTimesImpl(scope const(char)[] names, scope const(FSChar)* namez, const ta = SysTimeToFILETIME(accessTime); const tm = SysTimeToFILETIME(modificationTime); alias defaults = - AliasSeq!(GENERIC_WRITE, + AliasSeq!(FILE_WRITE_ATTRIBUTES, 0, null, OPEN_EXISTING, @@ -1664,6 +1664,16 @@ private void setTimesImpl(scope const(char)[] names, scope const(FSChar)* namez, rmdirRecurse(newdir); } +// https://issues.dlang.org/show_bug.cgi?id=23683 +@safe unittest +{ + scope(exit) deleteme.remove; + import std.stdio : File; + auto f = File(deleteme, "wb"); + SysTime time = SysTime(DateTime(2018, 10, 4, 0, 0, 30)); + setTimes(deleteme, time, time); +} + /++ Returns the time that the given file was last modified. @@ -4930,7 +4940,10 @@ alias DirIterator = _DirIterator!dip1000Enabled; $(LREF DirEntry). Throws: - $(LREF FileException) if the directory does not exist. + $(UL + $(LI $(LREF FileException) if the $(B path) directory does not exist or read permission is denied.) + $(LI $(LREF FileException) if $(B mode) is not `shallow` and a subdirectory cannot be read.) + ) Example: -------------------- @@ -4971,7 +4984,25 @@ auto dFiles = dirEntries("","*.{d,di}",SpanMode.depth); foreach (d; dFiles) writeln(d.name); -------------------- - +/ +To handle subdirectories with denied read permission, use `SpanMode.shallow`: +--- +void scan(string path) +{ + foreach (DirEntry entry; dirEntries(path, SpanMode.shallow)) + { + try + { + writeln(entry.name); + if (entry.isDir) + scan(entry.name); + } + catch (FileException fe) { continue; } // ignore + } +} + +scan(""); +--- ++/ // For some reason, doing the same alias-to-a-template trick as with DirIterator // does not work here. diff --git a/libphobos/src/std/format/internal/write.d b/libphobos/src/std/format/internal/write.d index 32c82995..7f127c0 100644 --- a/libphobos/src/std/format/internal/write.d +++ b/libphobos/src/std/format/internal/write.d @@ -50,27 +50,6 @@ if (is(BooleanTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) @safe unittest { - class C1 - { - bool val; - alias val this; - this(bool v){ val = v; } - } - - class C2 { - bool val; - alias val this; - this(bool v){ val = v; } - override string toString() const { return "C"; } - } - - () @trusted { - formatTest(new C1(false), "false"); - formatTest(new C1(true), "true"); - formatTest(new C2(false), "C"); - formatTest(new C2(true), "C"); - } (); - struct S1 { bool val; @@ -411,26 +390,6 @@ private uint baseOfSpec(in char spec) @safe pure @safe unittest { - class C1 - { - long val; - alias val this; - this(long v){ val = v; } - } - - class C2 - { - long val; - alias val this; - this(long v){ val = v; } - override string toString() const { return "C"; } - } - - () @trusted { - formatTest(new C1(10), "10"); - formatTest(new C2(10), "C"); - } (); - struct S1 { long val; @@ -709,26 +668,6 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) { formatTest(2.25, "2.25"); - class C1 - { - double val; - alias val this; - this(double v){ val = v; } - } - - class C2 - { - double val; - alias val this; - this(double v){ val = v; } - override string toString() const { return "C"; } - } - - () @trusted { - formatTest(new C1(2.25), "2.25"); - formatTest(new C2(2.25), "C"); - } (); - struct S1 { double val; @@ -1078,26 +1017,6 @@ if (is(CharTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) @safe unittest { - class C1 - { - char val; - alias val this; - this(char v){ val = v; } - } - - class C2 - { - char val; - alias val this; - this(char v){ val = v; } - override string toString() const { return "C"; } - } - - () @trusted { - formatTest(new C1('c'), "c"); - formatTest(new C2('c'), "C"); - } (); - struct S1 { char val; @@ -1165,26 +1084,6 @@ if (is(StringTypeOf!T) && !is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToSt @safe unittest { - // Test for bug 5371 for classes - class C1 - { - const string var; - alias var this; - this(string s){ var = s; } - } - - class C2 - { - string var; - alias var this; - this(string s){ var = s; } - } - - () @trusted { - formatTest(new C1("c1"), "c1"); - formatTest(new C2("c2"), "c2"); - } (); - // Test for bug 5371 for structs struct S1 { @@ -1204,16 +1103,6 @@ if (is(StringTypeOf!T) && !is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToSt @safe unittest { - class C3 - { - string val; - alias val this; - this(string s){ val = s; } - override string toString() const { return "C"; } - } - - () @trusted { formatTest(new C3("c3"), "C"); } (); - struct S3 { string val; alias val this; @@ -1436,36 +1325,6 @@ if (is(DynamicArrayTypeOf!T) && !is(StringTypeOf!T) && !is(T == enum) && !hasToS formatTest(S!0b101([0, 1, 2]), "S"); // Test for bug 7628 formatTest(S!0b110([0, 1, 2]), "S"); formatTest(S!0b111([0, 1, 2]), "S"); - - class C(uint flags) - { - int[] arr; - static if (flags & 1) - alias arr this; - - this(int[] a) { arr = a; } - - static if (flags & 2) - { - @property bool empty() const { return arr.length == 0; } - @property int front() const { return arr[0] * 2; } - void popFront() { arr = arr[1 .. $]; } - } - - static if (flags & 4) - override string toString() const { return "C"; } - } - - () @trusted { - formatTest(new C!0b000([0, 1, 2]), (new C!0b000([])).toString()); - formatTest(new C!0b001([0, 1, 2]), "[0, 1, 2]"); // Test for bug 7628 - formatTest(new C!0b010([0, 1, 2]), "[0, 2, 4]"); - formatTest(new C!0b011([0, 1, 2]), "[0, 2, 4]"); - formatTest(new C!0b100([0, 1, 2]), "C"); - formatTest(new C!0b101([0, 1, 2]), "C"); // Test for bug 7628 - formatTest(new C!0b110([0, 1, 2]), "C"); - formatTest(new C!0b111([0, 1, 2]), "C"); - } (); } @safe unittest @@ -1901,26 +1760,6 @@ if (is(AssocArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) @safe unittest { - class C1 - { - int[char] val; - alias val this; - this(int[char] v){ val = v; } - } - - class C2 - { - int[char] val; - alias val this; - this(int[char] v){ val = v; } - override string toString() const { return "C"; } - } - - () @trusted { - formatTest(new C1(['c':1, 'd':2]), [`['c':1, 'd':2]`, `['d':2, 'c':1]`]); - formatTest(new C2(['c':1, 'd':2]), "C"); - } (); - struct S1 { int[char] val; @@ -1990,7 +1829,8 @@ enum HasToStringResult customPutWriterFormatSpec, } -private enum hasPreviewIn = !is(typeof(mixin(q{(in ref int a) => a}))); +private alias DScannerBug895 = int[256]; +private immutable bool hasPreviewIn = ((in DScannerBug895 a) { return __traits(isRef, a); })(DScannerBug895.init); template hasToString(T, Char) { @@ -3167,18 +3007,6 @@ if (isPointer!T && !is(T == enum) && !hasToString!(T, Char)) formatTest(q, "FFEECCAA"); } -// https://issues.dlang.org/show_bug.cgi?id=8186 -@system unittest -{ - class B - { - int* a; - this() { a = new int; } - alias a this; - } - formatTest(B.init, "null"); -} - // https://issues.dlang.org/show_bug.cgi?id=9336 @system pure unittest { diff --git a/libphobos/src/std/format/read.d b/libphobos/src/std/format/read.d index 144fa8c..da9d0dc 100644 --- a/libphobos/src/std/format/read.d +++ b/libphobos/src/std/format/read.d @@ -303,8 +303,23 @@ uint formattedRead(alias fmt, Range, Args...)(auto ref Range r, auto ref Args ar if (isSomeString!(typeof(fmt))) { import std.format : checkFormatException; + import std.meta : staticMap; + import std.typecons : Tuple; + - alias e = checkFormatException!(fmt, Args); + // formattedRead supports std.typecons.Tuple + // however, checkFormatException does not + // this means that all std.typecons.Tuple's types in Args must be unwrapped + // and passed to checkFormatException + template Flatten(T) + { + static if (is(T : Tuple!Args, Args...)) + alias Flatten = Args; + else + alias Flatten = T; + } + + alias e = checkFormatException!(fmt, staticMap!(Flatten, Args)); static assert(!e, e); return .formattedRead(r, fmt, args); } @@ -361,6 +376,20 @@ if (isSomeString!(typeof(fmt))) assert(t[0] == 1 && t[1] == 2.125); } +// https://issues.dlang.org/show_bug.cgi?id=23600 +@safe pure unittest +{ + import std.typecons : Tuple, tuple; + + string h, w; + Tuple!(int, float) t; + + assert("hello 1 2.34 world".formattedRead!"%s %d %f %s"(h, t, w) == 3); + assert(h == "hello"); + assert(t == tuple(1, 2.34f)); + assert(w == "world"); +} + @safe unittest { import std.math.operations : isClose; diff --git a/libphobos/src/std/getopt.d b/libphobos/src/std/getopt.d index c85247f..42aeb40 100644 --- a/libphobos/src/std/getopt.d +++ b/libphobos/src/std/getopt.d @@ -558,7 +558,7 @@ private template optionValidator(A...) import std.format : format; enum fmt = "getopt validator: %s (at position %d)"; - enum isReceiver(T) = is(T : U*, U) || (is(T == function)) || (is(T == delegate)); + enum isReceiver(T) = is(T == U*, U) || (is(T == function)) || (is(T == delegate)); enum isOptionStr(T) = isSomeString!T || isSomeChar!T; auto validator() diff --git a/libphobos/src/std/internal/unicode_grapheme.d b/libphobos/src/std/internal/unicode_grapheme.d index d7b2c29..093ebd1 100644 --- a/libphobos/src/std/internal/unicode_grapheme.d +++ b/libphobos/src/std/internal/unicode_grapheme.d @@ -22,10 +22,16 @@ static if (size_t.sizeof == 4) enum hangulLVTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x80], [ 0x100, 0x80, 0xa00], [ 0x0, 0x20100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x80001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x10000001, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); //832 bytes enum hangulLVTTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x80], [ 0x100, 0x80, 0xa00], [ 0x0, 0x20100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x20001, 0x40003, 0x60005, 0x10007, 0x30002, 0x50004, 0x70006, 0x80001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xeffffffe, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xffffffef, 0xfeffffff, 0xffefffff, 0xfffeffff, 0xffffefff, 0xfffffeff, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); -//1920 bytes -enum mcTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0xc0], [ 0x100, 0x100, 0x2400], [ 0x2020100, 0x2020302, 0x5020204, 0x2060202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x30002, 0x50004, 0x60000, 0x7, 0x0, 0x0, 0x80000, 0x90000, 0xb000a, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf000e, 0x110010, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x130012, 0x150014, 0x170016, 0x190018, 0x1b001a, 0x1c, 0x1e001d, 0x20001f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x210000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x220000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xc8000000, 0xde01, 0x0, 0xc, 0xc0000000, 0x801981, 0x0, 0x8, 0xc0000000, 0x1, 0x0, 0x8, 0xc0000000, 0x1a01, 0x0, 0xc, 0x40000000, 0x801981, 0x0, 0x0, 0xc0000000, 0x801dc6, 0x0, 0xe, 0x0, 0x1e, 0x0, 0xc, 0x40000000, 0x600d9f, 0x80000, 0xc, 0xc0000000, 0x801dc1, 0x0, 0xc, 0x0, 0xff038000, 0xc0000, 0x0, 0xc0000000, 0x0, 0x80000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19021800, 0xc00000, 0x3f9c, 0x1c009f98, 0x0, 0x0, 0x0, 0x200000, 0x100000, 0x0, 0x0, 0x0, 0xc0400000, 0x1bf, 0x0, 0x0, 0x1fb0e78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000000, 0x0, 0xa00000, 0x7e01a, 0x0, 0x0, 0x0, 0x0, 0x10, 0xe8200000, 0x1b, 0x0, 0x4, 0x4c2, 0x0, 0xc5c80, 0x0, 0x300ff0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800002, 0x0, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x98, 0x0, 0x0, 0x3, 0xfff00000, 0xf, 0x0, 0x0, 0x0, 0xc0000, 0x0, 0x8, 0xcc300000, 0x1, 0x0, 0x0, 0x198000, 0x2000, 0x28000000, 0x0, 0x0, 0x0, 0x20c800, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16d8, 0x5, 0x0, 0x0, 0x0, 0x4, 0x1870000, 0x0, 0x0, 0x0, 0x1000, 0x60, 0x0, 0x4, 0x80380000, 0x4001, 0x0, 0x0, 0x2c7000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc, 0xc0000000, 0x80399e, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe00000, 0x23, 0x0, 0x0, 0x7a070000, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f038000, 0x0, 0x0, 0x0, 0x58070000, 0x0, 0x0, 0x0, 0x40d000, 0x0, 0x0, 0x0, 0x43, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1007000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21bf0000, 0x5, 0x0, 0x0, 0x0, 0xf00e0000, 0x10, 0x0, 0x2000000, 0x1800000, 0x0, 0x800000, 0x0, 0x0, 0x0, 0x0, 0x40008000, 0x0, 0x0, 0x0, 0x120200, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x587c00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600000, 0x8, 0xc0300000, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfffe0000, 0xffffffff, 0xff, 0x0, 0x0, 0x30000, 0x0, 0x0, 0x0, 0x7e060, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); -//3456 bytes -enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x110], [ 0x100, 0x1a0, 0x4a00], [ 0x2020100, 0x4020302, 0x7020605, 0xa090802, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x202020b, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x30002, 0x50004, 0x70006, 0x90008, 0xb000a, 0xd000c, 0xe, 0xf0000, 0x0, 0x100000, 0x120011, 0x140013, 0x160015, 0x0, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x190018, 0x0, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1d001c, 0x1f001e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200000, 0x0, 0x220021, 0x230000, 0x250024, 0x0, 0x0, 0x0, 0x26, 0x270000, 0x290028, 0x2b002a, 0x2d002c, 0x2f002e, 0x310030, 0x330032, 0x34, 0x360035, 0x380037, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3b003a, 0x0, 0x3c0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e0000, 0x3f0000, 0x40, 0x0, 0x0, 0x0, 0x41, 0x0, 0x0, 0x3b0042, 0x43, 0x44, 0x0, 0x460045, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x480047, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfffe0000, 0xbfffffff, 0xb6, 0x0, 0x7ff0000, 0x0, 0xfffff800, 0x10000, 0x0, 0x0, 0x9fc00000, 0x3d9f, 0x20000, 0xffff0000, 0x7ff, 0x0, 0x0, 0x1ffc0, 0x0, 0x200ff800, 0xfbc00000, 0x3eef, 0xe000000, 0x0, 0xff000000, 0x0, 0xfffffc00, 0xfffffffb, 0x7, 0x14000000, 0xfe21fe, 0xc, 0x2, 0x50000000, 0x80201e, 0x4000000c, 0x6, 0x10000000, 0x23986, 0x230000, 0x6, 0x10000000, 0x21be, 0xfc00000c, 0x2, 0xd0000000, 0xe0201e, 0xc, 0x4, 0x40000000, 0x802001, 0x0, 0x11, 0xd0000000, 0x603dc1, 0xc, 0x2, 0x90000000, 0x603044, 0xc, 0x3, 0x58000000, 0x80201e, 0xc, 0x2, 0x0, 0x805c8400, 0x0, 0x0, 0x7f20000, 0x7f80, 0x0, 0x0, 0x1ff20000, 0x7f00, 0x0, 0x3000000, 0x2a00000, 0x0, 0x7ffe0000, 0xfeffe0df, 0x1fffffff, 0x40, 0x0, 0x0, 0x66fde000, 0xc3000000, 0x1e0001, 0x20002064, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c0000, 0xc0000, 0xc0000, 0xc0000, 0x0, 0x3fb00000, 0x200ffe40, 0x0, 0xb800, 0x0, 0x0, 0x0, 0x60, 0x200, 0x0, 0x0, 0x0, 0xe040187, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9800000, 0x0, 0x7f400000, 0x9ff81fe5, 0x0, 0xffff0000, 0x7fff, 0x0, 0xf, 0x17f00000, 0x4, 0xff800, 0x3, 0x3b3c, 0x0, 0x3a340, 0x0, 0xcff000, 0x0, 0x0, 0x0, 0x0, 0xfff70000, 0x31021fd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff0000, 0x1ffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38000, 0x0, 0x0, 0x0, 0x80000000, 0x0, 0x0, 0x0, 0xffffffff, 0x0, 0xfc00, 0x0, 0x0, 0x6000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3ff78000, 0xc0000000, 0x0, 0x0, 0x30000, 0x844, 0x1060, 0x0, 0x0, 0x0, 0x0, 0x30, 0x8003ffff, 0x0, 0x3fc0, 0x3ff80, 0x0, 0x7, 0x33c80000, 0x0, 0x20, 0x0, 0x667e00, 0x1008, 0x10000000, 0x0, 0xc19d0000, 0x2, 0x403000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2120, 0x40000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x7c00000, 0x0, 0x0, 0x0, 0x0, 0xf06e, 0x87000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x0, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1800, 0x0, 0xe0000000, 0x0, 0x0, 0x1ffc0, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x2, 0xff000000, 0x7f, 0x80190000, 0x3, 0x6780000, 0x4, 0x0, 0x7, 0x1fef80, 0x0, 0x80000, 0x3, 0x7fc00000, 0x9e00, 0x0, 0x0, 0x40d38000, 0x2, 0x0, 0x0, 0x0, 0x80000000, 0x7f8, 0x3, 0x58000000, 0x800001, 0x1f1fc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff000000, 0x4000005c, 0x0, 0x0, 0xa5f90000, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb03c8000, 0x30000001, 0x0, 0x0, 0xa7f80000, 0x1, 0x0, 0x0, 0xbf2800, 0x0, 0x0, 0xe0000000, 0xfbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6ff8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58010000, 0x8, 0x0, 0x0, 0x0, 0xcf00000, 0x1, 0x7fe, 0x79f80000, 0xe7e0080, 0x0, 0x37ffc00, 0x0, 0x0, 0x0, 0x0, 0xbf7f0000, 0x0, 0x0, 0xfffc0000, 0x6dfcff, 0x0, 0x0, 0x0, 0xb47e0000, 0xbf, 0x0, 0xa30000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180000, 0x3, 0x7c00000, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3fff81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f0000, 0x0, 0x7f0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8000, 0x0, 0x78000, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x60000000, 0x0, 0x0, 0x0, 0xffffffff, 0xffff3fff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf807c3a0, 0xfe7, 0x3c00, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xf87fffff, 0xffffffff, 0x201fff, 0xf8000010, 0xfffe, 0x0, 0x0, 0xf9ffff7f, 0x7db, 0x0, 0x0, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000, 0x0, 0xf000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f0000, 0x0, 0x0, 0x0, 0x7f0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); +//896 bytes +enum prependTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x80], [ 0x100, 0x80, 0xc00], [ 0x1010100, 0x1010101, 0x1010102, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20001, 0x3, 0x0, 0x40000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005, 0x0, 0x0, 0x0, 0x70000, 0x8, 0x90000, 0xa0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000, 0x0, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30000, 0x0, 0x0, 0x4, 0x0, 0x0, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x80000000, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000000, 0x0, 0x0, 0x3f0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); +//1280 bytes +enum controlTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0xd0], [ 0x100, 0x120, 0xe00], [ 0x2020100, 0x3020202, 0x2020402, 0x2060502, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020207, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x10001, 0x10001, 0x10002, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10003, 0x10001, 0x10001, 0x10001, 0x10004, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x60005, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10007, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10008, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x90001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0xb000a, 0xc000c, 0xc000c, 0xc000c, 0xc000c, 0xc000c, 0xc000c, 0xc000c, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0xffffdbff, 0x0, 0x0, 0x80000000, 0xffffffff, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc800, 0x7f00, 0x0, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfff0000, 0x0, 0xffff0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f80000, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff0000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); +//1856 bytes +enum spacingMarkTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0xb0], [ 0x100, 0xe0, 0x2400], [ 0x1010100, 0x1010201, 0x4010103, 0x1050101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x30002, 0x50004, 0x70006, 0x8, 0x0, 0x0, 0x90000, 0xa0000, 0xc000b, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf000e, 0x110010, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x130012, 0x150014, 0x170016, 0x190018, 0x1b001a, 0x1c, 0x1e001d, 0x20001f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x210000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x220000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xc8000000, 0xde01, 0x0, 0xc, 0x80000000, 0x1981, 0x0, 0x8, 0xc0000000, 0x1, 0x0, 0x8, 0xc0000000, 0x1a01, 0x0, 0xc, 0x0, 0x1981, 0x0, 0x0, 0x80000000, 0x1dc6, 0x0, 0xe, 0x0, 0x1e, 0x0, 0xc, 0x40000000, 0xd9b, 0x80000, 0xc, 0x80000000, 0x1dc1, 0x0, 0xc, 0x0, 0x7f030000, 0xc0000, 0x0, 0x80000, 0x0, 0x0, 0x0, 0x80000, 0x0, 0x0, 0x0, 0xc0000000, 0x0, 0x80000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18020000, 0xc00000, 0x0, 0x10, 0x0, 0x0, 0x0, 0x200000, 0x100000, 0x0, 0x0, 0x0, 0xc0400000, 0x1bf, 0x0, 0x0, 0x1fb0e78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000000, 0x0, 0xa00000, 0x7e000, 0x0, 0x0, 0x0, 0x0, 0x10, 0xe8000000, 0x1b, 0x0, 0x4, 0x4c2, 0x0, 0xc5c80, 0x0, 0x300ff0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800002, 0x0, 0x98, 0x0, 0x0, 0x3, 0xfff00000, 0xf, 0x0, 0x0, 0x0, 0xc0000, 0x0, 0x8, 0xcc300000, 0x1, 0x0, 0x0, 0x198000, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x20c800, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16d8, 0x5, 0x0, 0x0, 0x0, 0x4, 0x1870000, 0x0, 0x0, 0x0, 0x1000, 0x60, 0x0, 0x4, 0x80380000, 0x4001, 0x0, 0x0, 0x2c7000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc, 0x80000000, 0x399e, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe00000, 0x23, 0x0, 0x0, 0x5a060000, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f030000, 0x0, 0x0, 0x0, 0x58070000, 0x0, 0x0, 0x0, 0x40d000, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1007000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21be0000, 0x5, 0x0, 0x0, 0x0, 0xf00e0000, 0x10, 0x0, 0x2000000, 0x1800000, 0x0, 0x800000, 0x0, 0x0, 0x0, 0x0, 0x40008000, 0x0, 0x0, 0x0, 0x120200, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x587c00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600000, 0x8, 0xc0300000, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfffe0000, 0xffffffff, 0xff, 0x0, 0x0, 0x30000, 0x0, 0x0, 0x0, 0x2040, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); +//3488 bytes +enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x110], [ 0x100, 0x1a0, 0x4b00], [ 0x2020100, 0x4020302, 0x7020605, 0xa090802, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x202020b, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x30002, 0x50004, 0x70006, 0x90008, 0xb000a, 0xd000c, 0xe, 0xf0000, 0x0, 0x100000, 0x120011, 0x140013, 0x160015, 0x0, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x190018, 0x0, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1d001c, 0x1f001e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200000, 0x0, 0x220021, 0x230000, 0x250024, 0x0, 0x0, 0x0, 0x26, 0x270000, 0x290028, 0x2b002a, 0x2d002c, 0x2f002e, 0x310030, 0x330032, 0x34, 0x360035, 0x380037, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3b003a, 0x0, 0x3c0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e0000, 0x3f0000, 0x40, 0x0, 0x0, 0x0, 0x41, 0x0, 0x0, 0x3b0042, 0x43, 0x44, 0x0, 0x460045, 0x0, 0x0, 0x0, 0x0, 0x470000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x490048, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfffe0000, 0xbfffffff, 0xb6, 0x0, 0x7ff0000, 0x0, 0xfffff800, 0x10000, 0x0, 0x0, 0x9fc00000, 0x3d9f, 0x20000, 0xffff0000, 0x7ff, 0x0, 0x0, 0x1ffc0, 0x0, 0x200ff800, 0xfbc00000, 0x3eef, 0xe000000, 0x0, 0xff000000, 0x0, 0xfffffc00, 0xfffffffb, 0x7, 0x14000000, 0xfe21fe, 0xc, 0x2, 0x50000000, 0x80201e, 0x4000000c, 0x6, 0x10000000, 0x23986, 0x230000, 0x6, 0x10000000, 0x21be, 0xfc00000c, 0x2, 0xd0000000, 0xe0201e, 0xc, 0x4, 0x40000000, 0x802001, 0x0, 0x11, 0xd0000000, 0x603dc1, 0xc, 0x2, 0x90000000, 0x603044, 0xc, 0x3, 0x58000000, 0x80201e, 0xc, 0x2, 0x0, 0x805c8400, 0x0, 0x0, 0x7f20000, 0x7f80, 0x0, 0x0, 0x1ff20000, 0x7f00, 0x0, 0x3000000, 0x2a00000, 0x0, 0x7ffe0000, 0xfeffe0df, 0x1fffffff, 0x40, 0x0, 0x0, 0x66fde000, 0xc3000000, 0x1e0001, 0x20002064, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c0000, 0xc0000, 0xc0000, 0xc0000, 0x0, 0x3fb00000, 0x200ffe40, 0x0, 0xb800, 0x0, 0x0, 0x0, 0x60, 0x200, 0x0, 0x0, 0x0, 0xe040187, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9800000, 0x0, 0x7f400000, 0x9ff81fe5, 0x0, 0xffff0000, 0x7fff, 0x0, 0xf, 0x17f00000, 0x4, 0xff800, 0x3, 0x3b3c, 0x0, 0x3a340, 0x0, 0xcff000, 0x0, 0x0, 0x0, 0x0, 0xfff70000, 0x31021fd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff0000, 0x1ffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38000, 0x0, 0x0, 0x0, 0x80000000, 0x0, 0x0, 0x0, 0xffffffff, 0x0, 0xfc00, 0x0, 0x0, 0x6000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3ff78000, 0xc0000000, 0x0, 0x0, 0x30000, 0x844, 0x1060, 0x0, 0x0, 0x0, 0x0, 0x30, 0x8003ffff, 0x0, 0x3fc0, 0x3ff80, 0x0, 0x7, 0x33c80000, 0x0, 0x20, 0x0, 0x667e00, 0x1008, 0x10000000, 0x0, 0xc19d0000, 0x2, 0x403000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2120, 0x40000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x7c00000, 0x0, 0x0, 0x0, 0x0, 0xf06e, 0x87000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x0, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1800, 0x0, 0xe0000000, 0x0, 0x0, 0x1ffc0, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x2, 0xff000000, 0x7f, 0x80190000, 0x3, 0x6780000, 0x4, 0x0, 0x7, 0x1fef80, 0x0, 0x80000, 0x3, 0x7fc00000, 0x9e00, 0x0, 0x0, 0x40d38000, 0x2, 0x0, 0x0, 0x0, 0x80000000, 0x7f8, 0x3, 0x58000000, 0x800001, 0x1f1fc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff000000, 0x4000005c, 0x0, 0x0, 0xa5f90000, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb03c8000, 0x30000001, 0x0, 0x0, 0xa7f80000, 0x1, 0x0, 0x0, 0xbf2800, 0x0, 0x0, 0xe0000000, 0xfbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6ff8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58010000, 0x8, 0x0, 0x0, 0x0, 0xcf00000, 0x1, 0x7fe, 0x79f80000, 0xe7e0080, 0x0, 0x37ffc00, 0x0, 0x0, 0x0, 0x0, 0xbf7f0000, 0x0, 0x0, 0xfffc0000, 0x6dfcff, 0x0, 0x0, 0x0, 0xb47e0000, 0xbf, 0x0, 0xa30000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180000, 0x3, 0x7c00000, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3fff81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f0000, 0x0, 0x7f0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8000, 0x0, 0x78000, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x60000000, 0x0, 0x0, 0x0, 0xffffffff, 0xffff3fff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf807c3a0, 0xfe7, 0x3c00, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xf87fffff, 0xffffffff, 0x201fff, 0xf8000010, 0xfffe, 0x0, 0x0, 0xf9ffff7f, 0x7db, 0x0, 0x0, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000, 0x0, 0xf000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f0000, 0x0, 0x0, 0x0, 0x7f0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8000000, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); +//1344 bytes +enum Extended_PictographicTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x40, 0x90], [ 0x100, 0xa0, 0x1800], [ 0x2020100, 0x2020202, 0x2020202, 0x3020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x2020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x30002, 0x40001, 0x60005, 0x80007, 0x90001, 0xa0001, 0x10001, 0x10001, 0x1000b, 0x1000c, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0xe000d, 0x10000f, 0x11000d, 0x130012, 0x150014, 0x1000d, 0xd000d, 0x16000d, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x10001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4200, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000000, 0x200, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000004, 0x0, 0x0, 0x3f00000, 0x600, 0x0, 0x0, 0xc000000, 0x100, 0x0, 0x0, 0x100, 0x0, 0x8000, 0x70ffe00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400c00, 0x1, 0x78000000, 0xfff7ffbf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff003f, 0xffffffff, 0xffffffff, 0xffffffff, 0x2057ff3f, 0x180102, 0xb85090, 0xf8, 0xe00000, 0x80010002, 0x0, 0x0, 0x0, 0x300000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180000e0, 0x0, 0x210000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20010000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2800000, 0x0, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xe000, 0x8000, 0x0, 0xc003f000, 0x7fe4000, 0xffffe000, 0xffffffff, 0x3f, 0x400fffe, 0xf7fc8000, 0xfffffe00, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x7ffffff, 0xffffffff, 0x3fffffff, 0xffffffc0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x0, 0x0, 0xfff00000, 0x0, 0x0, 0xffe00000, 0xffffffff, 0xf000, 0x0, 0xfc00ff00, 0x0, 0xff00, 0xffffc000, 0xffffffff, 0xffffffff, 0xfffff000, 0xf7ffffff, 0xffffffbf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x3fffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); } @@ -36,10 +42,16 @@ static if (size_t.sizeof == 8) enum hangulLVTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x40], [ 0x100, 0x80, 0xa00], [ 0x2010000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000300020001, 0x1000700060005, 0x5000400030002, 0x2000100070006, 0x6000500040003, 0x3000200010007, 0x7000600050004, 0x4000300020001, 0x1000700060005, 0x5000400030002, 0x8000100070006, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x100000010000001, 0x1000000100000, 0x10000001000, 0x1000000100000010, 0x10000001000000, 0x100000010000, 0x1000000100, 0x100000010000001, 0x1000000100000, 0x10000001000, 0x1000000100000010, 0x10000001000000, 0x100000010000, 0x1000000100, 0x100000010000001, 0x1000000100000, 0x10000001000, 0x1000000100000010, 0x10000001000000, 0x100000010000, 0x1000000100, 0x100000010000001, 0x1000000100000, 0x10000001000, 0x1000000100000010, 0x10000001000000, 0x100000010000, 0x1000000100, 0x10000001000000, 0x100000010000, 0x100, 0x0, 0x0, 0x0, 0x0, 0x0]); //832 bytes enum hangulLVTTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x40], [ 0x100, 0x80, 0xa00], [ 0x2010000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000300020001, 0x1000700060005, 0x5000400030002, 0x2000100070006, 0x6000500040003, 0x3000200010007, 0x7000600050004, 0x4000300020001, 0x1000700060005, 0x5000400030002, 0x8000100070006, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfeffffffeffffffe, 0xfffeffffffefffff, 0xfffffeffffffefff, 0xeffffffeffffffef, 0xffeffffffeffffff, 0xffffeffffffeffff, 0xffffffeffffffeff, 0xfeffffffeffffffe, 0xfffeffffffefffff, 0xfffffeffffffefff, 0xeffffffeffffffef, 0xffeffffffeffffff, 0xffffeffffffeffff, 0xffffffeffffffeff, 0xfeffffffeffffffe, 0xfffeffffffefffff, 0xfffffeffffffefff, 0xeffffffeffffffef, 0xffeffffffeffffff, 0xffffeffffffeffff, 0xffffffeffffffeff, 0xfeffffffeffffffe, 0xfffeffffffefffff, 0xfffffeffffffefff, 0xeffffffeffffffef, 0xffeffffffeffffff, 0xffffeffffffeffff, 0xffffffeffffffeff, 0xffeffffffeffffff, 0xffffeffffffeffff, 0xffffffeff, 0x0, 0x0, 0x0, 0x0, 0x0]); -//1920 bytes -enum mcTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x60], [ 0x100, 0x100, 0x2400], [ 0x202030202020100, 0x206020205020204, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000200010000, 0x6000000050004, 0x7, 0x8000000000000, 0xb000a00090000, 0xc, 0x0, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x110010000f000e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15001400130012, 0x19001800170016, 0x1c001b001a, 0x20001f001e001d, 0x0, 0x0, 0x0, 0x21000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x220000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc800000000000008, 0xde01, 0xc00000000000000c, 0x801981, 0xc000000000000008, 0x1, 0xc000000000000008, 0x1a01, 0x400000000000000c, 0x801981, 0xc000000000000000, 0x801dc6, 0xe, 0x1e, 0x400000000000000c, 0x8000000600d9f, 0xc00000000000000c, 0x801dc1, 0xc, 0xc0000ff038000, 0xc000000000000000, 0x8000000000000000, 0x0, 0x0, 0x1902180000000000, 0x3f9c00c00000, 0x1c009f98, 0x0, 0x10000000200000, 0x0, 0xc040000000000000, 0x1bf, 0x1fb0e7800000000, 0x0, 0x0, 0x0, 0x6000000, 0x7e01a00a00000, 0x0, 0x0, 0xe820000000000010, 0x1b, 0x4c200000004, 0xc5c8000000000, 0x300ff000000000, 0x0, 0x0, 0x80000200000000, 0xc00000000000, 0x0, 0x0, 0x0, 0x9800000000, 0x0, 0xfff0000000000003, 0xf, 0x0, 0xc0000, 0xcc30000000000008, 0x1, 0x19800000000000, 0x2800000000002000, 0x0, 0x20c80000000000, 0x0, 0x0, 0x0, 0x16d800000000, 0x5, 0x0, 0x187000000000004, 0x0, 0x100000000000, 0x60, 0x8038000000000004, 0x4001, 0x2c700000000000, 0x0, 0x0, 0x700000000, 0xc00000000000000c, 0xc0080399e, 0x0, 0x0, 0xe0000000000000, 0x23, 0x7a07000000000000, 0x2, 0x0, 0x0, 0x4f03800000000000, 0x0, 0x5807000000000000, 0x0, 0x40d00000000000, 0x0, 0x4300000000, 0x0, 0x0, 0x0, 0x100700000000000, 0x0, 0x0, 0x0, 0x21bf000000000000, 0x5, 0x0, 0x10f00e0000, 0x200000000000000, 0x1800000, 0x800000, 0x0, 0x4000800000000000, 0x0, 0x12020000000000, 0x0, 0x0, 0x0, 0x587c00, 0x0, 0x0, 0x0, 0x0, 0x60000000000000, 0xc030000000000008, 0x2, 0x0, 0x0, 0x0, 0xfffffffffffe0000, 0xff, 0x3000000000000, 0x0, 0x7e06000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); -//3456 bytes -enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x88], [ 0x100, 0x1a0, 0x4a00], [ 0x402030202020100, 0xa09080207020605, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x20202020202020b, 0x202020202020202, 0x202020202020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000000000000, 0x5000400030002, 0x9000800070006, 0xd000c000b000a, 0xf00000000000e, 0x10000000000000, 0x14001300120011, 0x160015, 0x17, 0x0, 0x0, 0x190018, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b00000000, 0x1f001e001d001c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000000000, 0x22002100000000, 0x25002400230000, 0x0, 0x2600000000, 0x29002800270000, 0x2d002c002b002a, 0x310030002f002e, 0x3400330032, 0x38003700360035, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x3b003a00000000, 0x3c000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x3e000000000000, 0x40003f0000, 0x0, 0x4100000000, 0x0, 0x43003b0042, 0x44, 0x460045, 0x0, 0x0, 0x0, 0x0, 0x0, 0x480047, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x3f8, 0x0, 0x0, 0x0, 0xbffffffffffe0000, 0xb6, 0x7ff0000, 0x10000fffff800, 0x0, 0x3d9f9fc00000, 0xffff000000020000, 0x7ff, 0x1ffc000000000, 0x200ff80000000000, 0x3eeffbc00000, 0xe000000, 0xff000000, 0xfffffffbfffffc00, 0x1400000000000007, 0xc00fe21fe, 0x5000000000000002, 0x4000000c0080201e, 0x1000000000000006, 0x23000000023986, 0x1000000000000006, 0xfc00000c000021be, 0xd000000000000002, 0xc00e0201e, 0x4000000000000004, 0x802001, 0xd000000000000011, 0xc00603dc1, 0x9000000000000002, 0xc00603044, 0x5800000000000003, 0xc0080201e, 0x2, 0x805c8400, 0x7f2000000000000, 0x7f80, 0x1ff2000000000000, 0x7f00, 0x2a0000003000000, 0x7ffe000000000000, 0x1ffffffffeffe0df, 0x40, 0x66fde00000000000, 0x1e0001c3000000, 0x20002064, 0x0, 0x0, 0xe0000000, 0x0, 0x0, 0xc0000001c0000, 0xc0000000c0000, 0x3fb0000000000000, 0x200ffe40, 0xb800, 0x0, 0x20000000060, 0x0, 0xe04018700000000, 0x0, 0x0, 0x0, 0x9800000, 0x9ff81fe57f400000, 0xffff000000000000, 0x7fff, 0x17f000000000000f, 0xff80000000004, 0x3b3c00000003, 0x3a34000000000, 0xcff00000000000, 0x0, 0x0, 0x31021fdfff70000, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x1000, 0x0, 0x0, 0x1ffffffff0000, 0x0, 0x0, 0x0, 0x3800000000000, 0x0, 0x8000000000000000, 0x0, 0xffffffff00000000, 0xfc0000000000, 0x0, 0x6000000, 0x0, 0x0, 0x3ff7800000000000, 0xc0000000, 0x3000000000000, 0x106000000844, 0x0, 0x0, 0x8003ffff00000030, 0x3fc000000000, 0x3ff80, 0x33c8000000000007, 0x2000000000, 0x667e0000000000, 0x1000000000001008, 0xc19d000000000000, 0x40300000000002, 0x0, 0x0, 0x0, 0x212000000000, 0x40000000, 0x0, 0x0, 0x0, 0xffff0000ffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0000000, 0x0, 0x0, 0x0, 0x0, 0x2000000000000000, 0x0, 0x0, 0x0, 0x100000000, 0x0, 0x7c0000000000000, 0x0, 0x0, 0x870000000000f06e, 0x0, 0x0, 0x6000000000, 0xf000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180000000000, 0xe000000000000000, 0x0, 0x1ffc0, 0x3c, 0x0, 0xff00000000000002, 0x801900000000007f, 0x678000000000003, 0x4, 0x1fef8000000007, 0x8000000000000, 0x7fc0000000000003, 0x9e00, 0x40d3800000000000, 0x2, 0x0, 0x7f880000000, 0x5800000000000003, 0x1f1fc000800001, 0x0, 0x0, 0xff00000000000000, 0x4000005c, 0xa5f9000000000000, 0xd, 0x0, 0x0, 0xb03c800000000000, 0x30000001, 0xa7f8000000000000, 0x1, 0xbf280000000000, 0x0, 0xfbce0000000, 0x0, 0x0, 0x0, 0x6ff800000000000, 0x0, 0x0, 0x0, 0x5801000000000000, 0x8, 0x0, 0x10cf00000, 0x79f80000000007fe, 0xe7e0080, 0x37ffc00, 0x0, 0xbf7f000000000000, 0x0, 0x6dfcfffffc0000, 0x0, 0xb47e000000000000, 0xbf, 0xa30000, 0x0, 0x0, 0x0, 0x0, 0x18000000000000, 0x7c0000000000003, 0x5, 0x0, 0x0, 0x0, 0x3fff81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f000000000000, 0x7f000000000000, 0x0, 0x0, 0x0, 0x0, 0x8000, 0x78000, 0x1000000000, 0x0, 0x0, 0x60000000, 0x0, 0xffff3fffffffffff, 0x7f, 0x0, 0x0, 0x0, 0xf807c3a000000000, 0x3c0000000fe7, 0x0, 0x0, 0x1c, 0x0, 0x0, 0xf87fffffffffffff, 0x201fffffffffff, 0xfffef8000010, 0x0, 0x7dbf9ffff7f, 0x0, 0x8000, 0x0, 0x0, 0x0, 0x400000000000, 0xf00000000000, 0x0, 0x0, 0x0, 0xf00000000000, 0x0, 0x0, 0x0, 0x7f0000, 0x0, 0x7f0, 0x0, 0x0, 0xffffffff00000000, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffff, 0x0, 0x0, 0x0, 0x0]); +//896 bytes +enum prependTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x40], [ 0x100, 0x80, 0xc00], [ 0x101010101010100, 0x101010101010102, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000100000000, 0x3, 0x40000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005, 0x0, 0x800070000, 0xa000000090000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x20000000, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30000, 0x400000000, 0x0, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x2000000000000000, 0x2000, 0x0, 0x0, 0x0, 0xc, 0x8000000000000000, 0x2, 0x0, 0x0, 0x400000000000000, 0x0, 0x3f0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); +//1280 bytes +enum controlTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x68], [ 0x100, 0x120, 0xe00], [ 0x302020202020100, 0x206050202020402, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020207, 0x202020202020202, 0x202020202020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000100010000, 0x1000200010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010003, 0x1000100010001, 0x1000100010004, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x6000500010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010007, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010008, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100090001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0xc000c000b000a, 0xc000c000c000c, 0xc000c000c000c, 0xc000c000c000c, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0xffffdbff, 0x8000000000000000, 0x2000ffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10000000, 0x0, 0x0, 0x0, 0x4000, 0x0, 0x0, 0x0, 0x7f000000c800, 0xffff00000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000, 0x0, 0x0, 0x0, 0xfff000000000000, 0xffff000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf00000000, 0x0, 0x0, 0x7f8000000000000, 0x0, 0x0, 0xffffffff, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0xffff000000000000, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0]); +//1856 bytes +enum spacingMarkTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x58], [ 0x100, 0xe0, 0x2400], [ 0x101020101010100, 0x105010104010103, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x101010101010101, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000200010000, 0x7000600050004, 0x8, 0x9000000000000, 0xc000b000a0000, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x110010000f000e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15001400130012, 0x19001800170016, 0x1c001b001a, 0x20001f001e001d, 0x0, 0x0, 0x0, 0x21000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x220000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc800000000000008, 0xde01, 0x800000000000000c, 0x1981, 0xc000000000000008, 0x1, 0xc000000000000008, 0x1a01, 0xc, 0x1981, 0x8000000000000000, 0x1dc6, 0xe, 0x1e, 0x400000000000000c, 0x8000000000d9b, 0x800000000000000c, 0x1dc1, 0xc, 0xc00007f030000, 0x8000000000000, 0x0, 0x8000000000000, 0x0, 0xc000000000000000, 0x8000000000000000, 0x0, 0x0, 0x1802000000000000, 0xc00000, 0x10, 0x0, 0x10000000200000, 0x0, 0xc040000000000000, 0x1bf, 0x1fb0e7800000000, 0x0, 0x0, 0x0, 0x6000000, 0x7e00000a00000, 0x0, 0x0, 0xe800000000000010, 0x1b, 0x4c200000004, 0xc5c8000000000, 0x300ff000000000, 0x0, 0x0, 0x80000200000000, 0x9800000000, 0x0, 0xfff0000000000003, 0xf, 0x0, 0xc0000, 0xcc30000000000008, 0x1, 0x19800000000000, 0x2000, 0x0, 0x20c80000000000, 0x0, 0x0, 0x0, 0x16d800000000, 0x5, 0x0, 0x187000000000004, 0x0, 0x100000000000, 0x60, 0x8038000000000004, 0x4001, 0x2c700000000000, 0x0, 0x0, 0x700000000, 0x800000000000000c, 0xc0000399e, 0x0, 0x0, 0xe0000000000000, 0x23, 0x5a06000000000000, 0x2, 0x0, 0x0, 0x4f03000000000000, 0x0, 0x5807000000000000, 0x0, 0x40d00000000000, 0x0, 0x4000000000, 0x0, 0x0, 0x0, 0x100700000000000, 0x0, 0x0, 0x0, 0x21be000000000000, 0x5, 0x0, 0x10f00e0000, 0x200000000000000, 0x1800000, 0x800000, 0x0, 0x4000800000000000, 0x0, 0x12020000000000, 0x0, 0x0, 0x0, 0x587c00, 0x0, 0x0, 0x0, 0x0, 0x60000000000000, 0xc030000000000008, 0x2, 0x0, 0x0, 0x0, 0xfffffffffffe0000, 0xff, 0x3000000000000, 0x0, 0x204000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); +//3488 bytes +enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x88], [ 0x100, 0x1a0, 0x4b00], [ 0x402030202020100, 0xa09080207020605, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x20202020202020b, 0x202020202020202, 0x202020202020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000000000000, 0x5000400030002, 0x9000800070006, 0xd000c000b000a, 0xf00000000000e, 0x10000000000000, 0x14001300120011, 0x160015, 0x17, 0x0, 0x0, 0x190018, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b00000000, 0x1f001e001d001c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20000000000000, 0x22002100000000, 0x25002400230000, 0x0, 0x2600000000, 0x29002800270000, 0x2d002c002b002a, 0x310030002f002e, 0x3400330032, 0x38003700360035, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x3b003a00000000, 0x3c000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x3e000000000000, 0x40003f0000, 0x0, 0x4100000000, 0x0, 0x43003b0042, 0x44, 0x460045, 0x0, 0x47000000000000, 0x0, 0x0, 0x0, 0x490048, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x3f8, 0x0, 0x0, 0x0, 0xbffffffffffe0000, 0xb6, 0x7ff0000, 0x10000fffff800, 0x0, 0x3d9f9fc00000, 0xffff000000020000, 0x7ff, 0x1ffc000000000, 0x200ff80000000000, 0x3eeffbc00000, 0xe000000, 0xff000000, 0xfffffffbfffffc00, 0x1400000000000007, 0xc00fe21fe, 0x5000000000000002, 0x4000000c0080201e, 0x1000000000000006, 0x23000000023986, 0x1000000000000006, 0xfc00000c000021be, 0xd000000000000002, 0xc00e0201e, 0x4000000000000004, 0x802001, 0xd000000000000011, 0xc00603dc1, 0x9000000000000002, 0xc00603044, 0x5800000000000003, 0xc0080201e, 0x2, 0x805c8400, 0x7f2000000000000, 0x7f80, 0x1ff2000000000000, 0x7f00, 0x2a0000003000000, 0x7ffe000000000000, 0x1ffffffffeffe0df, 0x40, 0x66fde00000000000, 0x1e0001c3000000, 0x20002064, 0x0, 0x0, 0xe0000000, 0x0, 0x0, 0xc0000001c0000, 0xc0000000c0000, 0x3fb0000000000000, 0x200ffe40, 0xb800, 0x0, 0x20000000060, 0x0, 0xe04018700000000, 0x0, 0x0, 0x0, 0x9800000, 0x9ff81fe57f400000, 0xffff000000000000, 0x7fff, 0x17f000000000000f, 0xff80000000004, 0x3b3c00000003, 0x3a34000000000, 0xcff00000000000, 0x0, 0x0, 0x31021fdfff70000, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x1000, 0x0, 0x0, 0x1ffffffff0000, 0x0, 0x0, 0x0, 0x3800000000000, 0x0, 0x8000000000000000, 0x0, 0xffffffff00000000, 0xfc0000000000, 0x0, 0x6000000, 0x0, 0x0, 0x3ff7800000000000, 0xc0000000, 0x3000000000000, 0x106000000844, 0x0, 0x0, 0x8003ffff00000030, 0x3fc000000000, 0x3ff80, 0x33c8000000000007, 0x2000000000, 0x667e0000000000, 0x1000000000001008, 0xc19d000000000000, 0x40300000000002, 0x0, 0x0, 0x0, 0x212000000000, 0x40000000, 0x0, 0x0, 0x0, 0xffff0000ffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0000000, 0x0, 0x0, 0x0, 0x0, 0x2000000000000000, 0x0, 0x0, 0x0, 0x100000000, 0x0, 0x7c0000000000000, 0x0, 0x0, 0x870000000000f06e, 0x0, 0x0, 0x6000000000, 0xf000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180000000000, 0xe000000000000000, 0x0, 0x1ffc0, 0x3c, 0x0, 0xff00000000000002, 0x801900000000007f, 0x678000000000003, 0x4, 0x1fef8000000007, 0x8000000000000, 0x7fc0000000000003, 0x9e00, 0x40d3800000000000, 0x2, 0x0, 0x7f880000000, 0x5800000000000003, 0x1f1fc000800001, 0x0, 0x0, 0xff00000000000000, 0x4000005c, 0xa5f9000000000000, 0xd, 0x0, 0x0, 0xb03c800000000000, 0x30000001, 0xa7f8000000000000, 0x1, 0xbf280000000000, 0x0, 0xfbce0000000, 0x0, 0x0, 0x0, 0x6ff800000000000, 0x0, 0x0, 0x0, 0x5801000000000000, 0x8, 0x0, 0x10cf00000, 0x79f80000000007fe, 0xe7e0080, 0x37ffc00, 0x0, 0xbf7f000000000000, 0x0, 0x6dfcfffffc0000, 0x0, 0xb47e000000000000, 0xbf, 0xa30000, 0x0, 0x0, 0x0, 0x0, 0x18000000000000, 0x7c0000000000003, 0x5, 0x0, 0x0, 0x0, 0x3fff81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f000000000000, 0x7f000000000000, 0x0, 0x0, 0x0, 0x0, 0x8000, 0x78000, 0x1000000000, 0x0, 0x0, 0x60000000, 0x0, 0xffff3fffffffffff, 0x7f, 0x0, 0x0, 0x0, 0xf807c3a000000000, 0x3c0000000fe7, 0x0, 0x0, 0x1c, 0x0, 0x0, 0xf87fffffffffffff, 0x201fffffffffff, 0xfffef8000010, 0x0, 0x7dbf9ffff7f, 0x0, 0x8000, 0x0, 0x0, 0x0, 0x400000000000, 0xf00000000000, 0x0, 0x0, 0x0, 0xf00000000000, 0x0, 0x0, 0x0, 0x7f0000, 0x0, 0x7f0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf800000000000000, 0xffffffff00000000, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffff, 0x0, 0x0, 0x0, 0x0]); +//1344 bytes +enum Extended_PictographicTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0, 0x20, 0x48], [ 0x100, 0xa0, 0x1800], [ 0x202020202020100, 0x302020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x202020202020202, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000100010000, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x4000100030002, 0x8000700060005, 0xa000100090001, 0x1000100010001, 0x1000c0001000b, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x10000f000e000d, 0x1300120011000d, 0x1000d00150014, 0x16000d000d000d, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x1000100010001, 0x0, 0x0, 0x420000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000000000000000, 0x200, 0x0, 0x0, 0x200000400000000, 0x0, 0x60003f00000, 0x0, 0x1000c000000, 0x0, 0x100, 0x70ffe0000008000, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x400c0000000000, 0x7800000000000001, 0xfffffffffff7ffbf, 0xffffffffffffffff, 0xffffffffffff003f, 0xffffffffffffffff, 0x1801022057ff3f, 0xf800b85090, 0x8001000200e00000, 0x0, 0x30000000000000, 0x0, 0x0, 0x0, 0x180000e0, 0x210000, 0x0, 0x0, 0x2001000000000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2800000, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x80000000e000, 0xc003f00000000000, 0xffffe00007fe4000, 0x3fffffffff, 0xf7fc80000400fffe, 0xfffffffffffffe00, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x7ffffffffffffff, 0x3fffffffffffffff, 0xffffffffffffffc0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0xfff0000000000000, 0x0, 0xffffffffffe00000, 0xf000, 0xfc00ff00, 0xffffc0000000ff00, 0xffffffffffffffff, 0xf7fffffffffff000, 0xffffffffffffffbf, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x3fffffffffffffff, 0x0, 0x0, 0x0, 0x0]); } diff --git a/libphobos/src/std/math/exponential.d b/libphobos/src/std/math/exponential.d index 66f4b8a..fd1ff24 100644 --- a/libphobos/src/std/math/exponential.d +++ b/libphobos/src/std/math/exponential.d @@ -39,7 +39,8 @@ static import core.stdc.math; version (DigitalMars) { - version = INLINE_YL2X; // x87 has opcodes for these + version (OSX) { } // macOS 13 (M1) has issues emulating instruction + else version = INLINE_YL2X; // x87 has opcodes for these } version (D_InlineAsm_X86) version = InlineAsm_X86_Any; @@ -2862,7 +2863,7 @@ float ldexp(float n, int exp) @safe pure nothrow @nogc { return core.math.ldex private { - // Coefficients shared across log(), log2(), log10(). + // Coefficients shared across log(), log2(), log10(), log1p(). template LogCoeffs(T) { import std.math : floatTraits, RealFormat; @@ -3022,6 +3023,25 @@ private alias log2Q = logQ; // Coefficients for log(1 + x) = x - x^^2/2 + x^^3 P(x)/Q(x) + static immutable double[7] logp1P = [ + 2.0039553499201281259648E1, + 5.7112963590585538103336E1, + 6.0949667980987787057556E1, + 2.9911919328553073277375E1, + 6.5787325942061044846969E0, + 4.9854102823193375972212E-1, + 4.5270000862445199635215E-5, + ]; + static immutable double[7] logp1Q = [ + 1.0000000000000000000000E0, + 6.0118660497603843919306E1, + 2.1642788614495947685003E2, + 3.0909872225312059774938E2, + 2.2176239823732856465394E2, + 8.3047565967967209469434E1, + 1.5062909083469192043167E1, + ]; + static immutable double[7] log10P = [ 1.98892446572874072159E1, 5.67349287391754285487E1, @@ -3070,6 +3090,26 @@ private 7.0376836292E-2, ]; + // Coefficients for log(1 + x) = x - x^^2/2 + x^^3 P(x)/Q(x) + static immutable float[7] logp1P = [ + 2.0039553499E1, + 5.7112963590E1, + 6.0949667980E1, + 2.9911919328E1, + 6.5787325942E0, + 4.9854102823E-1, + 4.5270000862E-5, + ]; + static immutable float[7] logp1Q = [ + 1.00000000000E0, + 6.01186604976E1, + 2.16427886144E2, + 3.09098722253E2, + 2.21762398237E2, + 8.30475659679E1, + 1.50629090834E1, + ]; + // log2 and log10 uses the same coefficients as log. alias log2P = logP; alias log10P = logP; @@ -3135,7 +3175,7 @@ real log(ulong x) @safe pure nothrow @nogc { return log(cast(real) x); } assert(feqrel(log(E), 1) >= real.mant_dig - 1); } -private T logImpl(T)(T x) @safe pure nothrow @nogc +private T logImpl(T, bool LOG1P = false)(T x) @safe pure nothrow @nogc { import std.math.constants : SQRT1_2; import std.math.algebraic : poly; @@ -3145,6 +3185,12 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc alias coeffs = LogCoeffs!T; alias F = floatTraits!T; + static if (LOG1P) + { + const T xm1 = x; + x = x + 1.0; + } + static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeExtended53 || F.realFormat == RealFormat.ieeeQuadruple) @@ -3219,11 +3265,28 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc if (x < SQRT1_2) { exp -= 1; - x = 2.0 * x - 1.0; + static if (LOG1P) + { + if (exp != 0) + x = 2.0 * x - 1.0; + else + x = xm1; + } + else + x = 2.0 * x - 1.0; + } else { - x = x - 1.0; + static if (LOG1P) + { + if (exp != 0) + x = x - 1.0; + else + x = xm1; + } + else + x = x - 1.0; } z = x * x; static if (F.realFormat == RealFormat.ieeeSingle) @@ -3241,6 +3304,84 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc return z; } +@safe @nogc nothrow unittest +{ + import std.math : floatTraits, RealFormat; + import std.meta : AliasSeq; + + static void testLog(T)(T[2][] vals) + { + import std.math.operations : isClose; + import std.math.traits : isNaN; + foreach (ref pair; vals) + { + if (isNaN(pair[1])) + assert(isNaN(log(pair[0]))); + else + assert(isClose(log(pair[0]), pair[1])); + } + } + static foreach (F; AliasSeq!(float, double, real)) + {{ + F[2][24] vals = [ + [F(1), F(0x0p+0)], [F(2), F(0x1.62e42fefa39ef358p-1)], + [F(4), F(0x1.62e42fefa39ef358p+0)], [F(8), F(0x1.0a2b23f3bab73682p+1)], + [F(16), F(0x1.62e42fefa39ef358p+1)], [F(32), F(0x1.bb9d3beb8c86b02ep+1)], + [F(64), F(0x1.0a2b23f3bab73682p+2)], [F(128), F(0x1.3687a9f1af2b14ecp+2)], + [F(256), F(0x1.62e42fefa39ef358p+2)], [F(512), F(0x1.8f40b5ed9812d1c2p+2)], + [F(1024), F(0x1.bb9d3beb8c86b02ep+2)], [F(2048), F(0x1.e7f9c1e980fa8e98p+2)], + [F(3), F(0x1.193ea7aad030a976p+0)], [F(5), F(0x1.9c041f7ed8d336bp+0)], + [F(7), F(0x1.f2272ae325a57546p+0)], [F(15), F(0x1.5aa16394d481f014p+1)], + [F(17), F(0x1.6aa6bc1fa7f79cfp+1)], [F(31), F(0x1.b78ce48912b59f12p+1)], + [F(33), F(0x1.bf8d8f4d5b8d1038p+1)], [F(63), F(0x1.09291e8e3181b20ep+2)], + [F(65), F(0x1.0b292939429755ap+2)], [F(-0), -F.infinity], [F(0), -F.infinity], + [F(10000), F(0x1.26bb1bbb5551582ep+3)], + ]; + testLog(vals); + }} + { + float[2][16] vals = [ + [float.nan, float.nan],[-float.nan, float.nan], + [float.infinity, float.infinity], [-float.infinity, float.nan], + [float.min_normal, -0x1.5d58ap+6f], [-float.min_normal, float.nan], + [float.max, 0x1.62e43p+6f], [-float.max, float.nan], + [float.min_normal / 2, -0x1.601e68p+6f], [-float.min_normal / 2, float.nan], + [float.max / 2, 0x1.601e68p+6f], [-float.max / 2, float.nan], + [float.min_normal / 3, -0x1.61bd9ap+6f], [-float.min_normal / 3, float.nan], + [float.max / 3, 0x1.5e7f36p+6f], [-float.max / 3, float.nan], + ]; + testLog(vals); + } + { + double[2][16] vals = [ + [double.nan, double.nan],[-double.nan, double.nan], + [double.infinity, double.infinity], [-double.infinity, double.nan], + [double.min_normal, -0x1.6232bdd7abcd2p+9], [-double.min_normal, double.nan], + [double.max, 0x1.62e42fefa39efp+9], [-double.max, double.nan], + [double.min_normal / 2, -0x1.628b76e3a7b61p+9], [-double.min_normal / 2, double.nan], + [double.max / 2, 0x1.628b76e3a7b61p+9], [-double.max / 2, double.nan], + [double.min_normal / 3, -0x1.62bf5d2b81354p+9], [-double.min_normal / 3, double.nan], + [double.max / 3, 0x1.6257909bce36ep+9], [-double.max / 3, double.nan], + ]; + testLog(vals); + } + alias F = floatTraits!real; + static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple) + {{ + real[2][16] vals = [ + [real.nan, real.nan],[-real.nan, real.nan], + [real.infinity, real.infinity], [-real.infinity, real.nan], + [real.min_normal, -0x1.62d918ce2421d66p+13L], [-real.min_normal, real.nan], + [real.max, 0x1.62e42fefa39ef358p+13L], [-real.max, real.nan], + [real.min_normal / 2, -0x1.62dea45ee3e064dcp+13L], [-real.min_normal / 2, real.nan], + [real.max / 2, 0x1.62dea45ee3e064dcp+13L], [-real.max / 2, real.nan], + [real.min_normal / 3, -0x1.62e1e2c3617857e6p+13L], [-real.min_normal / 3, real.nan], + [real.max / 3, 0x1.62db65fa664871d2p+13L], [-real.max / 3, real.nan], + ]; + testLog(vals); + }} +} + /************************************** * Calculate the base-10 logarithm of x. * @@ -3296,6 +3437,14 @@ real log10(ulong x) @safe pure nothrow @nogc { return log10(cast(real) x); } assert(fabs(log10(1000.0L) - 3) < .000001); } +@safe pure nothrow @nogc unittest +{ + import std.math.algebraic : fabs; + + assert(fabs(log10(1000.0) - 3) < .000001); + assert(fabs(log10(1000.0f) - 3) < .000001); +} + private T log10Impl(T)(T x) @safe pure nothrow @nogc { import std.math.constants : SQRT1_2; @@ -3404,6 +3553,84 @@ Ldone: return z; } +@safe @nogc nothrow unittest +{ + import std.math : floatTraits, RealFormat; + import std.meta : AliasSeq; + + static void testLog10(T)(T[2][] vals) + { + import std.math.operations : isClose; + import std.math.traits : isNaN; + foreach (ref pair; vals) + { + if (isNaN(pair[1])) + assert(isNaN(log10(pair[0]))); + else + assert(isClose(log10(pair[0]), pair[1])); + } + } + static foreach (F; AliasSeq!(float, double, real)) + {{ + F[2][24] vals = [ + [F(1), F(0x0p+0)], [F(2), F(0x1.34413509f79fef32p-2)], + [F(4), F(0x1.34413509f79fef32p-1)], [F(8), F(0x1.ce61cf8ef36fe6cap-1)], + [F(16), F(0x1.34413509f79fef32p+0)], [F(32), F(0x1.8151824c7587eafep+0)], + [F(64), F(0x1.ce61cf8ef36fe6cap+0)], [F(128), F(0x1.0db90e68b8abf14cp+1)], + [F(256), F(0x1.34413509f79fef32p+1)], [F(512), F(0x1.5ac95bab3693ed18p+1)], + [F(1024), F(0x1.8151824c7587eafep+1)], [F(2048), F(0x1.a7d9a8edb47be8e4p+1)], + [F(3), F(0x1.e8927964fd5fd08cp-2)], [F(5), F(0x1.65df657b04300868p-1)], + [F(7), F(0x1.b0b0b0b78cc3f296p-1)], [F(15), F(0x1.2d145116c16ff856p+0)], + [F(17), F(0x1.3afeb354b7d9731ap+0)], [F(31), F(0x1.7dc9e145867e62eap+0)], + [F(33), F(0x1.84bd545e4baeddp+0)], [F(63), F(0x1.cca1950e4511e192p+0)], + [F(65), F(0x1.d01b16f9433cf7b8p+0)], [F(-0), -F.infinity], [F(0), -F.infinity], + [F(10000), F(0x1p+2)], + ]; + testLog10(vals); + }} + { + float[2][16] vals = [ + [float.nan, float.nan],[-float.nan, float.nan], + [float.infinity, float.infinity], [-float.infinity, float.nan], + [float.min_normal, -0x1.2f703p+5f], [-float.min_normal, float.nan], + [float.max, 0x1.344136p+5f], [-float.max, float.nan], + [float.min_normal / 2, -0x1.31d8b2p+5f], [-float.min_normal / 2, float.nan], + [float.max / 2, 0x1.31d8b2p+5f], [-float.max / 2, float.nan], + [float.min_normal / 3, -0x1.334156p+5f], [-float.min_normal / 3, float.nan], + [float.max / 3, 0x1.30701p+5f], [-float.max / 3, float.nan], + ]; + testLog10(vals); + } + { + double[2][16] vals = [ + [double.nan, double.nan],[-double.nan, double.nan], + [double.infinity, double.infinity], [-double.infinity, double.nan], + [double.min_normal, -0x1.33a7146f72a42p+8], [-double.min_normal, double.nan], + [double.max, 0x1.34413509f79ffp+8], [-double.max, double.nan], + [double.min_normal / 2, -0x1.33f424bcb522p+8], [-double.min_normal / 2, double.nan], + [double.max / 2, 0x1.33f424bcb522p+8], [-double.max / 2, double.nan], + [double.min_normal / 3, -0x1.3421390dcbe37p+8], [-double.min_normal / 3, double.nan], + [double.max / 3, 0x1.33c7106b9e609p+8], [-double.max / 3, double.nan], + ]; + testLog10(vals); + } + alias F = floatTraits!real; + static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple) + {{ + real[2][16] vals = [ + [real.nan, real.nan],[-real.nan, real.nan], + [real.infinity, real.infinity], [-real.infinity, real.nan], + [real.min_normal, -0x1.343793004f503232p+12L], [-real.min_normal, real.nan], + [real.max, 0x1.34413509f79fef32p+12L], [-real.max, real.nan], + [real.min_normal / 2, -0x1.343c6405237810b2p+12L], [-real.min_normal / 2, real.nan], + [real.max / 2, 0x1.343c6405237810b2p+12L], [-real.max / 2, real.nan], + [real.min_normal / 3, -0x1.343f354a34e427bp+12L], [-real.min_normal / 3, real.nan], + [real.max / 3, 0x1.343992c0120bf9b2p+12L], [-real.max / 3, real.nan], + ]; + testLog10(vals); + }} +} + /** * Calculates the natural logarithm of 1 + x. * @@ -3476,6 +3703,9 @@ real log1p(ulong x) @safe pure nothrow @nogc { return log1p(cast(real) x); } private T log1pImpl(T)(T x) @safe pure nothrow @nogc { import std.math.traits : isNaN, isInfinity, signbit; + import std.math.algebraic : poly; + import std.math.constants : SQRT1_2, SQRT2; + import std.math : floatTraits, RealFormat; // Special cases. if (isNaN(x) || x == 0.0) @@ -3487,7 +3717,104 @@ private T log1pImpl(T)(T x) @safe pure nothrow @nogc if (x < -1.0) return T.nan; - return logImpl(x + 1.0); + alias F = floatTraits!T; + static if (F.realFormat == RealFormat.ieeeSingle || + F.realFormat == RealFormat.ieeeDouble) + { + // When the input is within the range 1/sqrt(2) <= x+1 <= sqrt(2), compute + // log1p inline. Forwarding to log() would otherwise result in inaccuracies. + const T xp1 = x + 1.0; + if (xp1 >= SQRT1_2 && xp1 <= SQRT2) + { + alias coeffs = LogCoeffs!T; + + T px = poly(x, coeffs.logp1P); + T qx = poly(x, coeffs.logp1Q); + const T xx = x * x; + qx = x + ((cast(T) -0.5) * xx + x * (xx * px / qx)); + return qx; + } + } + + return logImpl!(T, true)(x); +} + +@safe @nogc nothrow unittest +{ + import std.math : floatTraits, RealFormat; + import std.meta : AliasSeq; + + static void testLog1p(T)(T[2][] vals) + { + import std.math.operations : isClose; + import std.math.traits : isNaN; + foreach (ref pair; vals) + { + if (isNaN(pair[1])) + assert(isNaN(log1p(pair[0]))); + else + assert(isClose(log1p(pair[0]), pair[1])); + } + } + static foreach (F; AliasSeq!(float, double, real)) + {{ + F[2][24] vals = [ + [F(1), F(0x1.62e42fefa39ef358p-1)], [F(2), F(0x1.193ea7aad030a976p+0)], + [F(4), F(0x1.9c041f7ed8d336bp+0)], [F(8), F(0x1.193ea7aad030a976p+1)], + [F(16), F(0x1.6aa6bc1fa7f79cfp+1)], [F(32), F(0x1.bf8d8f4d5b8d1038p+1)], + [F(64), F(0x1.0b292939429755ap+2)], [F(128), F(0x1.37072a9b5b6cb31p+2)], + [F(256), F(0x1.63241004e9010ad8p+2)], [F(512), F(0x1.8f60adf041bde2a8p+2)], + [F(1024), F(0x1.bbad39ebe1cc08b6p+2)], [F(2048), F(0x1.e801c1698ba4395cp+2)], + [F(3), F(0x1.62e42fefa39ef358p+0)], [F(5), F(0x1.cab0bfa2a2002322p+0)], + [F(7), F(0x1.0a2b23f3bab73682p+1)], [F(15), F(0x1.62e42fefa39ef358p+1)], + [F(17), F(0x1.71f7b3a6b918664cp+1)], [F(31), F(0x1.bb9d3beb8c86b02ep+1)], + [F(33), F(0x1.c35fc81b90df59c6p+1)], [F(63), F(0x1.0a2b23f3bab73682p+2)], + [F(65), F(0x1.0c234da4a23a6686p+2)], [F(-0), F(-0x0p+0)], [F(0), F(0x0p+0)], + [F(10000), F(0x1.26bbed6fbd84182ep+3)], + ]; + testLog1p(vals); + }} + { + float[2][16] vals = [ + [float.nan, float.nan],[-float.nan, float.nan], + [float.infinity, float.infinity], [-float.infinity, float.nan], + [float.min_normal, 0x1p-126f], [-float.min_normal, -0x1p-126f], + [float.max, 0x1.62e43p+6f], [-float.max, float.nan], + [float.min_normal / 2, 0x0.8p-126f], [-float.min_normal / 2, -0x0.8p-126f], + [float.max / 2, 0x1.601e68p+6f], [-float.max / 2, float.nan], + [float.min_normal / 3, 0x0.555556p-126f], [-float.min_normal / 3, -0x0.555556p-126f], + [float.max / 3, 0x1.5e7f36p+6f], [-float.max / 3, float.nan], + ]; + testLog1p(vals); + } + { + double[2][16] vals = [ + [double.nan, double.nan],[-double.nan, double.nan], + [double.infinity, double.infinity], [-double.infinity, double.nan], + [double.min_normal, 0x1p-1022], [-double.min_normal, -0x1p-1022], + [double.max, 0x1.62e42fefa39efp+9], [-double.max, double.nan], + [double.min_normal / 2, 0x0.8p-1022], [-double.min_normal / 2, -0x0.8p-1022], + [double.max / 2, 0x1.628b76e3a7b61p+9], [-double.max / 2, double.nan], + [double.min_normal / 3, 0x0.5555555555555p-1022], [-double.min_normal / 3, -0x0.5555555555555p-1022], + [double.max / 3, 0x1.6257909bce36ep+9], [-double.max / 3, double.nan], + ]; + testLog1p(vals); + } + alias F = floatTraits!real; + static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple) + {{ + real[2][16] vals = [ + [real.nan, real.nan],[-real.nan, real.nan], + [real.infinity, real.infinity], [-real.infinity, real.nan], + [real.min_normal, 0x1p-16382L], [-real.min_normal, -0x1p-16382L], + [real.max, 0x1.62e42fefa39ef358p+13L], [-real.max, real.nan], + [real.min_normal / 2, 0x0.8p-16382L], [-real.min_normal / 2, -0x0.8p-16382L], + [real.max / 2, 0x1.62dea45ee3e064dcp+13L], [-real.max / 2, real.nan], + [real.min_normal / 3, 0x0.5555555555555556p-16382L], [-real.min_normal / 3, -0x0.5555555555555556p-16382L], + [real.max / 3, 0x1.62db65fa664871d2p+13L], [-real.max / 3, real.nan], + ]; + testLog1p(vals); + }} } /*************************************** @@ -3635,6 +3962,84 @@ Ldone: return z; } +@safe @nogc nothrow unittest +{ + import std.math : floatTraits, RealFormat; + import std.meta : AliasSeq; + + static void testLog2(T)(T[2][] vals) + { + import std.math.operations : isClose; + import std.math.traits : isNaN; + foreach (ref pair; vals) + { + if (isNaN(pair[1])) + assert(isNaN(log2(pair[0]))); + else + assert(isClose(log2(pair[0]), pair[1])); + } + } + static foreach (F; AliasSeq!(float, double, real)) + {{ + F[2][24] vals = [ + [F(1), F(0x0p+0)], [F(2), F(0x1p+0)], + [F(4), F(0x1p+1)], [F(8), F(0x1.8p+1)], + [F(16), F(0x1p+2)], [F(32), F(0x1.4p+2)], + [F(64), F(0x1.8p+2)], [F(128), F(0x1.cp+2)], + [F(256), F(0x1p+3)], [F(512), F(0x1.2p+3)], + [F(1024), F(0x1.4p+3)], [F(2048), F(0x1.6p+3)], + [F(3), F(0x1.95c01a39fbd687ap+0)], [F(5), F(0x1.2934f0979a3715fcp+1)], + [F(7), F(0x1.675767f54042cd9ap+1)], [F(15), F(0x1.f414fdb4982259ccp+1)], + [F(17), F(0x1.0598fdbeb244c5ap+2)], [F(31), F(0x1.3d118d66c4d4e554p+2)], + [F(33), F(0x1.42d75a6eb1dfb0e6p+2)], [F(63), F(0x1.7e8bc1179e0caa9cp+2)], + [F(65), F(0x1.816e79685c2d2298p+2)], [F(-0), -F.infinity], [F(0), -F.infinity], + [F(10000), F(0x1.a934f0979a3715fcp+3)], + ]; + testLog2(vals); + }} + { + float[2][16] vals = [ + [float.nan, float.nan],[-float.nan, float.nan], + [float.infinity, float.infinity], [-float.infinity, float.nan], + [float.min_normal, -0x1.f8p+6f], [-float.min_normal, float.nan], + [float.max, 0x1p+7f], [-float.max, float.nan], + [float.min_normal / 2, -0x1.fcp+6f], [-float.min_normal / 2, float.nan], + [float.max / 2, 0x1.fcp+6f], [-float.max / 2, float.nan], + [float.min_normal / 3, -0x1.fe57p+6f], [-float.min_normal / 3, float.nan], + [float.max / 3, 0x1.f9a9p+6f], [-float.max / 3, float.nan], + ]; + testLog2(vals); + } + { + double[2][16] vals = [ + [double.nan, double.nan],[-double.nan, double.nan], + [double.infinity, double.infinity], [-double.infinity, double.nan], + [double.min_normal, -0x1.ffp+9], [-double.min_normal, double.nan], + [double.max, 0x1p+10], [-double.max, double.nan], + [double.min_normal / 2, -0x1.ff8p+9], [-double.min_normal / 2, double.nan], + [double.max / 2, 0x1.ff8p+9], [-double.max / 2, double.nan], + [double.min_normal / 3, -0x1.ffcae00d1cfdfp+9], [-double.min_normal / 3, double.nan], + [double.max / 3, 0x1.ff351ff2e3021p+9], [-double.max / 3, double.nan], + ]; + testLog2(vals); + } + alias F = floatTraits!real; + static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple) + {{ + real[2][16] vals = [ + [real.nan, real.nan],[-real.nan, real.nan], + [real.infinity, real.infinity], [-real.infinity, real.nan], + [real.min_normal, -0x1.fffp+13L], [-real.min_normal, real.nan], + [real.max, 0x1p+14L], [-real.max, real.nan], + [real.min_normal / 2, -0x1.fff8p+13L], [-real.min_normal / 2, real.nan], + [real.max / 2, 0x1.fff8p+13L], [-real.max / 2, real.nan], + [real.min_normal / 3, -0x1.fffcae00d1cfdeb4p+13L], [-real.min_normal / 3, real.nan], + [real.max / 3, 0x1.fff351ff2e30214cp+13L], [-real.max / 3, real.nan], + ]; + testLog2(vals); + }} +} + /***************************************** * Extracts the exponent of x as a signed integral value. * @@ -3754,6 +4159,84 @@ private T logbImpl(T)(T x) @trusted pure nothrow @nogc return ilogb(x); } +@safe @nogc nothrow unittest +{ + import std.math : floatTraits, RealFormat; + import std.meta : AliasSeq; + + static void testLogb(T)(T[2][] vals) + { + import std.math.operations : isClose; + import std.math.traits : isNaN; + foreach (ref pair; vals) + { + if (isNaN(pair[1])) + assert(isNaN(logb(pair[0]))); + else + assert(isClose(logb(pair[0]), pair[1])); + } + } + static foreach (F; AliasSeq!(float, double, real)) + {{ + F[2][24] vals = [ + [F(1), F(0x0p+0)], [F(2), F(0x1p+0)], + [F(4), F(0x1p+1)], [F(8), F(0x1.8p+1)], + [F(16), F(0x1p+2)], [F(32), F(0x1.4p+2)], + [F(64), F(0x1.8p+2)], [F(128), F(0x1.cp+2)], + [F(256), F(0x1p+3)], [F(512), F(0x1.2p+3)], + [F(1024), F(0x1.4p+3)], [F(2048), F(0x1.6p+3)], + [F(3), F(0x1p+0)], [F(5), F(0x1p+1)], + [F(7), F(0x1p+1)], [F(15), F(0x1.8p+1)], + [F(17), F(0x1p+2)], [F(31), F(0x1p+2)], + [F(33), F(0x1.4p+2)], [F(63), F(0x1.4p+2)], + [F(65), F(0x1.8p+2)], [F(-0), -F.infinity], [F(0), -F.infinity], + [F(10000), F(0x1.ap+3)], + ]; + testLogb(vals); + }} + { + float[2][16] vals = [ + [float.nan, float.nan],[-float.nan, float.nan], + [float.infinity, float.infinity], [-float.infinity, float.infinity], + [float.min_normal, -0x1.f8p+6f], [-float.min_normal, -0x1.f8p+6f], + [float.max, 0x1.fcp+6f], [-float.max, 0x1.fcp+6f], + [float.min_normal / 2, -0x1.fcp+6f], [-float.min_normal / 2, -0x1.fcp+6f], + [float.max / 2, 0x1.f8p+6f], [-float.max / 2, 0x1.f8p+6f], + [float.min_normal / 3, -0x1p+7f], [-float.min_normal / 3, -0x1p+7f], + [float.max / 3, 0x1.f8p+6f], [-float.max / 3, 0x1.f8p+6f], + ]; + testLogb(vals); + } + { + double[2][16] vals = [ + [double.nan, double.nan],[-double.nan, double.nan], + [double.infinity, double.infinity], [-double.infinity, double.infinity], + [double.min_normal, -0x1.ffp+9], [-double.min_normal, -0x1.ffp+9], + [double.max, 0x1.ff8p+9], [-double.max, 0x1.ff8p+9], + [double.min_normal / 2, -0x1.ff8p+9], [-double.min_normal / 2, -0x1.ff8p+9], + [double.max / 2, 0x1.ffp+9], [-double.max / 2, 0x1.ffp+9], + [double.min_normal / 3, -0x1p+10], [-double.min_normal / 3, -0x1p+10], + [double.max / 3, 0x1.ffp+9], [-double.max / 3, 0x1.ffp+9], + ]; + testLogb(vals); + } + alias F = floatTraits!real; + static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple) + {{ + real[2][16] vals = [ + [real.nan, real.nan],[-real.nan, real.nan], + [real.infinity, real.infinity], [-real.infinity, real.infinity], + [real.min_normal, -0x1.fffp+13L], [-real.min_normal, -0x1.fffp+13L], + [real.max, 0x1.fff8p+13L], [-real.max, 0x1.fff8p+13L], + [real.min_normal / 2, -0x1.fff8p+13L], [-real.min_normal / 2, -0x1.fff8p+13L], + [real.max / 2, 0x1.fffp+13L], [-real.max / 2, 0x1.fffp+13L], + [real.min_normal / 3, -0x1p+14L], [-real.min_normal / 3, -0x1p+14L], + [real.max / 3, 0x1.fffp+13L], [-real.max / 3, 0x1.fffp+13L], + ]; + testLogb(vals); + }} +} + /************************************* * Efficiently calculates x * 2$(SUPERSCRIPT n). * diff --git a/libphobos/src/std/net/curl.d b/libphobos/src/std/net/curl.d index 8745bbd..42a34b9 100644 --- a/libphobos/src/std/net/curl.d +++ b/libphobos/src/std/net/curl.d @@ -2171,7 +2171,7 @@ private mixin template Protocol() * * Example: * ---- - * import std.net.curl, std.stdio; + * import std.net.curl, std.stdio, std.conv; * auto client = HTTP("dlang.org"); * client.onReceive = (ubyte[] data) * { @@ -2817,7 +2817,7 @@ struct HTTP * * Example: * ---- - * import std.net.curl, std.stdio; + * import std.net.curl, std.stdio, std.conv; * auto client = HTTP("dlang.org"); * client.onReceive = (ubyte[] data) * { @@ -3054,7 +3054,7 @@ struct HTTP * * Example: * ---- - * import std.net.curl, std.stdio; + * import std.net.curl, std.stdio, std.conv; * auto http = HTTP("http://www.mydomain.com"); * http.onReceive = (ubyte[] data) { writeln(to!(const(char)[])(data)); return data.length; }; * http.postData = [1,2,3,4,5]; @@ -3073,7 +3073,7 @@ struct HTTP * * Example: * ---- - * import std.net.curl, std.stdio; + * import std.net.curl, std.stdio, std.conv; * auto http = HTTP("http://www.mydomain.com"); * http.onReceive = (ubyte[] data) { writeln(to!(const(char)[])(data)); return data.length; }; * http.postData = "The quick...."; @@ -3145,7 +3145,7 @@ struct HTTP * * Example: * ---- - * import std.net.curl, std.stdio; + * import std.net.curl, std.stdio, std.conv; * auto http = HTTP("dlang.org"); * http.onReceive = (ubyte[] data) { writeln(to!(const(char)[])(data)); return data.length; }; * http.onReceiveHeader = (in char[] key, in char[] value) { writeln(key, " = ", value); }; @@ -4551,7 +4551,7 @@ struct Curl * * Example: * ---- - * import std.net.curl, std.stdio; + * import std.net.curl, std.stdio, std.conv; * Curl curl; * curl.initialize(); * curl.set(CurlOption.url, "http://dlang.org"); diff --git a/libphobos/src/std/process.d b/libphobos/src/std/process.d index 3eaa283..494910f 100644 --- a/libphobos/src/std/process.d +++ b/libphobos/src/std/process.d @@ -2505,7 +2505,7 @@ version (Windows) import std.exception : collectException; import std.typecons : tuple; - TestScript prog = ":Loop\ngoto Loop;"; + TestScript prog = ":Loop\r\n" ~ "goto Loop"; auto pid = spawnProcess(prog.path); // Doesn't block longer than one second @@ -3658,7 +3658,7 @@ string escapeShellCommand(scope const(char[])[] args...) @safe pure { args : ["foo bar", "hello"], windows : `"foo bar" hello`, - posix : `'foo bar' 'hello'` + posix : `'foo bar' hello` }, { args : ["foo bar", "hello world"], @@ -3668,20 +3668,34 @@ string escapeShellCommand(scope const(char[])[] args...) @safe pure { args : ["foo bar", "hello", "world"], windows : `"foo bar" hello world`, - posix : `'foo bar' 'hello' 'world'` + posix : `'foo bar' hello world` }, { args : ["foo bar", `'"^\`], windows : `"foo bar" ^"'\^"^^\\^"`, posix : `'foo bar' ''\''"^\'` }, + { + args : ["foo bar", ""], + windows : `"foo bar" ^"^"`, + posix : `'foo bar' ''` + }, + { + args : ["foo bar", "2"], + windows : `"foo bar" ^"2^"`, + posix : `'foo bar' '2'` + }, ]; foreach (test; tests) + { + auto actual = escapeShellCommand(test.args); version (Windows) - assert(escapeShellCommand(test.args) == test.windows); + string expected = test.windows; else - assert(escapeShellCommand(test.args) == test.posix ); + string expected = test.posix; + assert(actual == expected, "\nExpected: " ~ expected ~ "\nGot: " ~ actual); + } } private string escapeShellCommandString(return scope string command) @safe pure @@ -3922,6 +3936,37 @@ private char[] escapePosixArgumentImpl(alias allocator)(scope const(char)[] arg) @safe nothrow if (is(typeof(allocator(size_t.init)[0] = char.init))) { + bool needQuoting = { + import std.ascii : isAlphaNum, isDigit; + import std.algorithm.comparison : among; + + // Empty arguments need to be specified as '' + if (arg.length == 0) + return true; + // Arguments ending with digits need to be escaped, + // to disambiguate with 1>file redirection syntax + if (isDigit(arg[$-1])) + return true; + + // Obtained using: + // for n in $(seq 1 255) ; do + // c=$(printf \\$(printf "%o" $n)) + // q=$(/bin/printf '%q' "$c") + // if [[ "$q" == "$c" ]] ; then printf "%s, " "'$c'" ; fi + // done + // printf '\n' + foreach (char c; arg) + if (!isAlphaNum(c) && !c.among('%', '+', ',', '-', '.', '/', ':', '@', ']', '_')) + return true; + return false; + }(); + if (!needQuoting) + { + auto buf = allocator(arg.length); + buf[] = arg; + return buf; + } + // '\'' means: close quoted part of argument, append an escaped // single quote, and reopen quotes @@ -3995,6 +4040,11 @@ version (unittest_burnin) // Then, test this module with: // rdmd --main -unittest -version=unittest_burnin process.d + import std.file : readText, remove; + import std.format : format; + import std.path : absolutePath; + import std.random : uniform; + auto helper = absolutePath("std_process_unittest_helper"); assert(executeShell(helper ~ " hello").output.split("\0")[1..$] == ["hello"], "Helper malfunction"); diff --git a/libphobos/src/std/range/primitives.d b/libphobos/src/std/range/primitives.d index cdab401..748fde3 100644 --- a/libphobos/src/std/range/primitives.d +++ b/libphobos/src/std/range/primitives.d @@ -171,9 +171,9 @@ Returns: */ enum bool isInputRange(R) = is(typeof(R.init) == R) - && is(ReturnType!((R r) => r.empty) == bool) + && is(typeof((R r) { return r.empty; } (R.init)) == bool) && (is(typeof((return ref R r) => r.front)) || is(typeof(ref (return ref R r) => r.front))) - && !is(ReturnType!((R r) => r.front) == void) + && !is(typeof((R r) { return r.front; } (R.init)) == void) && is(typeof((R r) => r.popFront)); /// @@ -998,7 +998,7 @@ See_Also: The header of $(MREF std,range) for tutorials on ranges. */ enum bool isForwardRange(R) = isInputRange!R - && is(ReturnType!((R r) => r.save) == R); + && is(typeof((R r) { return r.save; } (R.init)) == R); /// @safe unittest @@ -1041,7 +1041,7 @@ See_Also: */ enum bool isBidirectionalRange(R) = isForwardRange!R && is(typeof((R r) => r.popBack)) - && is(ReturnType!((R r) => r.back) == ElementType!R); + && is(typeof((R r) { return r.back; } (R.init)) == ElementType!R); /// @safe unittest @@ -1674,8 +1674,8 @@ The following expression must be true for `hasSlicing` to be `true`: ---- isForwardRange!R - && !isNarrowString!R - && is(ReturnType!((R r) => r[1 .. 1].length) == size_t) + && !(isAutodecodableString!R && !isAggregateType!R) + && is(typeof((R r) { return r[1 .. 1].length; } (R.init)) == size_t) && (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R) && (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R)) && (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R @@ -1688,7 +1688,7 @@ The following expression must be true for `hasSlicing` to be `true`: */ enum bool hasSlicing(R) = isForwardRange!R && !(isAutodecodableString!R && !isAggregateType!R) - && is(ReturnType!((R r) => r[1 .. 1].length) == size_t) + && is(typeof((R r) { return r[1 .. 1].length; } (R.init)) == size_t) && (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R) && (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R)) && (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R diff --git a/libphobos/src/std/regex/internal/parser.d b/libphobos/src/std/regex/internal/parser.d index 448bb99..ab2b297 100644 --- a/libphobos/src/std/regex/internal/parser.d +++ b/libphobos/src/std/regex/internal/parser.d @@ -1010,12 +1010,14 @@ if (isForwardRange!R && is(ElementType!R : dchar)) // @trusted void error(string msg) { - import std.array : appender; - import std.format.write : formattedWrite; - auto app = appender!string(); - formattedWrite(app, "%s\nPattern with error: `%s` <--HERE-- `%s`", - msg, origin[0..$-pat.length], pat); - throw new RegexException(app.data); + import std.conv : text; + string app = msg; + app ~= "\nPattern with error: `"; + app ~= origin[0..$-pat.length].text; + app ~= "` <--HERE-- `"; + app ~= pat.text; + app ~= "`"; + throw new RegexException(app); } alias Char = BasicElementOf!R; diff --git a/libphobos/src/std/socket.d b/libphobos/src/std/socket.d index 593052e..3359c8e 100644 --- a/libphobos/src/std/socket.d +++ b/libphobos/src/std/socket.d @@ -802,10 +802,14 @@ class InternetHost { string getHostNameFromInt = ih.name.dup; - assert(ih.getHostByAddr(ia.toAddrString())); - string getHostNameFromStr = ih.name.dup; + // This randomly fails in the compiler test suite + //assert(ih.getHostByAddr(ia.toAddrString())); - assert(getHostNameFromInt == getHostNameFromStr); + if (ih.getHostByAddr(ia.toAddrString())) + { + string getHostNameFromStr = ih.name.dup; + assert(getHostNameFromInt == getHostNameFromStr); + } } } diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d index 802aa128..92e4906 100644 --- a/libphobos/src/std/stdio.d +++ b/libphobos/src/std/stdio.d @@ -1374,8 +1374,9 @@ Throws: `Exception` if the file is not opened. } /** -Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/ftell.html, ftell) for the -managed file handle. +Calls $(HTTP cplusplus.com/reference/cstdio/ftell.html, ftell) +for the managed file handle, which returns the current value of +the position indicator of the file handle. Throws: `Exception` if the file is not opened. `ErrnoException` if the call to `ftell` fails. diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d index e5f305b..bbbca69 100644 --- a/libphobos/src/std/traits.d +++ b/libphobos/src/std/traits.d @@ -10,6 +10,7 @@ * $(TR $(TH Category) $(TH Templates)) * $(TR $(TD Symbol Name traits) $(TD * $(LREF fullyQualifiedName) + * $(LREF mangledName) * $(LREF moduleName) * $(LREF packageName) * )) @@ -67,9 +68,7 @@ * $(LREF isCovariantWith) * $(LREF isImplicitlyConvertible) * )) - * $(TR $(TD SomethingTypeOf) $(TD - * $(LREF rvalueOf) - * $(LREF lvalueOf) + * $(TR $(TD Type Constructors) $(TD * $(LREF InoutOf) * $(LREF ConstOf) * $(LREF SharedOf) @@ -138,7 +137,8 @@ * $(LREF Promoted) * )) * $(TR $(TD Misc) $(TD - * $(LREF mangledName) + * $(LREF lvalueOf) + * $(LREF rvalueOf) * $(LREF Select) * $(LREF select) * )) @@ -889,7 +889,7 @@ private template fqnType(T, ); } } - else static if (is(T : U*, U)) + else static if (is(T == U*, U)) { enum fqnType = chain!( fqnType!(U, qualifiers) ~ "*" @@ -986,6 +986,10 @@ private template fqnType(T, * or a class with an `opCall`. Please note that $(D_KEYWORD ref) * is not part of a type, but the attribute of the function * (see template $(LREF functionAttributes)). + * + * $(NOTE To reduce template instantiations, consider instead using + * $(D typeof(() { return func(args); } ())) if the argument types are known or + * $(D static if (is(typeof(func) Ret == return))) if only that basic test is needed.) */ template ReturnType(alias func) if (isCallable!func) @@ -2302,7 +2306,7 @@ if (isCallable!func) int test(int); int test() @property; } - alias ov = __traits(getVirtualFunctions, Overloads, "test"); + alias ov = __traits(getVirtualMethods, Overloads, "test"); alias F_ov0 = FunctionTypeOf!(ov[0]); alias F_ov1 = FunctionTypeOf!(ov[1]); alias F_ov2 = FunctionTypeOf!(ov[2]); @@ -3925,7 +3929,7 @@ template hasStaticMember(T, string member) { static if (__traits(hasMember, T, member)) { - static if (is(T : V*, V)) + static if (is(T == V*, V)) alias U = V; else alias U = T; @@ -4529,7 +4533,7 @@ if (is(C == class) || is(C == interface)) static if (__traits(hasMember, Node, name) && __traits(compiles, __traits(getMember, Node, name))) { // Get all overloads in sight (not hidden). - alias inSight = __traits(getVirtualFunctions, Node, name); + alias inSight = __traits(getVirtualMethods, Node, name); // And collect all overloads in ancestor classes to reveal hidden // methods. The result may contain duplicates. @@ -5297,7 +5301,8 @@ enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lv static assert(!isAssignable!S5); // `-preview=in` is enabled - static if (!is(typeof(mixin(q{(in ref int a) => a})))) + alias DScannerBug895 = int[256]; + static if (((in DScannerBug895 a) { return __traits(isRef, a); })(DScannerBug895.init)) { struct S6 { void opAssign(in S5); } @@ -6066,7 +6071,7 @@ template StringTypeOf(T) static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) ))); alias Str = Q!T[]; - class C(S) { S val; alias val this; } + struct C(S) { S val; alias val this; } static assert(is(StringTypeOf!(C!Str) == Str)); }} } @@ -7481,24 +7486,10 @@ Params: Returns: A `bool` */ -template isSomeFunction(alias T) -{ - static if (is(typeof(& T) U : U*) && is(U == function) || is(typeof(& T) U == delegate)) - { - // T is a (nested) function symbol. - enum bool isSomeFunction = true; - } - else static if (is(T W) || is(typeof(T) W)) - { - // T is an expression or a type. Take the type of it and examine. - static if (is(W F : F*) && is(F == function)) - enum bool isSomeFunction = true; // function pointer - else - enum bool isSomeFunction = is(W == function) || is(W == delegate); - } - else - enum bool isSomeFunction = false; -} +enum bool isSomeFunction(alias T) = + is(T == return) || + is(typeof(T) == return) || + is(typeof(&T) == return); // @property /// @safe unittest @@ -7513,17 +7504,16 @@ template isSomeFunction(alias T) auto c = new C; auto fp = &func; auto dg = &c.method; - real val; static assert( isSomeFunction!func); static assert( isSomeFunction!prop); static assert( isSomeFunction!(C.method)); static assert( isSomeFunction!(C.prop)); static assert( isSomeFunction!(c.prop)); - static assert( isSomeFunction!(c.prop)); static assert( isSomeFunction!fp); static assert( isSomeFunction!dg); + real val; static assert(!isSomeFunction!int); static assert(!isSomeFunction!val); } @@ -7969,7 +7959,7 @@ has both opApply and a range interface. */ template ForeachType(T) { - alias ForeachType = ReturnType!(typeof( + alias ForeachType = typeof( (inout int x = 0) { foreach (elem; T.init) @@ -7977,7 +7967,7 @@ template ForeachType(T) return elem; } assert(0); - })); + }()); } /// diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d index 25cf9e0..bde8439 100644 --- a/libphobos/src/std/typecons.d +++ b/libphobos/src/std/typecons.d @@ -3160,12 +3160,6 @@ struct Nullable(T) } /// ditto - inout(typeof(this)) opIndex() inout - { - return this; - } - - /// ditto inout(typeof(this)) opIndex(size_t[2] dim) inout in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0]) { @@ -3192,6 +3186,74 @@ struct Nullable(T) { return get(); } + + /** + * Converts `Nullable` to a range. Works even when the contained type is `immutable`. + */ + auto opSlice(this This)() + { + static struct NullableRange + { + private This value; + + // starts out true if value is null + private bool empty_; + + @property bool empty() const @safe pure nothrow + { + return empty_; + } + + void popFront() @safe pure nothrow + { + empty_ = true; + } + + alias popBack = popFront; + + @property ref inout(typeof(value.get())) front() inout @safe pure nothrow + { + return value.get(); + } + + alias back = front; + + @property inout(typeof(this)) save() inout + { + return this; + } + + size_t[2] opSlice(size_t dim : 0)(size_t from, size_t to) const + { + return [from, to]; + } + + @property size_t length() const @safe pure nothrow + { + return !empty; + } + + alias opDollar(size_t dim : 0) = length; + + ref inout(typeof(value.get())) opIndex(size_t index) inout @safe pure nothrow + in (index < length) + { + return value.get(); + } + + inout(typeof(this)) opIndex(size_t[2] dim) inout + in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0]) + { + return (dim[0] == 0 && dim[1] == 1) ? this : this.init; + } + + auto opIndex() inout + { + return this; + } + } + return NullableRange(this, isNull); + } } /// ditto @@ -3774,6 +3836,34 @@ auto nullable(T)(T t) assert(hasLvalueElements!(Nullable!int)); } +// https://issues.dlang.org/show_bug.cgi?id=23640 +@safe pure nothrow unittest +{ + import std.algorithm.comparison : equal; + import std.range : only; + import std.range.primitives : hasLength, hasSlicing, + isRandomAccessRange; + static immutable struct S { int[] array; } + auto value = S([42]); + alias ImmutableNullable = immutable Nullable!S; + auto a = ImmutableNullable(value)[]; + alias Range = typeof(a); + assert(isRandomAccessRange!Range); + assert(hasLength!Range); + assert(hasSlicing!Range); + assert(!a.empty); + assert(a.front == value); + assert(a.back == value); + assert(a[0] == value); + assert(a.equal(only(value))); + assert(a[0 .. $].equal(only(value))); + Range b = a.save(); + assert(!b.empty); + b.popFront(); + assert(!a.empty); + assert(b.empty); +} + /** Just like `Nullable!T`, except that the null state is defined as a particular value. For example, $(D Nullable!(uint, uint.max)) is an diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d index 5c0659e..e2a0de7 100644 --- a/libphobos/src/std/uni/package.d +++ b/libphobos/src/std/uni/package.d @@ -712,6 +712,8 @@ import std.traits : isConvertibleToString, isIntegral, isSomeChar, isSomeString, Unqual, isDynamicArray; // debug = std_uni; +import std.internal.unicode_tables; // generated file + debug(std_uni) import std.stdio; // writefln, writeln private: @@ -6962,23 +6964,192 @@ private: enum EMPTY_CASE_TRIE = ushort.max;// from what gen_uni uses internally -// control - '\r' -enum controlSwitch = ` - case '\u0000':..case '\u0008':case '\u000E':..case '\u001F':case '\u007F':.. - case '\u0084':case '\u0086':..case '\u009F': case '\u0009':..case '\u000C': case '\u0085': -`; // TODO: redo the most of hangul stuff algorithmically in case of Graphemes too -// kill unrolled switches +// Use combined trie instead of checking for '\r' | '\n' | ccTrie, +// or extend | '\u200D' separately private static bool isRegionalIndicator(dchar ch) @safe pure @nogc nothrow { return ch >= '\U0001F1E6' && ch <= '\U0001F1FF'; } +// Our grapheme decoder is a state machine, this is list of all possible +// states before each code point. +private enum GraphemeState +{ + Start, + CR, + RI, + L, + V, + LVT, + Emoji, + EmojiZWJ, + Prepend, + End +} + +// Message values whether end of grapheme is reached +private enum TransformRes +{ + // No, unless the source range ends here + // (GB2 - break at end of text, unless text is empty) + goOn, + redo, // Run last character again with new state + retInclude, // Yes, after the just iterated character + retExclude // Yes, before the just iterated character +} + +// The logic of the grapheme decoding is all here +// GB# means Grapheme Breaking rule number # - see Unicode standard annex #29 +// Note, getting GB1 (break at start of text, unless text is empty) right +// relies on the user starting grapheme walking from beginning of the text, and +// not attempting to walk an empty text. +private enum TransformRes + function(ref GraphemeState, dchar) @safe pure nothrow @nogc [] graphemeTransforms = +[ + GraphemeState.Start: (ref state, ch) + { + // GB4. Break after controls. + if (graphemeControlTrie[ch] || ch == '\n') + return TransformRes.retInclude; + + with (GraphemeState) state = + ch == '\r' ? CR : + isRegionalIndicator(ch) ? RI : + isHangL(ch) ? L : + hangLV[ch] || isHangV(ch) ? V : + hangLVT[ch] || isHangT(ch) ? LVT : + prependTrie[ch] ? Prepend : + xpictoTrie[ch] ? Emoji : + End; + + // No matter what we encountered, we always include the + // first code point in the grapheme. + return TransformRes.goOn; + }, + + // GB3, GB4. Do not break between a CR and LF. + // Otherwise, break after controls. + GraphemeState.CR: (ref state, ch) => ch == '\n' ? + TransformRes.retInclude : + TransformRes.retExclude, + + // GB12 - GB13. Do not break within emoji flag sequences. + // That is, do not break between regional indicator (RI) symbols if + // there is an odd number of RI characters before the break point. + // This state applies if one and only one RI code point has been + // encountered. + GraphemeState.RI: (ref state, ch) + { + state = GraphemeState.End; + + return isRegionalIndicator(ch) ? + TransformRes.goOn : + TransformRes.redo; + }, + + // GB6. Do not break Hangul syllable sequences. + GraphemeState.L: (ref state, ch) + { + if (isHangL(ch)) + return TransformRes.goOn; + else if (isHangV(ch) || hangLV[ch]) + { + state = GraphemeState.V; + return TransformRes.goOn; + } + else if (hangLVT[ch]) + { + state = GraphemeState.LVT; + return TransformRes.goOn; + } + + state = GraphemeState.End; + return TransformRes.redo; + }, + + // GB7. Do not break Hangul syllable sequences. + GraphemeState.V: (ref state, ch) + { + if (isHangV(ch)) + return TransformRes.goOn; + else if (isHangT(ch)) + { + state = GraphemeState.LVT; + return TransformRes.goOn; + } + + state = GraphemeState.End; + return TransformRes.redo; + }, + + // GB8. Do not break Hangul syllable sequences. + GraphemeState.LVT: (ref state, ch) + { + if (isHangT(ch)) + return TransformRes.goOn; + + state = GraphemeState.End; + return TransformRes.redo; + }, + + // GB11. Do not break within emoji modifier sequences or emoji + // zwj sequences. This state applies when the last code point was + // NOT a ZWJ. + GraphemeState.Emoji: (ref state, ch) + { + if (graphemeExtendTrie[ch]) + return TransformRes.goOn; + + static assert(!graphemeExtendTrie['\u200D']); + + if (ch == '\u200D') + { + state = GraphemeState.EmojiZWJ; + return TransformRes.goOn; + } + + state = GraphemeState.End; + // There might still be spacing marks are + // at the end, which are not allowed in + // middle of emoji sequences + return TransformRes.redo; + }, + + // GB11. Do not break within emoji modifier sequences or emoji + // zwj sequences. This state applies when the last code point was + // a ZWJ. + GraphemeState.EmojiZWJ: (ref state, ch) + { + state = GraphemeState.Emoji; + if (xpictoTrie[ch]) + return TransformRes.goOn; + return TransformRes.redo; + }, + + // GB9b. Do not break after Prepend characters. + GraphemeState.Prepend: (ref state, ch) + { + // GB5. Break before controls. + if (graphemeControlTrie[ch] || ch == '\r' || ch == '\n') + return TransformRes.retExclude; + + state = GraphemeState.Start; + return TransformRes.redo; + }, + + // GB9, GB9a. Do not break before extending characters, ZWJ + // or SpacingMarks. + // GB999. Otherwise, break everywhere. + GraphemeState.End: (ref state, ch) + => !graphemeExtendTrie[ch] && !spacingMarkTrie[ch] && ch != '\u200D' ? + TransformRes.retExclude : + TransformRes.goOn +]; + template genericDecodeGrapheme(bool getValue) { - alias graphemeExtend = graphemeExtendTrie; - alias spacingMark = mcTrie; static if (getValue) alias Value = Grapheme; else @@ -6986,115 +7157,44 @@ template genericDecodeGrapheme(bool getValue) Value genericDecodeGrapheme(Input)(ref Input range) { - import std.internal.unicode_tables : isHangL, isHangT, isHangV; // generated file - enum GraphemeState { - Start, - CR, - RI, - L, - V, - LVT - } static if (getValue) Grapheme grapheme; auto state = GraphemeState.Start; - enum eat = q{ - static if (getValue) - grapheme ~= ch; - range.popFront(); - }; - dchar ch; + assert(!range.empty, "Attempting to decode grapheme from an empty " ~ Input.stringof); + outer: while (!range.empty) { ch = range.front; - final switch (state) with(GraphemeState) + + rerun: + final switch (graphemeTransforms[state](state, ch)) + with(TransformRes) { - case Start: - mixin(eat); - if (ch == '\r') - state = CR; - else if (isRegionalIndicator(ch)) - state = RI; - else if (isHangL(ch)) - state = L; - else if (hangLV[ch] || isHangV(ch)) - state = V; - else if (hangLVT[ch]) - state = LVT; - else if (isHangT(ch)) - state = LVT; - else - { - switch (ch) - { - mixin(controlSwitch); - goto L_End; - default: - goto L_End_Extend; - } - } - break; - case CR: - if (ch == '\n') - mixin(eat); - goto L_End_Extend; - case RI: - if (isRegionalIndicator(ch)) - mixin(eat); - goto L_End_Extend; - case L: - if (isHangL(ch)) - mixin(eat); - else if (isHangV(ch) || hangLV[ch]) - { - state = V; - mixin(eat); - } - else if (hangLVT[ch]) - { - state = LVT; - mixin(eat); - } - else - goto L_End_Extend; - break; - case V: - if (isHangV(ch)) - mixin(eat); - else if (isHangT(ch)) - { - state = LVT; - mixin(eat); - } - else - goto L_End_Extend; - break; - case LVT: - if (isHangT(ch)) - { - mixin(eat); - } - else - goto L_End_Extend; - break; + case goOn: + static if (getValue) + grapheme ~= ch; + range.popFront(); + continue; + + case redo: + goto rerun; + + case retInclude: + static if (getValue) + grapheme ~= ch; + range.popFront(); + break outer; + + case retExclude: + break outer; } } - L_End_Extend: - while (!range.empty) - { - ch = range.front; - // extend & spacing marks - if (!graphemeExtend[ch] && !spacingMark[ch]) - break; - mixin(eat); - } - L_End: + static if (getValue) return grapheme; } - } public: // Public API continues @@ -7143,6 +7243,31 @@ if (is(C : dchar)) static assert(c2 == 3); // \u0301 has 2 UTF-8 code units } +// TODO: make this @nogc. Probably no big deal since the state machine is +// already GC-free. +@safe pure nothrow unittest +{ + // grinning face ~ emoji modifier fitzpatrick type-5 ~ grinning face + assert(graphemeStride("\U0001F600\U0001f3FE\U0001F600"d, 0) == 2); + // skier ~ female sign ~ '€' + assert(graphemeStride("\u26F7\u2640€"d, 0) == 1); + // skier ~ emoji modifier fitzpatrick type-5 ~ female sign ~ '€' + assert(graphemeStride("\u26F7\U0001f3FE\u2640€"d, 0) == 2); + // skier ~ zero-width joiner ~ female sign ~ '€' + assert(graphemeStride("\u26F7\u200D\u2640€"d, 0) == 3); + // skier ~ emoji modifier fitzpatrick type-5 ~ zero-width joiner + // ~ female sign ~ '€' + assert(graphemeStride("\u26F7\U0001f3FE\u200D\u2640€"d, 0) == 4); + // skier ~ zero-width joiner ~ '€' + assert(graphemeStride("\u26F7\u200D€"d, 0) == 2); + //'€' ~ zero-width joiner ~ skier + assert(graphemeStride("€\u200D\u26F7"d, 0) == 2); + // Kaithi number sign ~ Devanagari digit four ~ Devanagari digit two + assert(graphemeStride("\U000110BD\u096A\u0968"d, 0) == 2); + // Kaithi number sign ~ null + assert(graphemeStride("\U000110BD\0"d, 0) == 1); +} + /++ Reads one full grapheme cluster from an $(REF_ALTTEXT input range, isInputRange, std,range,primitives) of dchar `inp`. @@ -7285,6 +7410,13 @@ private static @safe struct InputRangeString assert(nonForwardRange.walkLength == 4); } +// Issue 23474 +@safe pure unittest +{ + import std.range.primitives : walkLength; + assert(byGrapheme("\r\u0308").walkLength == 2); +} + /++ $(P Lazily transform a range of $(LREF Grapheme)s to a range of code points.) @@ -10530,8 +10662,6 @@ private: @safe pure nothrow @nogc @property { - import std.internal.unicode_tables; // generated file - // It's important to use auto return here, so that the compiler // only runs semantic on the return type if the function gets // used. Also these are functions rather than templates to not @@ -10578,10 +10708,10 @@ private: } //grapheme breaking algorithm tables - auto mcTrie() + auto spacingMarkTrie() { - import std.internal.unicode_grapheme : mcTrieEntries; - static immutable res = asTrie(mcTrieEntries); + import std.internal.unicode_grapheme : spacingMarkTrieEntries; + static immutable res = asTrie(spacingMarkTrieEntries); return res; } @@ -10606,6 +10736,27 @@ private: return res; } + auto prependTrie() + { + import std.internal.unicode_grapheme : prependTrieEntries; + static immutable res = asTrie(prependTrieEntries); + return res; + } + + auto graphemeControlTrie() + { + import std.internal.unicode_grapheme : controlTrieEntries; + static immutable res = asTrie(controlTrieEntries); + return res; + } + + auto xpictoTrie() + { + import std.internal.unicode_grapheme : Extended_PictographicTrieEntries; + static immutable res = asTrie(Extended_PictographicTrieEntries); + return res; + } + // tables below are used for composition/decomposition auto combiningClassTrie() { diff --git a/libphobos/src/std/utf.d b/libphobos/src/std/utf.d index 7a0556d..3eef5cb 100644 --- a/libphobos/src/std/utf.d +++ b/libphobos/src/std/utf.d @@ -3136,7 +3136,7 @@ private T toUTFImpl(T, S)(scope S s) collection cycle and cause a nasty bug when the C code tries to use it. +/ template toUTFz(P) -if (is(P : C*, C) && isSomeChar!C) +if (is(P == C*, C) && isSomeChar!C) { P toUTFz(S)(S str) @safe pure if (isSomeString!S) diff --git a/libphobos/testsuite/libphobos.hash/test_hash.d b/libphobos/testsuite/libphobos.hash/test_hash.d index 0ad2443..a6d7e5a 100644 --- a/libphobos/testsuite/libphobos.hash/test_hash.d +++ b/libphobos/testsuite/libphobos.hash/test_hash.d @@ -290,14 +290,14 @@ void issue22076() extern(C++) static class C0 { int foo() { return 0; } // Need at least one function in vtable. - S0 a; alias a this; + S0 a; alias a this; // { dg-warning "is deprecated" } } extern(C++) static class C1 { S1 a; inout(S1)* b() inout nothrow { return &a; } - alias b this; + alias b this; // { dg-warning "is deprecated" } } cast(void) hashOf(S0.init); diff --git a/libphobos/testsuite/libphobos.shared/finalize.d b/libphobos/testsuite/libphobos.shared/finalize.d index fcec87b..f31b818 100644 --- a/libphobos/testsuite/libphobos.shared/finalize.d +++ b/libphobos/testsuite/libphobos.shared/finalize.d @@ -7,9 +7,9 @@ import core.sys.posix.dlfcn; void runTest() { Object obj; - obj = Object.factory("lib.MyFinalizer"); // { dg-warning "is deprecated" } + obj = Object.factory("lib.MyFinalizer"); assert(obj.toString() == "lib.MyFinalizer"); - obj = Object.factory("lib.MyFinalizerBig"); // { dg-warning "is deprecated" } + obj = Object.factory("lib.MyFinalizerBig"); assert(obj.toString() == "lib.MyFinalizerBig"); } |