mirror of
https://github.com/dlang/phobos.git
synced 2025-04-27 05:30:33 +03:00
fix Issue 16291 - EncodingScheme.create fails
- add EncodingScheme.register overload that references the registered class - just adding the FQN name of a class does not reference that class, so it must not end up in the binary and subsequently EncodingScheme.create failed - This used to work by chance b/c all the EncodingScheme implementations were in a module w/ static ctor. Any user of std.encoding did drag in that ModuleInfo, which in turn referenced all classes of std.encoding. Since moving the static ctor to std.internal.phobosinit to break a cycle, the classes were no longer referenced by a ModuleInfo w/ shared ctor, so they wouldn't end up in the binary unless explicitly referenced elsewhere. - deprecate the old EncodingScheme.register(string fqn) b/c relying on Object.factory is slow, error prone (linkage), and really unnecessary - import encodinginit in std.encoding so that the std_encoding_shared_static_this callback actually gets run
This commit is contained in:
parent
ebbdf21a7e
commit
9d73d18c0c
6 changed files with 60 additions and 32 deletions
|
@ -216,7 +216,7 @@ EXTRA_MODULES_INTERNAL := $(addprefix \
|
|||
std/internal/digest/, sha_SSSE3 ) $(addprefix \
|
||||
std/internal/math/, biguintcore biguintnoasm biguintx86 \
|
||||
gammafunction errorfunction) $(addprefix std/internal/, \
|
||||
cstring phobosinit processinit unicode_tables scopebuffer\
|
||||
cstring encodinginit processinit unicode_tables scopebuffer\
|
||||
unicode_comp unicode_decomp unicode_grapheme unicode_norm) \
|
||||
$(addprefix std/internal/test/, dummyrange) \
|
||||
$(addprefix std/experimental/ndslice/, internal) \
|
||||
|
|
|
@ -55,6 +55,7 @@ module std.encoding;
|
|||
import std.traits;
|
||||
import std.typecons;
|
||||
import std.range.primitives;
|
||||
import std.internal.encodinginit;
|
||||
|
||||
@system unittest
|
||||
{
|
||||
|
@ -2360,17 +2361,30 @@ abstract class EncodingScheme
|
|||
* This function allows user-defined subclasses of EncodingScheme to
|
||||
* be declared in other modules.
|
||||
*
|
||||
* Params:
|
||||
* Klass = The subclass of EncodingScheme to register.
|
||||
*
|
||||
* Example:
|
||||
* ----------------------------------------------
|
||||
* class Amiga1251 : EncodingScheme
|
||||
* {
|
||||
* shared static this()
|
||||
* {
|
||||
* EncodingScheme.register("path.to.Amiga1251");
|
||||
* EncodingScheme.register!Amiga1251;
|
||||
* }
|
||||
* }
|
||||
* ----------------------------------------------
|
||||
*/
|
||||
static void register(Klass:EncodingScheme)()
|
||||
{
|
||||
scope scheme = new Klass();
|
||||
foreach (encodingName;scheme.names())
|
||||
{
|
||||
supported[toLower(encodingName)] = () => new Klass();
|
||||
}
|
||||
}
|
||||
|
||||
deprecated("Please pass the EncodingScheme subclass as template argument instead.")
|
||||
static void register(string className)
|
||||
{
|
||||
auto scheme = cast(EncodingScheme)ClassInfo.find(className).create();
|
||||
|
@ -2378,7 +2392,7 @@ abstract class EncodingScheme
|
|||
throw new EncodingException("Unable to create class "~className);
|
||||
foreach (encodingName;scheme.names())
|
||||
{
|
||||
supported[toLower(encodingName)] = className;
|
||||
supportedFactories[toLower(encodingName)] = className;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2396,7 +2410,12 @@ abstract class EncodingScheme
|
|||
*/
|
||||
static EncodingScheme create(string encodingName)
|
||||
{
|
||||
auto p = toLower(encodingName) in supported;
|
||||
encodingName = toLower(encodingName);
|
||||
|
||||
if (auto p = encodingName in supported)
|
||||
return (*p)();
|
||||
|
||||
auto p = encodingName in supportedFactories;
|
||||
if (p is null)
|
||||
throw new EncodingException("Unrecognized Encoding: "~encodingName);
|
||||
string className = *p;
|
||||
|
@ -2650,7 +2669,8 @@ abstract class EncodingScheme
|
|||
return t.length - s.length;
|
||||
}
|
||||
|
||||
__gshared string[string] supported;
|
||||
__gshared EncodingScheme function()[string] supported;
|
||||
__gshared string[string] supportedFactories;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3297,6 +3317,20 @@ class EncodingSchemeUtf32Native : EncodingScheme
|
|||
assert(ub.length == 8);
|
||||
}
|
||||
|
||||
|
||||
// shared static this() called from encodinginit to break ctor cycle
|
||||
extern(C) void std_encoding_shared_static_this()
|
||||
{
|
||||
EncodingScheme.register!EncodingSchemeASCII;
|
||||
EncodingScheme.register!EncodingSchemeLatin1;
|
||||
EncodingScheme.register!EncodingSchemeLatin2;
|
||||
EncodingScheme.register!EncodingSchemeWindows1250;
|
||||
EncodingScheme.register!EncodingSchemeWindows1252;
|
||||
EncodingScheme.register!EncodingSchemeUtf8;
|
||||
EncodingScheme.register!EncodingSchemeUtf16Native;
|
||||
EncodingScheme.register!EncodingSchemeUtf32Native;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
|
|
19
std/internal/encodinginit.d
Normal file
19
std/internal/encodinginit.d
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Written in the D programming language.
|
||||
|
||||
/++
|
||||
The purpose of this module is to perform static construction away from the
|
||||
normal modules to eliminate cyclic construction errors.
|
||||
|
||||
Copyright: Copyright 2011 - 2016
|
||||
License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
|
||||
Authors: Martin Nowak, Steven Schveighoffer
|
||||
Source: $(PHOBOSSRC std/internal/_encodinginit.d)
|
||||
+/
|
||||
module std.internal.encodinginit;
|
||||
|
||||
extern(C) void std_encoding_shared_static_this();
|
||||
|
||||
shared static this()
|
||||
{
|
||||
std_encoding_shared_static_this();
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
// Written in the D programming language.
|
||||
|
||||
/++
|
||||
The purpose of this module is to perform static construction away from the
|
||||
normal modules to eliminate cyclic construction errors.
|
||||
|
||||
Copyright: Copyright 2011 - 2016
|
||||
License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
|
||||
Authors: Jonathan M Davis, Kato Shoichi, Steven Schveighoffer
|
||||
Source: $(PHOBOSSRC std/internal/_phobosinit.d)
|
||||
+/
|
||||
module std.internal.phobosinit;
|
||||
|
||||
shared static this()
|
||||
{
|
||||
import std.encoding : EncodingScheme;
|
||||
EncodingScheme.register("std.encoding.EncodingSchemeASCII");
|
||||
EncodingScheme.register("std.encoding.EncodingSchemeLatin1");
|
||||
EncodingScheme.register("std.encoding.EncodingSchemeLatin2");
|
||||
EncodingScheme.register("std.encoding.EncodingSchemeWindows1250");
|
||||
EncodingScheme.register("std.encoding.EncodingSchemeWindows1252");
|
||||
EncodingScheme.register("std.encoding.EncodingSchemeUtf8");
|
||||
EncodingScheme.register("std.encoding.EncodingSchemeUtf16Native");
|
||||
EncodingScheme.register("std.encoding.EncodingSchemeUtf32Native");
|
||||
}
|
|
@ -267,7 +267,7 @@ SRC_STD_C_FREEBSD= \
|
|||
|
||||
SRC_STD_INTERNAL= \
|
||||
std\internal\cstring.d \
|
||||
std\internal\phobosinit.d \
|
||||
std\internal\encodinginit.d \
|
||||
std\internal\processinit.d \
|
||||
std\internal\unicode_tables.d \
|
||||
std\internal\unicode_comp.d \
|
||||
|
|
|
@ -286,7 +286,7 @@ SRC_STD_C_FREEBSD= \
|
|||
|
||||
SRC_STD_INTERNAL= \
|
||||
std\internal\cstring.d \
|
||||
std\internal\phobosinit.d \
|
||||
std\internal\encodinginit.d \
|
||||
std\internal\processinit.d \
|
||||
std\internal\unicode_tables.d \
|
||||
std\internal\unicode_comp.d \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue