aboutsummaryrefslogtreecommitdiff
path: root/libphobos/src/std/base64.d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2019-06-18 20:42:10 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2021-11-30 16:53:28 +0100
commit5fee5ec362f7a243f459e6378fd49dfc89dc9fb5 (patch)
tree61d1bdbca854a903c0860406f457f06b2040be7a /libphobos/src/std/base64.d
parentb3f60112edcb85b459e60f66c44a55138b1cef49 (diff)
downloadgcc-5fee5ec362f7a243f459e6378fd49dfc89dc9fb5.zip
gcc-5fee5ec362f7a243f459e6378fd49dfc89dc9fb5.tar.gz
gcc-5fee5ec362f7a243f459e6378fd49dfc89dc9fb5.tar.bz2
d: Import dmd b8384668f, druntime e6caaab9, phobos 5ab9ad256 (v2.098.0-beta.1)
The D front-end is now itself written in D, in order to build GDC, you will need a working GDC compiler (GCC version 9.1 or later). GCC changes: - Add support for bootstrapping the D front-end. These add the required components in order to have a D front-end written in D itself. Because the compiler front-end only depends on the core runtime modules, only libdruntime is built for the bootstrap stages. D front-end changes: - Import dmd v2.098.0-beta.1. Druntime changes: - Import druntime v2.098.0-beta.1. Phobos changes: - Import phobos v2.098.0-beta.1. The jump from v2.076.1 to v2.098.0 covers nearly 4 years worth of development on the D programming language and run-time libraries. ChangeLog: * Makefile.def: Add bootstrap to libbacktrace, libphobos, zlib, and libatomic. * Makefile.in: Regenerate. * Makefile.tpl (POSTSTAGE1_HOST_EXPORTS): Fix command for GDC. (STAGE1_CONFIGURE_FLAGS): Add --with-libphobos-druntime-only if target-libphobos-bootstrap. (STAGE2_CONFIGURE_FLAGS): Likewise. * configure: Regenerate. * configure.ac: Add support for bootstrapping D front-end. config/ChangeLog: * acx.m4 (ACX_PROG_GDC): New m4 function. gcc/ChangeLog: * Makefile.in (GDC): New variable. (GDCFLAGS): New variable. * configure: Regenerate. * configure.ac: Add call to ACX_PROG_GDC. Substitute GDCFLAGS. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd b8384668f. * Make-lang.in (d-warn): Use strict warnings. (DMD_WARN_CXXFLAGS): Remove. (DMD_COMPILE): Remove. (CHECKING_DFLAGS): Define. (WARN_DFLAGS): Define. (ALL_DFLAGS): Define. (DCOMPILE.base): Define. (DCOMPILE): Define. (DPOSTCOMPILE): Define. (DLINKER): Define. (DLLINKER): Define. (D_FRONTEND_OBJS): Add new dmd front-end objects. (D_GENERATED_SRCS): Remove. (D_GENERATED_OBJS): Remove. (D_ALL_OBJS): Remove D_GENERATED_OBJS. (d21$(exeext)): Build using DLLINKER and -static-libphobos. (d.tags): Remove dmd/*.c and dmd/root/*.c. (d.mostlyclean): Remove D_GENERATED_SRCS, d/idgen$(build_exeext), d/impcnvgen$(build_exeext). (D_INCLUDES): Include $(srcdir)/d/dmd/res. (CFLAGS-d/id.o): Remove. (CFLAGS-d/impcnvtab.o): Remove. (d/%.o): Build using DCOMPILE and DPOSTCOMPILE. Update dependencies from d/dmd/%.c to d/dmd/%.d. (d/idgen$(build_exeext)): Remove. (d/impcnvgen$(build_exeext)): Remove. (d/id.c): Remove. (d/id.h): Remove. (d/impcnvtab.c): Remove. (d/%.dmdgen.o): Remove. (D_SYSTEM_H): Remove. (d/idgen.dmdgen.o): Remove. (d/impcnvgen.dmdgen.o): Remove. * config-lang.in (boot_language): New variable. * d-attribs.cc: Include dmd/expression.h. * d-builtins.cc: Include d-frontend.h. (build_frontend_type): Update for new front-end interface. (d_eval_constant_expression): Likewise. (d_build_builtins_module): Likewise. (maybe_set_builtin_1): Likewise. (d_build_d_type_nodes): Likewise. * d-codegen.cc (d_decl_context): Likewise. (declaration_reference_p): Likewise. (declaration_type): Likewise. (parameter_reference_p): Likewise. (parameter_type): Likewise. (get_array_length): Likewise. (build_delegate_cst): Likewise. (build_typeof_null_value): Likewise. (identity_compare_p): Likewise. (lower_struct_comparison): Likewise. (build_filename_from_loc): Likewise. (build_assert_call): Remove LIBCALL_SWITCH_ERROR. (build_bounds_index_condition): Call LIBCALL_ARRAYBOUNDS_INDEXP on bounds error. (build_bounds_slice_condition): Call LIBCALL_ARRAYBOUNDS_SLICEP on bounds error. (array_bounds_check): Update for new front-end interface. (checkaction_trap_p): Handle CHECKACTION_context. (get_function_type): Update for new front-end interface. (d_build_call): Likewise. * d-compiler.cc: Remove include of dmd/scope.h. (Compiler::genCmain): Remove. (Compiler::paintAsType): Update for new front-end interface. (Compiler::onParseModule): Likewise. * d-convert.cc (convert_expr): Remove call to LIBCALL_ARRAYCAST. (convert_for_rvalue): Update for new front-end interface. (convert_for_assignment): Likewise. (convert_for_condition): Likewise. (d_array_convert): Likewise. * d-diagnostic.cc (error): Remove. (errorSupplemental): Remove. (warning): Remove. (warningSupplemental): Remove. (deprecation): Remove. (deprecationSupplemental): Remove. (message): Remove. (vtip): New. * d-frontend.cc (global): Remove. (Global::_init): Remove. (Global::startGagging): Remove. (Global::endGagging): Remove. (Global::increaseErrorCount): Remove. (Loc::Loc): Remove. (Loc::toChars): Remove. (Loc::equals): Remove. (isBuiltin): Update for new front-end interface. (eval_builtin): Likewise. (getTypeInfoType): Likewise. (inlineCopy): Remove. * d-incpath.cc: Include d-frontend.h. (add_globalpaths): Call d_gc_malloc to allocate Strings. (add_filepaths): Likewise. * d-lang.cc: Include dmd/id.h, dmd/root/file.h, d-frontend.h. Remove include of dmd/mars.h, id.h. (entrypoint_module): Remove. (entrypoint_root_module): Remove. (deps_write_string): Update for new front-end interface. (deps_write): Likewise. (d_init_options): Call rt_init. Remove setting global params that are default initialized by the front-end. (d_handle_option): Handle OPT_fcheckaction_, OPT_fdump_c___spec_, OPT_fdump_c___spec_verbose, OPT_fextern_std_, OPT_fpreview, OPT_revert, OPT_fsave_mixins_, and OPT_ftransition. (d_post_options): Propagate dip1021 and dip1000 preview flags to dip25, and flag_diagnostics_show_caret to printErrorContext. (d_add_entrypoint_module): Remove. (d_parse_file): Update for new front-end interface. (d_type_promotes_to): Likewise. (d_types_compatible_p): Likewise. * d-longdouble.cc (CTFloat::zero): Remove. (CTFloat::one): Remove. (CTFloat::minusone): Remove. (CTFloat::half): Remove. * d-system.h (POSIX): Remove. (realpath): Remove. (isalpha): Remove. (isalnum): Remove. (isdigit): Remove. (islower): Remove. (isprint): Remove. (isspace): Remove. (isupper): Remove. (isxdigit): Remove. (tolower): Remove. (_mkdir): Remove. (INT32_MAX): Remove. (INT32_MIN): Remove. (INT64_MIN): Remove. (UINT32_MAX): Remove. (UINT64_MAX): Remove. * d-target.cc: Include calls.h. (target): Remove. (define_float_constants): Remove initialization of snan. (Target::_init): Update for new front-end interface. (Target::isVectorTypeSupported): Likewise. (Target::isVectorOpSupported): Remove cases for unordered operators. (TargetCPP::typeMangle): Update for new front-end interface. (TargetCPP::parameterType): Likewise. (Target::systemLinkage): Likewise. (Target::isReturnOnStack): Likewise. (Target::isCalleeDestroyingArgs): Define. (Target::preferPassByRef): Define. * d-tree.h (d_add_entrypoint_module): Remove. * decl.cc (gcc_attribute_p): Update for new front-end interface. (apply_pragma_crt): Define. (DeclVisitor::visit(PragmaDeclaration *)): Handle pragmas crt_constructor and crt_destructor. (DeclVisitor::visit(TemplateDeclaration *)): Update for new front-end interface. (DeclVisitor::visit): Likewise. (DeclVisitor::finish_vtable): Likewise. (get_symbol_decl): Error if template has more than one nesting context. Update for new front-end interface. (make_thunk): Update for new front-end interface. (get_vtable_decl): Likewise. * expr.cc (ExprVisitor::visit): Likewise. (build_return_dtor): Likewise. * imports.cc (ImportVisitor::visit): Likewise. * intrinsics.cc: Include dmd/expression.h. Remove include of dmd/mangle.h. (maybe_set_intrinsic): Update for new front-end interface. * intrinsics.def (INTRINSIC_ROL): Update intrinsic signature. (INTRINSIC_ROR): Likewise. (INTRINSIC_ROR_TIARG): Likewise. (INTRINSIC_TOPREC): Likewise. (INTRINSIC_TOPRECL): Likewise. (INTRINSIC_TAN): Update intrinsic module and signature. (INTRINSIC_ISNAN): Likewise. (INTRINSIC_ISFINITE): Likewise. (INTRINSIC_COPYSIGN): Define intrinsic. (INTRINSIC_COPYSIGNI): Define intrinsic. (INTRINSIC_EXP): Update intrinsic module. (INTRINSIC_EXPM1): Likewise. (INTRINSIC_EXP2): Likewise. (INTRINSIC_LOG): Likewise. (INTRINSIC_LOG2): Likewise. (INTRINSIC_LOG10): Likewise. (INTRINSIC_POW): Likewise. (INTRINSIC_ROUND): Likewise. (INTRINSIC_FLOORF): Likewise. (INTRINSIC_FLOOR): Likewise. (INTRINSIC_FLOORL): Likewise. (INTRINSIC_CEILF): Likewise. (INTRINSIC_CEIL): Likewise. (INTRINSIC_CEILL): Likewise. (INTRINSIC_TRUNC): Likewise. (INTRINSIC_FMIN): Likewise. (INTRINSIC_FMAX): Likewise. (INTRINSIC_FMA): Likewise. (INTRINSIC_VA_ARG): Update intrinsic signature. (INTRINSIC_VASTART): Likewise. * lang.opt (fcheck=): Add alternate aliases for contract switches. (fcheckaction=): New option. (check_action): New Enum and EnumValue entries. (fdump-c++-spec-verbose): New option. (fdump-c++-spec=): New option. (fextern-std=): New option. (extern_stdcpp): New Enum and EnumValue entries (fpreview=): New options. (frevert=): New options. (fsave-mixins): New option. (ftransition=): Update options. * modules.cc (get_internal_fn): Replace Prot with Visibility. (build_internal_fn): Likewise. (build_dso_cdtor_fn): Likewise. (build_module_tree): Remove check for __entrypoint module. * runtime.def (P5): Define. (ARRAYBOUNDS_SLICEP): Define. (ARRAYBOUNDS_INDEXP): Define. (NEWTHROW): Define. (ADCMP2): Remove. (ARRAYCAST): Remove. (SWITCH_STRING): Remove. (SWITCH_USTRING): Remove. (SWITCH_DSTRING): Remove. (SWITCH_ERROR): Remove. * toir.cc (IRVisitor::visit): Update for new front-end interface. (IRVisitor::check_previous_goto): Remove checks for case and default statements. (IRVisitor::visit(SwitchStatement *)): Remove handling of string switch conditions. * typeinfo.cc: Include d-frontend.h. (get_typeinfo_kind): Update for new front-end interface. (make_frontend_typeinfo): Likewise. (TypeInfoVisitor::visit): Likewise. (builtin_typeinfo_p): Likewise. (get_typeinfo_decl): Likewise. (build_typeinfo): Likewise. * types.cc (valist_array_p): Likewise. (make_array_type): Likewise. (merge_aggregate_types): Likewise. (TypeVisitor::visit(TypeBasic *)): Likewise. (TypeVisitor::visit(TypeFunction *)): Likewise. (TypeVisitor::visit(TypeStruct *)): Update comment. * verstr.h: Removed. * d-frontend.h: New file. gcc/po/ChangeLog: * EXCLUDES: Remove d/dmd sources from list. gcc/testsuite/ChangeLog: * gdc.dg/Wcastresult2.d: Update test. * gdc.dg/asm1.d: Likewise. * gdc.dg/asm2.d: Likewise. * gdc.dg/asm3.d: Likewise. * gdc.dg/gdc282.d: Likewise. * gdc.dg/imports/gdc170.d: Likewise. * gdc.dg/intrinsics.d: Likewise. * gdc.dg/pr101672.d: Likewise. * gdc.dg/pr90650a.d: Likewise. * gdc.dg/pr90650b.d: Likewise. * gdc.dg/pr94777a.d: Likewise. * gdc.dg/pr95250.d: Likewise. * gdc.dg/pr96869.d: Likewise. * gdc.dg/pr98277.d: Likewise. * gdc.dg/pr98457.d: Likewise. * gdc.dg/simd1.d: Likewise. * gdc.dg/simd2a.d: Likewise. * gdc.dg/simd2b.d: Likewise. * gdc.dg/simd2c.d: Likewise. * gdc.dg/simd2d.d: Likewise. * gdc.dg/simd2e.d: Likewise. * gdc.dg/simd2f.d: Likewise. * gdc.dg/simd2g.d: Likewise. * gdc.dg/simd2h.d: Likewise. * gdc.dg/simd2i.d: Likewise. * gdc.dg/simd2j.d: Likewise. * gdc.dg/simd7951.d: Likewise. * gdc.dg/torture/gdc309.d: Likewise. * gdc.dg/torture/pr94424.d: Likewise. * gdc.dg/torture/pr94777b.d: Likewise. * lib/gdc-utils.exp (gdc-convert-args): Handle new compiler options. (gdc-convert-test): Handle CXXFLAGS, EXTRA_OBJC_SOURCES, and ARG_SETS test directives. (gdc-do-test): Only import modules in the test run directory. * gdc.dg/pr94777c.d: New test. * gdc.dg/pr96156b.d: New test. * gdc.dg/pr96157c.d: New test. * gdc.dg/simd_ctfe.d: New test. * gdc.dg/torture/simd17344.d: New test. * gdc.dg/torture/simd20052.d: New test. * gdc.dg/torture/simd6.d: New test. * gdc.dg/torture/simd7.d: New test. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime e6caaab9. * libdruntime/Makefile.am (D_EXTRA_FLAGS): Build libdruntime with -fpreview=dip1000, -fpreview=fieldwise, and -fpreview=dtorfields. (ALL_DRUNTIME_SOURCES): Add DRUNTIME_DSOURCES_STDCXX. (DRUNTIME_DSOURCES): Update list of C binding modules. (DRUNTIME_DSOURCES_STDCXX): Likewise. (DRUNTIME_DSOURCES_LINUX): Likewise. (DRUNTIME_DSOURCES_OPENBSD): Likewise. (DRUNTIME_DISOURCES): Remove __entrypoint.di. * libdruntime/Makefile.in: Regenerated. * libdruntime/__entrypoint.di: Removed. * libdruntime/gcc/deh.d (_d_isbaseof): Update signature. (_d_createTrace): Likewise. (__gdc_begin_catch): Remove reference to the exception. (_d_throw): Increment reference count of thrown object before unwind. (__gdc_personality): Chain exceptions with Throwable.chainTogether. * libdruntime/gcc/emutls.d: Update imports. * libdruntime/gcc/sections/elf.d: Update imports. (DSO.moduleGroup): Update signature. * libdruntime/gcc/sections/macho.d: Update imports. (DSO.moduleGroup): Update signature. * libdruntime/gcc/sections/pecoff.d: Update imports. (DSO.moduleGroup): Update signature. * src/MERGE: Merge upstream phobos 5ab9ad256. * src/Makefile.am (D_EXTRA_DFLAGS): Add -fpreview=dip1000 and -fpreview=dtorfields flags. (PHOBOS_DSOURCES): Update list of std modules. * src/Makefile.in: Regenerate. * testsuite/lib/libphobos.exp (libphobos-dg-test): Handle assembly compile types. (dg-test): Override. (additional_prunes): Define. (libphobos-dg-prune): Filter any additional_prunes set by tests. * testsuite/libphobos.aa/test_aa.d: Update test. * testsuite/libphobos.druntime/druntime.exp (version_flags): Add -fversion=CoreUnittest. * testsuite/libphobos.druntime_shared/druntime_shared.exp (version_flags): Add -fversion=CoreUnittest -fversion=Shared. * testsuite/libphobos.exceptions/unknown_gc.d: Update test. * testsuite/libphobos.hash/test_hash.d: Update test. * testsuite/libphobos.phobos/phobos.exp (version_flags): Add -fversion=StdUnittest * testsuite/libphobos.phobos_shared/phobos_shared.exp (version_flags): Likewise. * testsuite/libphobos.shared/host.c: Update test. * testsuite/libphobos.shared/load.d: Update test. * testsuite/libphobos.shared/load_13414.d: Update test. * testsuite/libphobos.thread/fiber_guard_page.d: Update test. * testsuite/libphobos.thread/tlsgc_sections.d: Update test. * testsuite/testsuite_flags.in: Add -fpreview=dip1000 to --gdcflags. * testsuite/libphobos.shared/link_mod_collision.d: Removed. * testsuite/libphobos.shared/load_mod_collision.d: Removed. * testsuite/libphobos.betterc/betterc.exp: New test. * testsuite/libphobos.config/config.exp: New test. * testsuite/libphobos.gc/gc.exp: New test. * testsuite/libphobos.imports/imports.exp: New test. * testsuite/libphobos.lifetime/lifetime.exp: New test. * testsuite/libphobos.unittest/unittest.exp: New test.
Diffstat (limited to 'libphobos/src/std/base64.d')
-rw-r--r--libphobos/src/std/base64.d374
1 files changed, 232 insertions, 142 deletions
diff --git a/libphobos/src/std/base64.d b/libphobos/src/std/base64.d
index 6211d10..866f700 100644
--- a/libphobos/src/std/base64.d
+++ b/libphobos/src/std/base64.d
@@ -51,15 +51,16 @@
* Copyright: Masahiro Nakagawa 2010-.
* License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
* Authors: Masahiro Nakagawa, Daniel Murphy (Single value Encoder and Decoder)
- * Source: $(PHOBOSSRC std/_base64.d)
+ * Source: $(PHOBOSSRC std/base64.d)
* Macros:
- * LREF2=<a href="#$1">$(D $2)</a>
+ * LREF2=<a href="#$1">`$2`</a>
*/
module std.base64;
-import std.exception; // enforce
-import std.range.primitives; // isInputRange, isOutputRange, isForwardRange, ElementType, hasLength
-import std.traits; // isArray
+import std.exception : enforce;
+import std.range.primitives : empty, front, isInputRange, isOutputRange,
+ isForwardRange, ElementType, hasLength, popFront, put, save;
+import std.traits : isArray;
// Make sure module header code examples work correctly.
@safe unittest
@@ -138,8 +139,8 @@ alias Base64URLNoPadding = Base64Impl!('-', '_', Base64.NoPadding);
* -----
*
* NOTE:
- * Encoded strings will not have any padding if the $(D Padding) parameter is
- * set to $(D NoPadding).
+ * Encoded strings will not have any padding if the `Padding` parameter is
+ * set to `NoPadding`.
*/
template Base64Impl(char Map62th, char Map63th, char Padding = '=')
{
@@ -205,19 +206,19 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
- * Encode $(D_PARAM source) into a $(D char[]) buffer using Base64
+ * Encode $(D_PARAM source) into a `char[]` buffer using Base64
* encoding.
*
* Params:
- * source = The $(LINK2 std_range_primitives.html#isInputRange, input
- * range) to _encode.
- * buffer = The $(D char[]) buffer to store the encoded result.
+ * source = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+ * to _encode.
+ * buffer = The `char[]` buffer to store the encoded result.
*
* Returns:
* The slice of $(D_PARAM buffer) that contains the encoded string.
*/
@trusted
- pure char[] encode(R1, R2)(in R1 source, R2 buffer) if (isArray!R1 && is(ElementType!R1 : ubyte) &&
+ pure char[] encode(R1, R2)(in R1 source, return scope R2 buffer) if (isArray!R1 && is(ElementType!R1 : ubyte) &&
is(R2 == char[]))
in
{
@@ -227,7 +228,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
{
assert(result.length == encodeLength(source.length), "The length of result is different from Base64");
}
- body
+ do
{
immutable srcLen = source.length;
if (srcLen == 0)
@@ -310,7 +311,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
// @@@BUG@@@ D's DbC can't caputre an argument of function and store the result of precondition.
//assert(result.length == encodeLength(source.length), "The length of result is different from Base64");
}
- body
+ do
{
immutable srcLen = source.length;
if (srcLen == 0)
@@ -362,7 +363,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
}
// @@@BUG@@@ Workaround for DbC problem. See comment on 'out'.
- version (unittest)
+ version (StdUnittest)
assert(
bufptr - buffer.ptr == encodeLength(srcLen),
"The length of result is different from Base64"
@@ -378,26 +379,25 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
* Encodes $(D_PARAM source) into an
- * $(LINK2 std_range_primitives.html#isOutputRange, output range) using
+ * $(REF_ALTTEXT output range, isOutputRange, std,range,primitives) using
* Base64 encoding.
*
* Params:
- * source = The $(LINK2 std_range_primitives.html#isInputRange, input
- * range) to _encode.
- * range = The $(LINK2 std_range_primitives.html#isOutputRange, output
- * range) to store the encoded result.
+ * source = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+ * to _encode.
+ * range = The $(REF_ALTTEXT output range, isOutputRange, std,range,primitives)
+ * to store the encoded result.
*
* Returns:
- * The number of times the output range's $(D put) method was invoked.
+ * The number of times the output range's `put` method was invoked.
*/
- size_t encode(R1, R2)(in R1 source, auto ref R2 range)
- if (isArray!R1 && is(ElementType!R1 : ubyte) &&
- !is(R2 == char[]) && isOutputRange!(R2, char))
+ size_t encode(E, R)(scope const(E)[] source, auto ref R range)
+ if (is(E : ubyte) && isOutputRange!(R, char) && !is(R == char[]))
out(result)
{
assert(result == encodeLength(source.length), "The number of put is different from the length of Base64");
}
- body
+ do
{
immutable srcLen = source.length;
if (srcLen == 0)
@@ -405,23 +405,23 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
immutable blocks = srcLen / 3;
immutable remain = srcLen % 3;
- auto srcptr = source.ptr;
- size_t pcount;
+ auto s = source; // copy for out contract length check
+ size_t pcount;
foreach (Unused; 0 .. blocks)
{
- immutable val = srcptr[0] << 16 | srcptr[1] << 8 | srcptr[2];
+ immutable val = s[0] << 16 | s[1] << 8 | s[2];
put(range, EncodeMap[val >> 18 ]);
put(range, EncodeMap[val >> 12 & 0x3f]);
put(range, EncodeMap[val >> 6 & 0x3f]);
put(range, EncodeMap[val & 0x3f]);
- srcptr += 3;
+ s = s[3 .. $];
pcount += 4;
}
if (remain)
{
- immutable val = srcptr[0] << 16 | (remain == 2 ? srcptr[1] << 8 : 0);
+ immutable val = s[0] << 16 | (remain == 2 ? s[1] << 8 : 0);
put(range, EncodeMap[val >> 18 ]);
put(range, EncodeMap[val >> 12 & 0x3f]);
pcount += 2;
@@ -453,22 +453,17 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
}
///
- @system unittest
+ @safe pure nothrow unittest
{
- // @system because encode for OutputRange is @system
- struct OutputRange
- {
- char[] result;
- void put(const(char) ch) @safe { result ~= ch; }
- }
+ import std.array : appender;
+ auto output = appender!string();
ubyte[] data = [0x1a, 0x2b, 0x3c, 0x4d, 0x5d, 0x6e];
// This overload of encode() returns the number of calls to the output
// range's put method.
- OutputRange output;
assert(Base64.encode(data, output) == 8);
- assert(output.result == "Gis8TV1u");
+ assert(output.data == "Gis8TV1u");
}
@@ -481,12 +476,6 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
size_t encode(R1, R2)(R1 source, auto ref R2 range)
if (!isArray!R1 && isInputRange!R1 && is(ElementType!R1 : ubyte) &&
hasLength!R1 && !is(R2 == char[]) && isOutputRange!(R2, char))
- out(result)
- {
- // @@@BUG@@@ Workaround for DbC problem.
- //assert(result == encodeLength(source.length), "The number of put is different from the length of Base64");
- }
- body
{
immutable srcLen = source.length;
if (srcLen == 0)
@@ -546,7 +535,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
}
// @@@BUG@@@ Workaround for DbC problem.
- version (unittest)
+ version (StdUnittest)
assert(
pcount == encodeLength(srcLen),
"The number of put is different from the length of Base64"
@@ -563,11 +552,11 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* buffers.
*
* Params:
- * source = The $(LINK2 std_range_primitives.html#isInputRange, input
- * range) to _encode.
+ * source = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+ * to _encode.
*
* Returns:
- * A newly-allocated $(D char[]) buffer containing the encoded string.
+ * A newly-allocated `char[]` buffer containing the encoded string.
*/
@safe
pure char[] encode(Range)(Range source) if (isArray!Range && is(ElementType!Range : ubyte))
@@ -594,12 +583,11 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
- * An $(LINK2 std_range_primitives.html#isInputRange, input range) that
+ * An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) that
* iterates over the respective Base64 encodings of a range of data items.
*
- * This range will be a $(LINK2 std_range_primitives.html#isForwardRange,
- * forward range) if the underlying data source is at least a forward
- * range.
+ * This range will be a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
+ * if the underlying data source is at least a forward range.
*
* Note: This struct is not intended to be created in user code directly;
* use the $(LREF encoder) function instead.
@@ -616,7 +604,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
this(Range range)
{
range_ = range;
- doEncoding();
+ if (!empty)
+ doEncoding();
}
@@ -645,8 +634,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Advance the range to the next chunk of encoded data.
*
* Throws:
- * $(D Base64Exception) If invoked when
- * $(LREF2 .Base64Impl.Encoder.empty, empty) returns $(D true).
+ * `Base64Exception` If invoked when
+ * $(LREF2 .Base64Impl.Encoder.empty, empty) returns `true`.
*/
void popFront()
{
@@ -671,11 +660,10 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Save the current iteration state of the range.
*
* This method is only available if the underlying range is a
- * $(LINK2 std_range_primitives.html#isForwardRange, forward
- * range).
+ * $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives).
*
* Returns:
- * A copy of $(D this).
+ * A copy of `this`.
*/
@property
typeof(this) save()
@@ -705,11 +693,11 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
- * An $(LINK2 std_range_primitives.html#isInputRange, input range) that
+ * An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) that
* iterates over the encoded bytes of the given source data.
*
- * It will be a $(LINK2 std_range_primitives.html#isForwardRange, forward
- * range) if the underlying data source is at least a forward range.
+ * It will be a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
+ * if the underlying data source is at least a forward range.
*
* Note: This struct is not intended to be created in user code directly;
* use the $(LREF encoder) function instead.
@@ -764,8 +752,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Advance to the next encoded character.
*
* Throws:
- * $(D Base64Exception) If invoked when $(LREF2 .Base64Impl.Encoder.empty.2,
- * empty) returns $(D true).
+ * `Base64Exception` If invoked when $(LREF2 .Base64Impl.Encoder.empty.2,
+ * empty) returns `true`.
*/
void popFront()
{
@@ -835,11 +823,10 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Save the current iteration state of the range.
*
* This method is only available if the underlying range is a
- * $(LINK2 std_range_primitives.html#isForwardRange, forward
- * range).
+ * $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives).
*
* Returns:
- * A copy of $(D this).
+ * A copy of `this`.
*/
@property
typeof(this) save()
@@ -853,23 +840,23 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
- * Construct an $(D Encoder) that iterates over the Base64 encoding of the
- * given $(LINK2 std_range_primitives.html#isInputRange, input range).
+ * Construct an `Encoder` that iterates over the Base64 encoding of the
+ * given $(REF_ALTTEXT input range, isInputRange, std,range,primitives).
*
* Params:
- * range = An $(LINK2 std_range_primitives.html#isInputRange, input
- * range) over the data to be encoded.
+ * range = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+ * over the data to be encoded.
*
* Returns:
- * If $(D_PARAM range) is a range of bytes, an $(D Encoder) that iterates
+ * If $(D_PARAM range) is a range of bytes, an `Encoder` that iterates
* over the bytes of the corresponding Base64 encoding.
*
- * If $(D_PARAM range) is a range of ranges of bytes, an $(D Encoder) that
+ * If $(D_PARAM range) is a range of ranges of bytes, an `Encoder` that
* iterates over the Base64 encoded strings of each element of the range.
*
- * In both cases, the returned $(D Encoder) will be a
- * $(LINK2 std_range_primitives.html#isForwardRange, forward range) if the
- * given $(D range) is at least a forward range, otherwise it will be only
+ * In both cases, the returned `Encoder` will be a
+ * $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) if the
+ * given `range` is at least a forward range, otherwise it will be only
* an input range.
*
* Example:
@@ -982,19 +969,19 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Decodes $(D_PARAM source) into the given buffer.
*
* Params:
- * source = The $(LINK2 std_range_primitives.html#isInputRange, input
- * range) to _decode.
+ * source = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+ * to _decode.
* buffer = The buffer to store decoded result.
*
* Returns:
* The slice of $(D_PARAM buffer) containing the decoded result.
*
* Throws:
- * $(D Base64Exception) if $(D_PARAM source) contains characters outside the
+ * `Base64Exception` if $(D_PARAM source) contains characters outside the
* base alphabet of the current Base64 encoding scheme.
*/
@trusted
- pure ubyte[] decode(R1, R2)(in R1 source, R2 buffer) if (isArray!R1 && is(ElementType!R1 : dchar) &&
+ pure ubyte[] decode(R1, R2)(in R1 source, return scope R2 buffer) if (isArray!R1 && is(ElementType!R1 : dchar) &&
is(R2 == ubyte[]) && isOutputRange!(R2, ubyte))
in
{
@@ -1005,7 +992,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
immutable expect = realDecodeLength(source);
assert(result.length == expect, "The length of result is different from the expected length");
}
- body
+ do
{
immutable srcLen = source.length;
if (srcLen == 0)
@@ -1085,13 +1072,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
{
assert(buffer.length >= decodeLength(source.length), "Insufficient buffer for decoding");
}
- out(result)
- {
- // @@@BUG@@@ Workaround for DbC problem.
- //immutable expect = decodeLength(source.length) - 2;
- //assert(result.length >= expect, "The length of result is smaller than expected length");
- }
- body
+ do
{
immutable srcLen = source.length;
if (srcLen == 0)
@@ -1143,8 +1124,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
}
}
- // @@@BUG@@@ Workaround for DbC problem.
- version (unittest)
+ // We need to do the check here because we have consumed the length
+ version (StdUnittest)
assert(
(bufptr - buffer.ptr) >= (decodeLength(srcLen) - 2),
"The length of result is smaller than expected length"
@@ -1159,19 +1140,19 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
* Decodes $(D_PARAM source) into a given
- * $(LINK2 std_range_primitives.html#isOutputRange, output range).
+ * $(REF_ALTTEXT output range, isOutputRange, std,range,primitives).
*
* Params:
- * source = The $(LINK2 std_range_primitives.html#isInputRange, input
- * range) to _decode.
- * range = The $(LINK2 std_range_primitives.html#isOutputRange, output
- * range) to store the decoded result.
+ * source = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+ * to _decode.
+ * range = The $(REF_ALTTEXT output range, isOutputRange, std,range,primitives)
+ * to store the decoded result.
*
* Returns:
- * The number of times the output range's $(D put) method was invoked.
+ * The number of times the output range's `put` method was invoked.
*
* Throws:
- * $(D Base64Exception) if $(D_PARAM source) contains characters outside the
+ * `Base64Exception` if $(D_PARAM source) contains characters outside the
* base alphabet of the current Base64 encoding scheme.
*/
size_t decode(R1, R2)(in R1 source, auto ref R2 range)
@@ -1182,7 +1163,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
immutable expect = realDecodeLength(source);
assert(result == expect, "The result of decode is different from the expected");
}
- body
+ do
{
immutable srcLen = source.length;
if (srcLen == 0)
@@ -1271,7 +1252,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
//immutable expect = decodeLength(source.length) - 2;
//assert(result >= expect, "The length of result is smaller than expected length");
}
- body
+ do
{
immutable srcLen = source.length;
if (srcLen == 0)
@@ -1329,7 +1310,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
}
// @@@BUG@@@ Workaround for DbC problem.
- version (unittest)
+ version (StdUnittest)
assert(
pcount >= (decodeLength(srcLen) - 2),
"The length of result is smaller than expected length"
@@ -1346,11 +1327,11 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* buffers.
*
* Params:
- * source = The $(LINK2 std_range_primitives.html#isInputRange, input
- * range) to _decode.
+ * source = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+ * to _decode.
*
* Returns:
- * A newly-allocated $(D ubyte[]) buffer containing the decoded string.
+ * A newly-allocated `ubyte[]` buffer containing the decoded string.
*/
@safe
pure ubyte[] decode(Range)(Range source) if (isArray!Range && is(ElementType!Range : dchar))
@@ -1377,12 +1358,11 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
- * An $(LINK2 std_range_primitives.html#isInputRange, input range) that
+ * An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) that
* iterates over the decoded data of a range of Base64 encodings.
*
- * This range will be a $(LINK2 std_range_primitives.html#isForwardRange,
- * forward range) if the underlying data source is at least a forward
- * range.
+ * This range will be a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
+ * if the underlying data source is at least a forward range.
*
* Note: This struct is not intended to be created in user code directly;
* use the $(LREF decoder) function instead.
@@ -1399,7 +1379,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
this(Range range)
{
range_ = range;
- doDecoding();
+ if (!empty)
+ doDecoding();
}
@@ -1428,8 +1409,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Advance to the next element in the input to be decoded.
*
* Throws:
- * $(D Base64Exception) if invoked when $(LREF2 .Base64Impl.Decoder.empty,
- * empty) returns $(D true).
+ * `Base64Exception` if invoked when $(LREF2 .Base64Impl.Decoder.empty,
+ * empty) returns `true`.
*/
void popFront()
{
@@ -1451,10 +1432,9 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Saves the current iteration state.
*
* This method is only available if the underlying range is a
- * $(LINK2 std_range_primitives.html#isForwardRange, forward
- * range).
+ * $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
*
- * Returns: A copy of $(D this).
+ * Returns: A copy of `this`.
*/
@property
typeof(this) save()
@@ -1488,6 +1468,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
while (data.length % 4 != 0)
{
range_.popFront();
+ enforce(!range_.empty, new Base64Exception("Invalid length of encoded data"));
data ~= cast(const(char)[])range_.front;
}
}
@@ -1502,12 +1483,11 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
- * An $(LINK2 std_range_primitives.html#isInputRange, input range) that
+ * An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) that
* iterates over the bytes of data decoded from a Base64 encoded string.
*
- * This range will be a $(LINK2 std_range_primitives.html#isForwardRange,
- * forward range) if the underlying data source is at least a forward
- * range.
+ * This range will be a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
+ * if the underlying data source is at least a forward range.
*
* Note: This struct is not intended to be created in user code directly;
* use the $(LREF decoder) function instead.
@@ -1562,8 +1542,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Advance to the next decoded byte.
*
* Throws:
- * $(D Base64Exception) if invoked when $(LREF2 .Base64Impl.Decoder.empty,
- * empty) returns $(D true).
+ * `Base64Exception` if invoked when $(LREF2 .Base64Impl.Decoder.empty,
+ * empty) returns `true`.
*/
void popFront()
{
@@ -1644,10 +1624,9 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Saves the current iteration state.
*
* This method is only available if the underlying range is a
- * $(LINK2 std_range_primitives.html#isForwardRange, forward
- * range).
+ * $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
*
- * Returns: A copy of $(D this).
+ * Returns: A copy of `this`.
*/
@property
typeof(this) save()
@@ -1661,31 +1640,30 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
- * Construct a $(D Decoder) that iterates over the decoding of the given
+ * Construct a `Decoder` that iterates over the decoding of the given
* Base64 encoded data.
*
* Params:
- * range = An $(LINK2 std_range_primitives.html#isInputRange, input
- * range) over the data to be decoded.
+ * range = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+ * over the data to be decoded, or a `char` array. Will not accept
+ * `wchar[]` nor `dchar[]`.
*
* Returns:
- * If $(D_PARAM range) is a range of characters, a $(D Decoder) that
+ * If $(D_PARAM range) is a range or array of `char`, a `Decoder` that
* iterates over the bytes of the corresponding Base64 decoding.
*
- * If $(D_PARAM range) is a range of ranges of characters, a $(D Decoder)
+ * If $(D_PARAM range) is a range of ranges of characters, a `Decoder`
* that iterates over the decoded strings corresponding to each element of
- * the range. In this case, the length of each subrange must be a multiple
- * of 4; the returned _decoder does not keep track of Base64 decoding
- * state across subrange boundaries.
+ * the range.
*
- * In both cases, the returned $(D Decoder) will be a
- * $(LINK2 std_range_primitives.html#isForwardRange, forward range) if the
- * given $(D range) is at least a forward range, otherwise it will be only
+ * In both cases, the returned `Decoder` will be a
+ * $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) if the
+ * given `range` is at least a forward range, otherwise it will be only
* an input range.
*
* If the input data contains characters not found in the base alphabet of
* the current Base64 encoding scheme, the returned range may throw a
- * $(D Base64Exception).
+ * `Base64Exception`.
*
* Example:
* This example shows decoding over a range of input data lines.
@@ -1696,7 +1674,6 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* }
* -----
*
- * Example:
* This example shows decoding one byte at a time.
* -----
* auto encoded = Base64.encoder(cast(ubyte[])"0123456789");
@@ -1711,6 +1688,24 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
return typeof(return)(range);
}
+ /// ditto
+ Decoder!(const(ubyte)[]) decoder()(const(char)[] range)
+ {
+ import std.string : representation;
+ return typeof(return)(range.representation);
+ }
+
+ ///
+ @safe pure unittest
+ {
+ import std.algorithm.comparison : equal;
+ string encoded =
+ "VGhvdSBzaGFsdCBuZXZlciBjb250aW51ZSBhZnRlciBhc3NlcnRpbmcgbnVsbA==";
+
+ assert(Base64.decoder(encoded)
+ .equal("Thou shalt never continue after asserting null"));
+ }
+
private:
@safe
@@ -1766,18 +1761,18 @@ class Base64Exception : Exception
}
///
-@system unittest
+@safe unittest
{
import std.exception : assertThrown;
assertThrown!Base64Exception(Base64.decode("ab|c"));
}
-
@system unittest
{
import std.algorithm.comparison : equal;
import std.algorithm.sorting : sort;
import std.conv;
+ import std.exception : assertThrown;
import std.file;
import std.stdio;
@@ -1920,7 +1915,8 @@ class Base64Exception : Exception
assert(tv["foobar"] == b.data); a.clear(); b.clear();
}
- // @@@9543@@@ These tests were disabled because they actually relied on the input range having length.
+ // https://issues.dlang.org/show_bug.cgi?id=9543
+ // These tests were disabled because they actually relied on the input range having length.
// The implementation (currently) doesn't support encoding/decoding from a length-less source.
version (none)
{ // with InputRange
@@ -2039,7 +2035,7 @@ class Base64Exception : Exception
}
// Regression control for the output range ref bug in encode.
-@system unittest
+@safe unittest
{
struct InputRange
{
@@ -2064,12 +2060,14 @@ class Base64Exception : Exception
// Verify that any existing workaround that uses & still works.
InputRange ir2;
OutputRange or2;
- assert(Base64.encode(ir2, &or2) == 8);
+ () @trusted {
+ assert(Base64.encode(ir2, &or2) == 8);
+ }();
assert(or2.result == "Gis8TV1u");
}
// Regression control for the output range ref bug in decode.
-@system unittest
+@safe unittest
{
struct InputRange
{
@@ -2094,6 +2092,98 @@ class Base64Exception : Exception
// Verify that any existing workaround that uses & still works.
InputRange ir2;
OutputRange or2;
- assert(Base64.decode(ir2, &or2) == 6);
+ () @trusted {
+ assert(Base64.decode(ir2, &or2) == 6);
+ }();
assert(or2.result == [0x1a, 0x2b, 0x3c, 0x4d, 0x5d, 0x6e]);
}
+
+// https://issues.dlang.org/show_bug.cgi?id=21679
+// https://issues.dlang.org/show_bug.cgi?id=21706
+@safe unittest
+{
+ ubyte[][] input;
+ assert(Base64.encoder(input).empty);
+ assert(Base64.decoder(input).empty);
+}
+
+@safe unittest
+{
+ struct InputRange(ubyte[] data)
+ {
+ ubyte[] impl = data;
+ bool empty() { return impl.length == 0; }
+ ubyte front() { return impl[0]; }
+ void popFront() { impl = impl[1 .. $]; }
+ size_t length() { return impl.length; }
+ }
+
+ struct OutputRange
+ {
+ ubyte[] result;
+ void put(ubyte b) { result ~= b; }
+ }
+
+ void test_encode(ubyte[] data, string result)()
+ {
+ InputRange!data ir;
+ OutputRange or;
+ assert(Base64.encode(ir, or) == result.length);
+ assert(or.result == result);
+ }
+
+ void test_decode(ubyte[] data, string result)()
+ {
+ InputRange!data ir;
+ OutputRange or;
+ assert(Base64.decode(ir, or) == result.length);
+ assert(or.result == result);
+ }
+
+ test_encode!([], "");
+ test_encode!(['x'], "eA==");
+ test_encode!([123, 45], "ey0=");
+
+ test_decode!([], "");
+ test_decode!(['e', 'A', '=', '='], "x");
+ test_decode!(['e', 'y', '0', '='], "{-");
+}
+
+@system unittest
+{
+ // checking forward range
+ auto item = Base64.decoder(Base64.encoder(cast(ubyte[]) "foobar"));
+ auto copy = item.save();
+ item.popFront();
+ assert(item.front == 'o');
+ assert(copy.front == 'f');
+}
+
+@system unittest
+{
+ // checking invalid dchar
+ dchar[] c = cast(dchar[]) "รครครครค";
+
+ import std.exception : assertThrown;
+ assertThrown!Base64Exception(Base64.decode(c));
+}
+
+@safe unittest
+{
+ import std.array : array;
+
+ char[][] input = [['e', 'y'], ['0', '=']];
+ assert(Base64.decoder(input).array == [[123, 45]]);
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=21707
+@safe unittest
+{
+ import std.exception : assertThrown;
+
+ char[][] t1 = [[ 'Z', 'g', '=' ]];
+ assertThrown!Base64Exception(Base64.decoder(t1));
+
+ char[][] t2 = [[ 'e', 'y', '0' ], ['=', '=']];
+ assertThrown!Base64Exception(Base64.decoder(t2));
+}