From 0db187e7aef746c7abd079110172508598d9b672 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 13:20:30 +0000 Subject: [PATCH] Deploy to GitHub pages --- .circleci/config.yml | 33 + .circleci/run.sh | 105 ++ index.html | 35 + lu.array.html | 42 + lu.array.uniqueKey.html | 66 + lu.common.FileExistsException.filename.html | 35 + lu.common.FileExistsException.html | 36 + lu.common.FileExistsException.this.1.html | 35 + lu.common.FileExistsException.this.2.html | 35 + lu.common.FileExistsException.this.html | 1 + ...ommon.FileTypeMismatchException.attrs.html | 35 + ...on.FileTypeMismatchException.filename.html | 35 + lu.common.FileTypeMismatchException.html | 38 + ...mmon.FileTypeMismatchException.this.1.html | 35 + ...mmon.FileTypeMismatchException.this.2.html | 35 + lu.common.FileTypeMismatchException.this.html | 1 + lu.common.Next.html | 35 + lu.common.ReturnValueException.command.html | 35 + lu.common.ReturnValueException.html | 36 + lu.common.ReturnValueException.retval.html | 35 + lu.common.ReturnValueException.this.1.html | 35 + lu.common.ReturnValueException.this.2.html | 35 + lu.common.ReturnValueException.this.3.html | 35 + lu.common.ReturnValueException.this.html | 1 + lu.common.html | 37 + lu.common.sharedDomains.html | 86 + lu.container.Buffer.buf.1.html | 35 + lu.container.Buffer.buf.2.html | 35 + lu.container.Buffer.buf.html | 1 + lu.container.Buffer.bufferSize.1.html | 35 + lu.container.Buffer.bufferSize.2.html | 35 + lu.container.Buffer.bufferSize.html | 1 + lu.container.Buffer.clear.html | 35 + lu.container.Buffer.empty.html | 37 + lu.container.Buffer.end.html | 35 + lu.container.Buffer.front.html | 35 + lu.container.Buffer.growthFactor.html | 35 + lu.container.Buffer.html | 152 ++ lu.container.Buffer.length.html | 36 + lu.container.Buffer.opOpAssign.html | 35 + lu.container.Buffer.popFront.html | 35 + lu.container.Buffer.pos.html | 35 + lu.container.Buffer.put.1.html | 35 + lu.container.Buffer.put.2.html | 35 + lu.container.Buffer.put.html | 1 + lu.container.Buffer.reserve.html | 36 + lu.container.Buffer.reset.html | 36 + lu.container.CircularBuffer.buf.1.html | 35 + lu.container.CircularBuffer.buf.2.html | 35 + lu.container.CircularBuffer.buf.html | 1 + lu.container.CircularBuffer.caughtUp.html | 36 + lu.container.CircularBuffer.clear.html | 35 + lu.container.CircularBuffer.dup.html | 35 + lu.container.CircularBuffer.empty.html | 37 + lu.container.CircularBuffer.front.html | 35 + lu.container.CircularBuffer.head.html | 35 + lu.container.CircularBuffer.html | 137 ++ lu.container.CircularBuffer.initialised.html | 35 + lu.container.CircularBuffer.opOpAssign.html | 35 + lu.container.CircularBuffer.popFront.html | 35 + lu.container.CircularBuffer.put.html | 36 + lu.container.CircularBuffer.reset.html | 35 + lu.container.CircularBuffer.resize.html | 35 + lu.container.CircularBuffer.save.html | 35 + lu.container.CircularBuffer.size.html | 35 + lu.container.CircularBuffer.tail.html | 35 + lu.container.MutexedAA.aa.html | 35 + lu.container.MutexedAA.clear.html | 43 + lu.container.MutexedAA.get.html | 47 + lu.container.MutexedAA.has.html | 39 + lu.container.MutexedAA.html | 309 ++++ lu.container.MutexedAA.isReady.html | 36 + lu.container.MutexedAA.keys.html | 43 + lu.container.MutexedAA.length.html | 41 + lu.container.MutexedAA.mutex.html | 35 + lu.container.MutexedAA.opEquals.1.html | 50 + lu.container.MutexedAA.opEquals.2.html | 47 + lu.container.MutexedAA.opEquals.html | 1 + lu.container.MutexedAA.opIndex.html | 41 + lu.container.MutexedAA.opIndexAssign.html | 39 + lu.container.MutexedAA.opIndexOpAssign.html | 43 + lu.container.MutexedAA.opIndexUnary.html | 39 + lu.container.MutexedAA.rehash.html | 40 + lu.container.MutexedAA.remove.html | 42 + lu.container.MutexedAA.require.html | 41 + lu.container.MutexedAA.setup.html | 36 + lu.container.MutexedAA.uniqueKey.html | 44 + lu.container.MutexedAA.update.html | 50 + lu.container.MutexedAA.values.html | 43 + ...ainer.RehashingAA._lengthAtLastRehash.html | 36 + ...r.RehashingAA._newKeysSinceLastRehash.html | 35 + lu.container.RehashingAA._numRehashes.html | 35 + lu.container.RehashingAA.aa.html | 35 + lu.container.RehashingAA.aaOf.html | 35 + lu.container.RehashingAA.clear.html | 35 + lu.container.RehashingAA.dup.html | 35 + lu.container.RehashingAA.html | 68 + lu.container.RehashingAA.length.html | 35 + lu.container.RehashingAA.maybeRehash.html | 36 + ...er.RehashingAA.minimumNeededForRehash.html | 35 + ...er.RehashingAA.newKeysSinceLastRehash.html | 35 + lu.container.RehashingAA.numRehashes.html | 35 + lu.container.RehashingAA.onRehashDg.html | 35 + lu.container.RehashingAA.opAssign.html | 35 + lu.container.RehashingAA.opBinaryRight.html | 36 + lu.container.RehashingAA.opCast.html | 35 + lu.container.RehashingAA.opIndexAssign.html | 36 + lu.container.RehashingAA.rehash.html | 36 + ...RehashingAA.rehashThresholdMultiplier.html | 37 + lu.container.RehashingAA.remove.html | 36 + lu.container.RehashingAA.this.html | 35 + lu.container.html | 128 ++ lu.conv.Enum.fromString.html | 48 + lu.conv.Enum.html | 63 + lu.conv.Enum.toString.html | 42 + lu.conv.enumToString.html | 48 + lu.conv.html | 46 + lu.conv.numFromHex.html | 36 + lu.conv.rgbFromHex.html | 66 + lu.conv.toAlpha.html | 79 + lu.conv.toAlphaInto.html | 92 + lu.deltastrings.formatDeltaInto.html | 223 +++ lu.deltastrings.html | 82 + lu.html | 45 + lu.json.JSONStorage.KeyOrderStrategy.html | 38 + lu.json.JSONStorage.html | 63 + lu.json.JSONStorage.load.html | 39 + lu.json.JSONStorage.reset.html | 36 + lu.json.JSONStorage.save.html | 38 + lu.json.JSONStorage.serialiseInto.1.html | 38 + lu.json.JSONStorage.serialiseInto.2.html | 138 ++ lu.json.JSONStorage.serialiseInto.html | 1 + lu.json.JSONStorage.storage.html | 35 + lu.json.html | 76 + lu.json.populateFromJSON.html | 161 ++ lu.meld.MeldingStrategy.html | 39 + lu.meld.Unmeldable.html | 35 + lu.meld.html | 69 + lu.meld.meldInto.1.html | 352 ++++ lu.meld.meldInto.2.html | 71 + lu.meld.meldInto.3.html | 76 + lu.meld.meldInto.html | 1 + lu.numeric.getMultipleOf.html | 68 + lu.numeric.html | 39 + lu.objmanip.SetMemberException.html | 36 + ...jmanip.SetMemberException.memberToSet.html | 35 + lu.objmanip.SetMemberException.this.1.html | 35 + lu.objmanip.SetMemberException.this.2.html | 35 + lu.objmanip.SetMemberException.this.html | 1 + lu.objmanip.SetMemberException.typeName.html | 35 + ...bjmanip.SetMemberException.valueToSet.html | 35 + lu.objmanip.html | 64 + lu.objmanip.pruneAA.html | 118 ++ lu.objmanip.replaceMembers.html | 119 ++ lu.objmanip.setMemberByName.1.html | 239 +++ lu.objmanip.setMemberByName.2.html | 80 + lu.objmanip.setMemberByName.html | 1 + lu.semver.LuSemVer.html | 35 + lu.semver.LuSemVerPrerelease.html | 35 + lu.semver.html | 36 + ...erialisation.DeserialisationException.html | 36 + ...isation.DeserialisationException.this.html | 35 + ...sation.SerialisationUDAs.arrayPattern.html | 36 + ...on.SerialisationUDAs.escapedSeparator.html | 35 + lu.serialisation.SerialisationUDAs.html | 37 + ...alisation.SerialisationUDAs.separator.html | 35 + ...tion.SerialisationUDAs.unserialisable.html | 35 + lu.serialisation.deserialise.html | 290 +++ lu.serialisation.html | 90 + lu.serialisation.justifiedEntryValueText.html | 142 ++ lu.serialisation.serialise.1.html | 52 + lu.serialisation.serialise.2.html | 162 ++ lu.serialisation.serialise.html | 1 + lu.serialisation.serialiseArrayImpl.html | 38 + lu.serialisation.splitEntryValue.html | 64 + lu.string.AdvanceException.haystack.html | 35 + lu.string.AdvanceException.html | 35 + lu.string.AdvanceException.needle.html | 35 + lu.string.AdvanceException.this.html | 35 + lu.string.AdvanceExceptionImpl._haystack.html | 35 + lu.string.AdvanceExceptionImpl._needle.html | 35 + lu.string.AdvanceExceptionImpl.haystack.html | 35 + lu.string.AdvanceExceptionImpl.html | 36 + lu.string.AdvanceExceptionImpl.needle.html | 35 + lu.string.AdvanceExceptionImpl.this.1.html | 35 + lu.string.AdvanceExceptionImpl.this.2.html | 35 + lu.string.AdvanceExceptionImpl.this.html | 1 + lu.string.NomException.html | 35 + lu.string.NomExceptionImpl.html | 35 + lu.string.SplitResults.html | 35 + lu.string.advancePast.1.html | 238 +++ lu.string.advancePast.2.html | 38 + lu.string.advancePast.html | 1 + lu.string.beginsWithOneOf.html | 52 + lu.string.decode64.html | 45 + lu.string.encode64.html | 45 + lu.string.escapeControlCharacters.html | 62 + lu.string.html | 83 + lu.string.indent.html | 73 + lu.string.indentInto.html | 70 + lu.string.nom.html | 35 + lu.string.plurality.html | 47 + lu.string.removeControlCharacters.html | 60 + lu.string.splitInto.1.html | 107 ++ lu.string.splitInto.2.html | 181 ++ lu.string.splitInto.html | 1 + lu.string.splitLineAtPosition.html | 87 + lu.string.splitWithQuotes.html | 123 ++ lu.string.stripSuffix.html | 41 + lu.string.stripped.1.html | 69 + lu.string.stripped.2.html | 88 + lu.string.stripped.html | 1 + lu.string.strippedLeft.1.html | 67 + lu.string.strippedLeft.2.html | 77 + lu.string.strippedLeft.html | 1 + lu.string.strippedRight.1.html | 67 + lu.string.strippedRight.2.html | 77 + lu.string.strippedRight.html | 1 + lu.string.tabs.html | 59 + lu.string.unenclosed.html | 37 + lu.string.unquoted.html | 44 + lu.string.unsinglequoted.html | 44 + lu.traits.CategoryName.fqn.html | 35 + lu.traits.CategoryName.html | 101 ++ lu.traits.CategoryName.name.html | 35 + lu.traits.MixinConstraints.html | 89 + lu.traits.MixinScope.html | 35 + lu.traits.TakesParams.1.html | 61 + lu.traits.TakesParams.2.html | 70 + lu.traits.TakesParams.html | 1 + lu.traits.UnqualArray.1.html | 51 + lu.traits.UnqualArray.2.html | 51 + lu.traits.UnqualArray.3.html | 51 + lu.traits.UnqualArray.html | 1 + lu.traits.getSymbolsByUDA.html | 38 + lu.traits.getSymbolsByUDAImpl.html | 35 + lu.traits.html | 47 + lu.traits.isMerelyArray.html | 41 + lu.traits.isMutableArrayOfImmutables.html | 42 + lu.traits.isSerialisable.html | 52 + lu.traits.isStruct.html | 35 + lu.traits.isTrulyString.html | 41 + lu.traits.stringofParams.html | 52 + lu.typecons.UnderscoreOpDispatcher.html | 89 + ...s.UnderscoreOpDispatcher.opDispatch.1.html | 35 + ...s.UnderscoreOpDispatcher.opDispatch.2.html | 35 + ...ons.UnderscoreOpDispatcher.opDispatch.html | 1 + lu.typecons.html | 36 + lu.uda.CannotContainComments.html | 36 + lu.uda.Hidden.html | 36 + lu.uda.Quoted.html | 35 + lu.uda.Separator.html | 36 + lu.uda.Separator.token.html | 35 + lu.uda.Unserialisable.html | 35 + lu.uda.html | 38 + script.js | 180 ++ search-docs.html | 26 + search-docs.js | 421 +++++ search-results.html | 228 +++ style.css | 1593 +++++++++++++++++ 260 files changed, 15269 insertions(+) create mode 100644 .circleci/config.yml create mode 100755 .circleci/run.sh create mode 100644 index.html create mode 100644 lu.array.html create mode 100644 lu.array.uniqueKey.html create mode 100644 lu.common.FileExistsException.filename.html create mode 100644 lu.common.FileExistsException.html create mode 100644 lu.common.FileExistsException.this.1.html create mode 100644 lu.common.FileExistsException.this.2.html create mode 100644 lu.common.FileExistsException.this.html create mode 100644 lu.common.FileTypeMismatchException.attrs.html create mode 100644 lu.common.FileTypeMismatchException.filename.html create mode 100644 lu.common.FileTypeMismatchException.html create mode 100644 lu.common.FileTypeMismatchException.this.1.html create mode 100644 lu.common.FileTypeMismatchException.this.2.html create mode 100644 lu.common.FileTypeMismatchException.this.html create mode 100644 lu.common.Next.html create mode 100644 lu.common.ReturnValueException.command.html create mode 100644 lu.common.ReturnValueException.html create mode 100644 lu.common.ReturnValueException.retval.html create mode 100644 lu.common.ReturnValueException.this.1.html create mode 100644 lu.common.ReturnValueException.this.2.html create mode 100644 lu.common.ReturnValueException.this.3.html create mode 100644 lu.common.ReturnValueException.this.html create mode 100644 lu.common.html create mode 100644 lu.common.sharedDomains.html create mode 100644 lu.container.Buffer.buf.1.html create mode 100644 lu.container.Buffer.buf.2.html create mode 100644 lu.container.Buffer.buf.html create mode 100644 lu.container.Buffer.bufferSize.1.html create mode 100644 lu.container.Buffer.bufferSize.2.html create mode 100644 lu.container.Buffer.bufferSize.html create mode 100644 lu.container.Buffer.clear.html create mode 100644 lu.container.Buffer.empty.html create mode 100644 lu.container.Buffer.end.html create mode 100644 lu.container.Buffer.front.html create mode 100644 lu.container.Buffer.growthFactor.html create mode 100644 lu.container.Buffer.html create mode 100644 lu.container.Buffer.length.html create mode 100644 lu.container.Buffer.opOpAssign.html create mode 100644 lu.container.Buffer.popFront.html create mode 100644 lu.container.Buffer.pos.html create mode 100644 lu.container.Buffer.put.1.html create mode 100644 lu.container.Buffer.put.2.html create mode 100644 lu.container.Buffer.put.html create mode 100644 lu.container.Buffer.reserve.html create mode 100644 lu.container.Buffer.reset.html create mode 100644 lu.container.CircularBuffer.buf.1.html create mode 100644 lu.container.CircularBuffer.buf.2.html create mode 100644 lu.container.CircularBuffer.buf.html create mode 100644 lu.container.CircularBuffer.caughtUp.html create mode 100644 lu.container.CircularBuffer.clear.html create mode 100644 lu.container.CircularBuffer.dup.html create mode 100644 lu.container.CircularBuffer.empty.html create mode 100644 lu.container.CircularBuffer.front.html create mode 100644 lu.container.CircularBuffer.head.html create mode 100644 lu.container.CircularBuffer.html create mode 100644 lu.container.CircularBuffer.initialised.html create mode 100644 lu.container.CircularBuffer.opOpAssign.html create mode 100644 lu.container.CircularBuffer.popFront.html create mode 100644 lu.container.CircularBuffer.put.html create mode 100644 lu.container.CircularBuffer.reset.html create mode 100644 lu.container.CircularBuffer.resize.html create mode 100644 lu.container.CircularBuffer.save.html create mode 100644 lu.container.CircularBuffer.size.html create mode 100644 lu.container.CircularBuffer.tail.html create mode 100644 lu.container.MutexedAA.aa.html create mode 100644 lu.container.MutexedAA.clear.html create mode 100644 lu.container.MutexedAA.get.html create mode 100644 lu.container.MutexedAA.has.html create mode 100644 lu.container.MutexedAA.html create mode 100644 lu.container.MutexedAA.isReady.html create mode 100644 lu.container.MutexedAA.keys.html create mode 100644 lu.container.MutexedAA.length.html create mode 100644 lu.container.MutexedAA.mutex.html create mode 100644 lu.container.MutexedAA.opEquals.1.html create mode 100644 lu.container.MutexedAA.opEquals.2.html create mode 100644 lu.container.MutexedAA.opEquals.html create mode 100644 lu.container.MutexedAA.opIndex.html create mode 100644 lu.container.MutexedAA.opIndexAssign.html create mode 100644 lu.container.MutexedAA.opIndexOpAssign.html create mode 100644 lu.container.MutexedAA.opIndexUnary.html create mode 100644 lu.container.MutexedAA.rehash.html create mode 100644 lu.container.MutexedAA.remove.html create mode 100644 lu.container.MutexedAA.require.html create mode 100644 lu.container.MutexedAA.setup.html create mode 100644 lu.container.MutexedAA.uniqueKey.html create mode 100644 lu.container.MutexedAA.update.html create mode 100644 lu.container.MutexedAA.values.html create mode 100644 lu.container.RehashingAA._lengthAtLastRehash.html create mode 100644 lu.container.RehashingAA._newKeysSinceLastRehash.html create mode 100644 lu.container.RehashingAA._numRehashes.html create mode 100644 lu.container.RehashingAA.aa.html create mode 100644 lu.container.RehashingAA.aaOf.html create mode 100644 lu.container.RehashingAA.clear.html create mode 100644 lu.container.RehashingAA.dup.html create mode 100644 lu.container.RehashingAA.html create mode 100644 lu.container.RehashingAA.length.html create mode 100644 lu.container.RehashingAA.maybeRehash.html create mode 100644 lu.container.RehashingAA.minimumNeededForRehash.html create mode 100644 lu.container.RehashingAA.newKeysSinceLastRehash.html create mode 100644 lu.container.RehashingAA.numRehashes.html create mode 100644 lu.container.RehashingAA.onRehashDg.html create mode 100644 lu.container.RehashingAA.opAssign.html create mode 100644 lu.container.RehashingAA.opBinaryRight.html create mode 100644 lu.container.RehashingAA.opCast.html create mode 100644 lu.container.RehashingAA.opIndexAssign.html create mode 100644 lu.container.RehashingAA.rehash.html create mode 100644 lu.container.RehashingAA.rehashThresholdMultiplier.html create mode 100644 lu.container.RehashingAA.remove.html create mode 100644 lu.container.RehashingAA.this.html create mode 100644 lu.container.html create mode 100644 lu.conv.Enum.fromString.html create mode 100644 lu.conv.Enum.html create mode 100644 lu.conv.Enum.toString.html create mode 100644 lu.conv.enumToString.html create mode 100644 lu.conv.html create mode 100644 lu.conv.numFromHex.html create mode 100644 lu.conv.rgbFromHex.html create mode 100644 lu.conv.toAlpha.html create mode 100644 lu.conv.toAlphaInto.html create mode 100644 lu.deltastrings.formatDeltaInto.html create mode 100644 lu.deltastrings.html create mode 100644 lu.html create mode 100644 lu.json.JSONStorage.KeyOrderStrategy.html create mode 100644 lu.json.JSONStorage.html create mode 100644 lu.json.JSONStorage.load.html create mode 100644 lu.json.JSONStorage.reset.html create mode 100644 lu.json.JSONStorage.save.html create mode 100644 lu.json.JSONStorage.serialiseInto.1.html create mode 100644 lu.json.JSONStorage.serialiseInto.2.html create mode 100644 lu.json.JSONStorage.serialiseInto.html create mode 100644 lu.json.JSONStorage.storage.html create mode 100644 lu.json.html create mode 100644 lu.json.populateFromJSON.html create mode 100644 lu.meld.MeldingStrategy.html create mode 100644 lu.meld.Unmeldable.html create mode 100644 lu.meld.html create mode 100644 lu.meld.meldInto.1.html create mode 100644 lu.meld.meldInto.2.html create mode 100644 lu.meld.meldInto.3.html create mode 100644 lu.meld.meldInto.html create mode 100644 lu.numeric.getMultipleOf.html create mode 100644 lu.numeric.html create mode 100644 lu.objmanip.SetMemberException.html create mode 100644 lu.objmanip.SetMemberException.memberToSet.html create mode 100644 lu.objmanip.SetMemberException.this.1.html create mode 100644 lu.objmanip.SetMemberException.this.2.html create mode 100644 lu.objmanip.SetMemberException.this.html create mode 100644 lu.objmanip.SetMemberException.typeName.html create mode 100644 lu.objmanip.SetMemberException.valueToSet.html create mode 100644 lu.objmanip.html create mode 100644 lu.objmanip.pruneAA.html create mode 100644 lu.objmanip.replaceMembers.html create mode 100644 lu.objmanip.setMemberByName.1.html create mode 100644 lu.objmanip.setMemberByName.2.html create mode 100644 lu.objmanip.setMemberByName.html create mode 100644 lu.semver.LuSemVer.html create mode 100644 lu.semver.LuSemVerPrerelease.html create mode 100644 lu.semver.html create mode 100644 lu.serialisation.DeserialisationException.html create mode 100644 lu.serialisation.DeserialisationException.this.html create mode 100644 lu.serialisation.SerialisationUDAs.arrayPattern.html create mode 100644 lu.serialisation.SerialisationUDAs.escapedSeparator.html create mode 100644 lu.serialisation.SerialisationUDAs.html create mode 100644 lu.serialisation.SerialisationUDAs.separator.html create mode 100644 lu.serialisation.SerialisationUDAs.unserialisable.html create mode 100644 lu.serialisation.deserialise.html create mode 100644 lu.serialisation.html create mode 100644 lu.serialisation.justifiedEntryValueText.html create mode 100644 lu.serialisation.serialise.1.html create mode 100644 lu.serialisation.serialise.2.html create mode 100644 lu.serialisation.serialise.html create mode 100644 lu.serialisation.serialiseArrayImpl.html create mode 100644 lu.serialisation.splitEntryValue.html create mode 100644 lu.string.AdvanceException.haystack.html create mode 100644 lu.string.AdvanceException.html create mode 100644 lu.string.AdvanceException.needle.html create mode 100644 lu.string.AdvanceException.this.html create mode 100644 lu.string.AdvanceExceptionImpl._haystack.html create mode 100644 lu.string.AdvanceExceptionImpl._needle.html create mode 100644 lu.string.AdvanceExceptionImpl.haystack.html create mode 100644 lu.string.AdvanceExceptionImpl.html create mode 100644 lu.string.AdvanceExceptionImpl.needle.html create mode 100644 lu.string.AdvanceExceptionImpl.this.1.html create mode 100644 lu.string.AdvanceExceptionImpl.this.2.html create mode 100644 lu.string.AdvanceExceptionImpl.this.html create mode 100644 lu.string.NomException.html create mode 100644 lu.string.NomExceptionImpl.html create mode 100644 lu.string.SplitResults.html create mode 100644 lu.string.advancePast.1.html create mode 100644 lu.string.advancePast.2.html create mode 100644 lu.string.advancePast.html create mode 100644 lu.string.beginsWithOneOf.html create mode 100644 lu.string.decode64.html create mode 100644 lu.string.encode64.html create mode 100644 lu.string.escapeControlCharacters.html create mode 100644 lu.string.html create mode 100644 lu.string.indent.html create mode 100644 lu.string.indentInto.html create mode 100644 lu.string.nom.html create mode 100644 lu.string.plurality.html create mode 100644 lu.string.removeControlCharacters.html create mode 100644 lu.string.splitInto.1.html create mode 100644 lu.string.splitInto.2.html create mode 100644 lu.string.splitInto.html create mode 100644 lu.string.splitLineAtPosition.html create mode 100644 lu.string.splitWithQuotes.html create mode 100644 lu.string.stripSuffix.html create mode 100644 lu.string.stripped.1.html create mode 100644 lu.string.stripped.2.html create mode 100644 lu.string.stripped.html create mode 100644 lu.string.strippedLeft.1.html create mode 100644 lu.string.strippedLeft.2.html create mode 100644 lu.string.strippedLeft.html create mode 100644 lu.string.strippedRight.1.html create mode 100644 lu.string.strippedRight.2.html create mode 100644 lu.string.strippedRight.html create mode 100644 lu.string.tabs.html create mode 100644 lu.string.unenclosed.html create mode 100644 lu.string.unquoted.html create mode 100644 lu.string.unsinglequoted.html create mode 100644 lu.traits.CategoryName.fqn.html create mode 100644 lu.traits.CategoryName.html create mode 100644 lu.traits.CategoryName.name.html create mode 100644 lu.traits.MixinConstraints.html create mode 100644 lu.traits.MixinScope.html create mode 100644 lu.traits.TakesParams.1.html create mode 100644 lu.traits.TakesParams.2.html create mode 100644 lu.traits.TakesParams.html create mode 100644 lu.traits.UnqualArray.1.html create mode 100644 lu.traits.UnqualArray.2.html create mode 100644 lu.traits.UnqualArray.3.html create mode 100644 lu.traits.UnqualArray.html create mode 100644 lu.traits.getSymbolsByUDA.html create mode 100644 lu.traits.getSymbolsByUDAImpl.html create mode 100644 lu.traits.html create mode 100644 lu.traits.isMerelyArray.html create mode 100644 lu.traits.isMutableArrayOfImmutables.html create mode 100644 lu.traits.isSerialisable.html create mode 100644 lu.traits.isStruct.html create mode 100644 lu.traits.isTrulyString.html create mode 100644 lu.traits.stringofParams.html create mode 100644 lu.typecons.UnderscoreOpDispatcher.html create mode 100644 lu.typecons.UnderscoreOpDispatcher.opDispatch.1.html create mode 100644 lu.typecons.UnderscoreOpDispatcher.opDispatch.2.html create mode 100644 lu.typecons.UnderscoreOpDispatcher.opDispatch.html create mode 100644 lu.typecons.html create mode 100644 lu.uda.CannotContainComments.html create mode 100644 lu.uda.Hidden.html create mode 100644 lu.uda.Quoted.html create mode 100644 lu.uda.Separator.html create mode 100644 lu.uda.Separator.token.html create mode 100644 lu.uda.Unserialisable.html create mode 100644 lu.uda.html create mode 100644 script.js create mode 100644 search-docs.html create mode 100644 search-docs.js create mode 100644 search-results.html create mode 100644 style.css diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..4e857566 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,33 @@ +version: 2 + +jobs: + build: + docker: + - image: cimg/base:2021.11 + steps: + - checkout + - run: + name: Install compilers + command: ./.circleci/run.sh install-deps + - run: + name: Build and test (dmd) + command: ./.circleci/run.sh build-dmd + - run: + name: Build and test (ldc) + command: ./.circleci/run.sh build-ldc + #- store_artifacts: + #path: ./artifacts + +workflows: + version: 2 + build_and_test: + jobs: + - build: + filters: + branches: + ignore: + - /appveyor-.*/ + - /travis-.*/ + - gh-pages + - /dustmite-.*/ + - /github-.*/ diff --git a/.circleci/run.sh b/.circleci/run.sh new file mode 100755 index 00000000..94abc0c5 --- /dev/null +++ b/.circleci/run.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +set -uexo pipefail + +#DMD_VERSION="2.098.0" +#LDC_VERSION="1.28.0" +CURL_USER_AGENT="CirleCI $(curl --version | head -n 1)" + +update_repos() { + sudo apt-get update +} + +install_deps() { + sudo apt-get install g++-multilib + + # required for: "core.time.TimeException@std/datetime/timezone.d(2073): Directory /usr/share/zoneinfo/ does not exist." + #sudo apt-get install --reinstall tzdata gdb +} + +download_install_script() { + for i in {0..4}; do + if curl -fsS -A "$CURL_USER_AGENT" --max-time 5 https://dlang.org/install.sh -O || + curl -fsS -A "$CURL_USER_AGENT" --max-time 5 https://nightlies.dlang.org/install.sh -O ; then + break + elif [[ "$i" -ge 4 ]]; then + sleep $((1 << i)) + else + echo 'Failed to download install script' 1>&2 + exit 1 + fi + done +} + +install_and_activate_compiler() { + local compiler compiler_version_ext compiler_build + + compiler=$1 + [[ $# -gt 1 ]] && compiler_version_ext="-$2" || compiler_version_ext="" + compiler_build="${compiler}${compiler_version_ext}" + + source "$(CURL_USER_AGENT=\"$CURL_USER_AGENT\" bash install.sh $compiler_build --activate)" +} + +use_lu_master() { + if [[ ! -d lu ]]; then + git clone https://github.com/zorael/lu.git + dub add-local lu + fi +} + +build() { + local compiler_switch arch_switch + + compiler_switch="--compiler=$1" + arch_switch="--arch=$2" + + shift 2 # shift away compiler and arch + # "$@" is now any extra parameters passed to build + + dub clean + + time dub test $compiler_switch $arch_switch "$@" + time dub build $compiler_switch $arch_switch "$@" --nodeps -b debug + time dub build $compiler_switch $arch_switch "$@" --nodeps -b plain + time dub build $compiler_switch $arch_switch "$@" --nodeps -b release +} + +# execution start + +case $1 in + install-deps) + update_repos + install_deps + download_install_script + ;; + + build-dmd) + install_and_activate_compiler dmd #"$DMD_VERSION" + dmd --version + dub --version + + #use_lu_master + + #time build dmd x86 # no 32-bit libs? + time build dmd x86_64 + ;; + + build-ldc) + install_and_activate_compiler ldc #"$LDC_VERSION" + ldc2 --version + dub --version + + #use_lu_master + + #time build ldc2 x86 # no 32-bit libs? + time build ldc2 x86_64 + ;; + + *) + echo "Unknown command: $1"; + exit 1; + ;; +esac + +exit 0 diff --git a/index.html b/index.html new file mode 100644 index 00000000..2aa4426c --- /dev/null +++ b/index.html @@ -0,0 +1,35 @@ + + + + index (index) + + + + + + + + + + +
+
+

index

Modules

lu
module lu

lu is a general purpose library, doing a little bit of everything.

+ +
+ + + \ No newline at end of file diff --git a/lu.array.html b/lu.array.html new file mode 100644 index 00000000..32e3bddd --- /dev/null +++ b/lu.array.html @@ -0,0 +1,42 @@ + + + + lu.array (lu.array) + + + + + + + + + + +
+
+

lu.array

Simple array utilities.

Members

Functions

uniqueKey
auto uniqueKey(AA aa, K min, K max, V value)

Returns a unique key for the passed associative array. Reserves the key by + assigning it a value.

Examples

string[int] aa;
+
+immutable key = aa.uniqueKey;
+
+assert(key > 0);
+assert(key in aa);
+assert(aa[key] == string.init);

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.array.uniqueKey.html b/lu.array.uniqueKey.html new file mode 100644 index 00000000..ec9c04b3 --- /dev/null +++ b/lu.array.uniqueKey.html @@ -0,0 +1,66 @@ + + + + uniqueKey (lu.array.uniqueKey) + + + + + + + + + + +
+
+

uniqueKey

Returns a unique key for the passed associative array. Reserves the key by + assigning it a value.

Note: This function will end up in an endless loop if a narrow range of indexes + is supplied and the associative array already contains values for all of them.

uniqueKey
(
AA : V[K]
V
K
)
(
ref AA aa
,
K min = 1
,
K max = K.max
,
V value = V.init
)
if (
isIntegral!K
)

Parameters

aa AA

Associative array to get a unique key for.

min K

Optional minimum key value; defaults to 1.

max K

Optional maximum key value; defaults to K.max, where K is the + key type of the passed associative array.

value V

Optional value to assign to the key; defaults to V.init, where + V is the value type of the passed associative array.

Return Value

Type: auto

A unique key for the passed associative array. There will exist an array + entry for the key, with the value value.

Examples

string[int] aa;
+immutable key = aa.uniqueKey;
+assert(key > 0);
+assert(key in aa);
+assert(aa[key] == string.init);
import std.conv : to;
+
+{
+    string[int] aa;
+    immutable key = aa.uniqueKey;
+    assert(key in aa);
+}
+{
+    long[long] aa;
+    immutable key = aa.uniqueKey;
+    assert(key in aa);
+}
+{
+    shared bool[int] aa;
+    immutable key = aa.uniqueKey;
+    assert(key in aa);
+}
+{
+    int[int] aa;
+    immutable key = aa.uniqueKey(5, 6, 42);
+    assert(key == 5);
+    assert((aa[5] == 42), aa[5].to!string);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.common.FileExistsException.filename.html b/lu.common.FileExistsException.filename.html new file mode 100644 index 00000000..0ca09ff8 --- /dev/null +++ b/lu.common.FileExistsException.filename.html @@ -0,0 +1,35 @@ + + + + FileExistsException.filename (lu.common.FileExistsException.filename) + + + + + + + + + + +
+
+

FileExistsException.filename

The name of the file.

class FileExistsException
string filename;
+ +
+ + + \ No newline at end of file diff --git a/lu.common.FileExistsException.html b/lu.common.FileExistsException.html new file mode 100644 index 00000000..bf27e086 --- /dev/null +++ b/lu.common.FileExistsException.html @@ -0,0 +1,36 @@ + + + + FileExistsException (lu.common.FileExistsException) + + + + + + + + + + +
+
+

FileExistsException

Exception, to be thrown when attempting to create a file or directory and + finding that one already exists with the same name.

It is a normal Exception but with an attached filename string.

Constructors

this
this(string message, string file, size_t line, Throwable nextInChain)

Create a new FileExistsException, without attaching a filename.

this
this(string message, string filename, string file, size_t line, Throwable nextInChain)

Create a new FileExistsException, attaching a filename.

Members

Variables

filename
string filename;

The name of the file.

+ +
+ + + \ No newline at end of file diff --git a/lu.common.FileExistsException.this.1.html b/lu.common.FileExistsException.this.1.html new file mode 100644 index 00000000..a879437c --- /dev/null +++ b/lu.common.FileExistsException.this.1.html @@ -0,0 +1,35 @@ + + + + FileExistsException.this (lu.common.FileExistsException.this) + + + + + + + + + + +
+
+

FileExistsException.this

Create a new FileExistsException, without attaching a filename.

  1. this(string message, string file, size_t line, Throwable nextInChain)
    class FileExistsException
    pure nothrow @nogc @safe
    this
    (
    const string message
    ,
    const string file = __FILE__
    ,
    const size_t line = __LINE__
    ,
    Throwable nextInChain = null
    )
  2. this(string message, string filename, string file, size_t line, Throwable nextInChain)
+ +
+ + + \ No newline at end of file diff --git a/lu.common.FileExistsException.this.2.html b/lu.common.FileExistsException.this.2.html new file mode 100644 index 00000000..185c2f17 --- /dev/null +++ b/lu.common.FileExistsException.this.2.html @@ -0,0 +1,35 @@ + + + + FileExistsException.this (lu.common.FileExistsException.this) + + + + + + + + + + +
+
+

FileExistsException.this

Create a new FileExistsException, attaching a filename.

  1. this(string message, string file, size_t line, Throwable nextInChain)
  2. this(string message, string filename, string file, size_t line, Throwable nextInChain)
    class FileExistsException
    pure nothrow @nogc @safe
    this
    (
    const string message
    ,
    const string filename
    ,
    const string file = __FILE__
    ,
    const size_t line = __LINE__
    ,
    Throwable nextInChain = null
    )
+ +
+ + + \ No newline at end of file diff --git a/lu.common.FileExistsException.this.html b/lu.common.FileExistsException.this.html new file mode 100644 index 00000000..526c3754 --- /dev/null +++ b/lu.common.FileExistsException.this.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.common.FileTypeMismatchException.attrs.html b/lu.common.FileTypeMismatchException.attrs.html new file mode 100644 index 00000000..6a5b4e9e --- /dev/null +++ b/lu.common.FileTypeMismatchException.attrs.html @@ -0,0 +1,35 @@ + + + + FileTypeMismatchException.attrs (lu.common.FileTypeMismatchException.attrs) + + + + + + + + + + +
+
+

FileTypeMismatchException.attrs

File attributes.

class FileTypeMismatchException
ushort attrs;
+ +
+ + + \ No newline at end of file diff --git a/lu.common.FileTypeMismatchException.filename.html b/lu.common.FileTypeMismatchException.filename.html new file mode 100644 index 00000000..c6ec82c1 --- /dev/null +++ b/lu.common.FileTypeMismatchException.filename.html @@ -0,0 +1,35 @@ + + + + FileTypeMismatchException.filename (lu.common.FileTypeMismatchException.filename) + + + + + + + + + + +
+
+

FileTypeMismatchException.filename

The filename of the non-FIFO.

class FileTypeMismatchException
string filename;
+ +
+ + + \ No newline at end of file diff --git a/lu.common.FileTypeMismatchException.html b/lu.common.FileTypeMismatchException.html new file mode 100644 index 00000000..00c39352 --- /dev/null +++ b/lu.common.FileTypeMismatchException.html @@ -0,0 +1,38 @@ + + + + FileTypeMismatchException (lu.common.FileTypeMismatchException) + + + + + + + + + + +
+
+

FileTypeMismatchException

Exception, to be thrown when attempting to access a file or directory and + finding that something with the that name exists, but is of an unexpected type.

It is a normal Exception but with an embedded filename + string, and an uint representing the existing file's type (file, directory, + symlink, ...).

Constructors

this
this(string message, string file, size_t line, Throwable nextInChain)

Create a new FileTypeMismatchException, without embedding a filename.

this
this(string message, string filename, ushort attrs, string file, size_t line, Throwable nextInChain)

Create a new FileTypeMismatchException, embedding a filename.

Members

Variables

attrs
ushort attrs;

File attributes.

filename
string filename;

The filename of the non-FIFO.

+ +
+ + + \ No newline at end of file diff --git a/lu.common.FileTypeMismatchException.this.1.html b/lu.common.FileTypeMismatchException.this.1.html new file mode 100644 index 00000000..1ff80b4a --- /dev/null +++ b/lu.common.FileTypeMismatchException.this.1.html @@ -0,0 +1,35 @@ + + + + FileTypeMismatchException.this (lu.common.FileTypeMismatchException.this) + + + + + + + + + + +
+
+

FileTypeMismatchException.this

Create a new FileTypeMismatchException, without embedding a filename.

  1. this(string message, string file, size_t line, Throwable nextInChain)
    class FileTypeMismatchException
    pure nothrow @nogc @safe
    this
    (
    const string message
    ,
    const string file = __FILE__
    ,
    const size_t line = __LINE__
    ,
    Throwable nextInChain = null
    )
  2. this(string message, string filename, ushort attrs, string file, size_t line, Throwable nextInChain)
+ +
+ + + \ No newline at end of file diff --git a/lu.common.FileTypeMismatchException.this.2.html b/lu.common.FileTypeMismatchException.this.2.html new file mode 100644 index 00000000..56376ff0 --- /dev/null +++ b/lu.common.FileTypeMismatchException.this.2.html @@ -0,0 +1,35 @@ + + + + FileTypeMismatchException.this (lu.common.FileTypeMismatchException.this) + + + + + + + + + + +
+
+

FileTypeMismatchException.this

Create a new FileTypeMismatchException, embedding a filename.

  1. this(string message, string file, size_t line, Throwable nextInChain)
  2. this(string message, string filename, ushort attrs, string file, size_t line, Throwable nextInChain)
    class FileTypeMismatchException
    pure nothrow @nogc @safe
    this
    (
    const string message
    ,
    const string filename
    ,
    const ushort attrs
    ,
    const string file = __FILE__
    ,
    const size_t line = __LINE__
    ,
    Throwable nextInChain = null
    )
+ +
+ + + \ No newline at end of file diff --git a/lu.common.FileTypeMismatchException.this.html b/lu.common.FileTypeMismatchException.this.html new file mode 100644 index 00000000..f052077b --- /dev/null +++ b/lu.common.FileTypeMismatchException.this.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.common.Next.html b/lu.common.Next.html new file mode 100644 index 00000000..6a761383 --- /dev/null +++ b/lu.common.Next.html @@ -0,0 +1,35 @@ + + + + Next (lu.common.Next) + + + + + + + + + + +
+
+

Next

Enum of flags carrying the meaning of "what to do next".

Values

ValueMeaning
unset

Unset, invalid value.

noop

Do nothing.

continue_

Keep doing whatever is being done, alternatively continue on to the next step.

retry

Halt what's being done and give it another attempt.

returnSuccess

Exit or return with a positive return value.

returnFailure

Exit or abort with a negative return value.

crash

Fatally abort.

+ +
+ + + \ No newline at end of file diff --git a/lu.common.ReturnValueException.command.html b/lu.common.ReturnValueException.command.html new file mode 100644 index 00000000..0baaea60 --- /dev/null +++ b/lu.common.ReturnValueException.command.html @@ -0,0 +1,35 @@ + + + + ReturnValueException.command (lu.common.ReturnValueException.command) + + + + + + + + + + +
+
+

ReturnValueException.command

The command run.

class ReturnValueException
string command;
+ +
+ + + \ No newline at end of file diff --git a/lu.common.ReturnValueException.html b/lu.common.ReturnValueException.html new file mode 100644 index 00000000..e6da8700 --- /dev/null +++ b/lu.common.ReturnValueException.html @@ -0,0 +1,36 @@ + + + + ReturnValueException (lu.common.ReturnValueException) + + + + + + + + + + +
+
+

ReturnValueException

Exception, to be thrown when an executed command returns an error value.

It is a normal Exception but with an attached command + and return value.

Constructors

this
this(string message, string file, size_t line, Throwable nextInChain)

Create a new ReturnValueException, without attaching anything.

this
this(string message, string command, string file, size_t line, Throwable nextInChain)

Create a new ReturnValueException, attaching a command.

this
this(string message, string command, int retval, string file, size_t line, Throwable nextInChain)

Create a new ReturnValueException, attaching a command and a returned value.

Members

Variables

command
string command;

The command run.

retval
int retval;

The value returned.

+ +
+ + + \ No newline at end of file diff --git a/lu.common.ReturnValueException.retval.html b/lu.common.ReturnValueException.retval.html new file mode 100644 index 00000000..ddf3f58b --- /dev/null +++ b/lu.common.ReturnValueException.retval.html @@ -0,0 +1,35 @@ + + + + ReturnValueException.retval (lu.common.ReturnValueException.retval) + + + + + + + + + + +
+
+

ReturnValueException.retval

The value returned.

class ReturnValueException
int retval;
+ +
+ + + \ No newline at end of file diff --git a/lu.common.ReturnValueException.this.1.html b/lu.common.ReturnValueException.this.1.html new file mode 100644 index 00000000..a070b22b --- /dev/null +++ b/lu.common.ReturnValueException.this.1.html @@ -0,0 +1,35 @@ + + + + ReturnValueException.this (lu.common.ReturnValueException.this) + + + + + + + + + + +
+
+

ReturnValueException.this

Create a new ReturnValueException, without attaching anything.

  1. this(string message, string file, size_t line, Throwable nextInChain)
    class ReturnValueException
    pure nothrow @nogc @safe
    this
    (
    const string message
    ,
    const string file = __FILE__
    ,
    const size_t line = __LINE__
    ,
    Throwable nextInChain = null
    )
  2. this(string message, string command, string file, size_t line, Throwable nextInChain)
  3. this(string message, string command, int retval, string file, size_t line, Throwable nextInChain)
+ +
+ + + \ No newline at end of file diff --git a/lu.common.ReturnValueException.this.2.html b/lu.common.ReturnValueException.this.2.html new file mode 100644 index 00000000..072ce4ef --- /dev/null +++ b/lu.common.ReturnValueException.this.2.html @@ -0,0 +1,35 @@ + + + + ReturnValueException.this (lu.common.ReturnValueException.this) + + + + + + + + + + +
+
+

ReturnValueException.this

Create a new ReturnValueException, attaching a command.

  1. this(string message, string file, size_t line, Throwable nextInChain)
  2. this(string message, string command, string file, size_t line, Throwable nextInChain)
    class ReturnValueException
    pure nothrow @nogc @safe
    this
    (
    const string message
    ,
    const string command
    ,
    const string file = __FILE__
    ,
    const size_t line = __LINE__
    ,
    Throwable nextInChain = null
    )
  3. this(string message, string command, int retval, string file, size_t line, Throwable nextInChain)
+ +
+ + + \ No newline at end of file diff --git a/lu.common.ReturnValueException.this.3.html b/lu.common.ReturnValueException.this.3.html new file mode 100644 index 00000000..067869fe --- /dev/null +++ b/lu.common.ReturnValueException.this.3.html @@ -0,0 +1,35 @@ + + + + ReturnValueException.this (lu.common.ReturnValueException.this) + + + + + + + + + + +
+
+

ReturnValueException.this

Create a new ReturnValueException, attaching a command and a returned value.

  1. this(string message, string file, size_t line, Throwable nextInChain)
  2. this(string message, string command, string file, size_t line, Throwable nextInChain)
  3. this(string message, string command, int retval, string file, size_t line, Throwable nextInChain)
    class ReturnValueException
    pure nothrow @nogc @safe
    this
    (
    const string message
    ,
    const string command
    ,
    const int retval
    ,
    const string file = __FILE__
    ,
    const size_t line = __LINE__
    ,
    Throwable nextInChain = null
    )
+ +
+ + + \ No newline at end of file diff --git a/lu.common.ReturnValueException.this.html b/lu.common.ReturnValueException.this.html new file mode 100644 index 00000000..4c8c1a06 --- /dev/null +++ b/lu.common.ReturnValueException.this.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.common.html b/lu.common.html new file mode 100644 index 00000000..1a7bf9a7 --- /dev/null +++ b/lu.common.html @@ -0,0 +1,37 @@ + + + + lu.common (lu.common) + + + + + + + + + + +
+
+

lu.common

Functionality generic enough to be used in several places.

Members

Classes

FileExistsException
class FileExistsException

Exception, to be thrown when attempting to create a file or directory and + finding that one already exists with the same name.

FileTypeMismatchException
class FileTypeMismatchException

Exception, to be thrown when attempting to access a file or directory and + finding that something with the that name exists, but is of an unexpected type.

ReturnValueException
class ReturnValueException

Exception, to be thrown when an executed command returns an error value.

Enums

Next
enum Next

Enum of flags carrying the meaning of "what to do next".

Functions

sharedDomains
auto sharedDomains(string one, string other, Flag!"caseSensitive" caseSensitive)

Calculates how many dot-separated suffixes two strings share.

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.common.sharedDomains.html b/lu.common.sharedDomains.html new file mode 100644 index 00000000..01cef232 --- /dev/null +++ b/lu.common.sharedDomains.html @@ -0,0 +1,86 @@ + + + + sharedDomains (lu.common.sharedDomains) + + + + + + + + + + +
+
+

sharedDomains

Calculates how many dot-separated suffixes two strings share.

This is useful to see to what extent two addresses are similar.

pure @safe @nogc nothrow
sharedDomains
(
const string one
,
const string other
,
const Flag!"caseSensitive" caseSensitive = Yes.caseSensitive
)

Parameters

one string

First domain string.

other string

Second domain string.

caseSensitive Flag!"caseSensitive"

Whether or not comparison should be done on a + case-sensitive basis.

Return Value

Type: auto

The number of domains the two strings share.

TODO: + Support partial globs.

Examples

int numDomains = sharedDomains("irc.freenode.net", "leguin.freenode.net");
+assert(numDomains == 2);  // freenode.net
+
+int numDomains2 = sharedDomains("Portlane2.EU.GameSurge.net", "services.gamesurge.net", No.caseSensitive);
+assert(numDomains2 == 2);  // gamesurge.net
import std.conv : text;
+
+immutable n1 = sharedDomains("irc.freenode.net", "help.freenode.net");
+assert((n1 == 2), n1.text);
+
+immutable n2 = sharedDomains("irc.rizon.net", "services.rizon.net");
+assert((n2 == 2), n2.text);
+
+immutable n3 = sharedDomains("www.google.com", "www.yahoo.com");
+assert((n3 == 1), n3.text);
+
+immutable n4 = sharedDomains("www.google.se", "www.google.co.uk");
+assert((n4 == 0), n4.text);
+
+immutable n5 = sharedDomains("", string.init);
+assert((n5 == 0), n5.text);
+
+immutable n6 = sharedDomains("irc.rizon.net", "rizon.net");
+assert((n6 == 2), n6.text);
+
+immutable n7 = sharedDomains("rizon.net", "rizon.net");
+assert((n7 == 2), n7.text);
+
+immutable n8 = sharedDomains("net", "net");
+assert((n8 == 1), n8.text);
+
+immutable n9 = sharedDomains("forum.dlang.org", "...");
+assert((n9 == 0), n8.text);
+
+immutable n10 = sharedDomains("blahrizon.net", "rizon.net");
+assert((n10 == 1), n10.text);
+
+immutable n11 = sharedDomains("rizon.net", "blahrizon.net");
+assert((n11 == 1), n11.text);
+
+immutable n12 = sharedDomains("rizon.net", "irc.rizon.net");
+assert((n12 == 2), n12.text);
+
+immutable n13 = sharedDomains("irc.gamesurge.net", "Stuff.GameSurge.net", No.caseSensitive);
+assert((n13 == 2), n13.text);
+
+immutable n14 = sharedDomains("irc.freenode.net", "irc.FREENODE.net", No.caseSensitive);
+assert((n14 == 3), n14.text);
+
+immutable n15 = sharedDomains("irc.SpotChat.org", "irc.FREENODE.net", No.caseSensitive);
+assert((n15 == 0), n15.text);
+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.buf.1.html b/lu.container.Buffer.buf.1.html new file mode 100644 index 00000000..52ef2439 --- /dev/null +++ b/lu.container.Buffer.buf.1.html @@ -0,0 +1,35 @@ + + + + Buffer.buf (lu.container.Buffer.buf) + + + + + + + + + + +
+
+

Buffer.buf

Internal buffer dynamic array.

  1. T[] buf;
    struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
    pure nothrow
    static if(dynamic)
    T[] buf;
  2. T[bufferSize] buf;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.buf.2.html b/lu.container.Buffer.buf.2.html new file mode 100644 index 00000000..b7748654 --- /dev/null +++ b/lu.container.Buffer.buf.2.html @@ -0,0 +1,35 @@ + + + + Buffer.buf (lu.container.Buffer.buf) + + + + + + + + + + +
+
+

Buffer.buf

Internal buffer static array.

  1. T[] buf;
  2. T[bufferSize] buf;
    struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
    pure nothrow
    static if(!(dynamic))
    T[bufferSize] buf;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.buf.html b/lu.container.Buffer.buf.html new file mode 100644 index 00000000..93b0fbae --- /dev/null +++ b/lu.container.Buffer.buf.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.container.Buffer.bufferSize.1.html b/lu.container.Buffer.bufferSize.1.html new file mode 100644 index 00000000..7ffa18d3 --- /dev/null +++ b/lu.container.Buffer.bufferSize.1.html @@ -0,0 +1,35 @@ + + + + Buffer.bufferSize (lu.container.Buffer.bufferSize) + + + + + + + + + + +
+
+

Buffer.bufferSize

Variable buffer size.

  1. size_t bufferSize;
    struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
    pure nothrow
    static if(dynamic)
    size_t bufferSize;
  2. alias bufferSize = originalSize
+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.bufferSize.2.html b/lu.container.Buffer.bufferSize.2.html new file mode 100644 index 00000000..9cb54be2 --- /dev/null +++ b/lu.container.Buffer.bufferSize.2.html @@ -0,0 +1,35 @@ + + + + Buffer.bufferSize (lu.container.Buffer.bufferSize) + + + + + + + + + + +
+
+

Buffer.bufferSize

Static buffer size.

  1. size_t bufferSize;
  2. alias bufferSize = originalSize
    struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
    pure nothrow
    static if(!(dynamic))
    alias bufferSize = originalSize
+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.bufferSize.html b/lu.container.Buffer.bufferSize.html new file mode 100644 index 00000000..19734933 --- /dev/null +++ b/lu.container.Buffer.bufferSize.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.container.Buffer.clear.html b/lu.container.Buffer.clear.html new file mode 100644 index 00000000..cf6dda20 --- /dev/null +++ b/lu.container.Buffer.clear.html @@ -0,0 +1,35 @@ + + + + Buffer.clear (lu.container.Buffer.clear) + + + + + + + + + + +
+
+

Buffer.clear

Zeroes out the buffer's elements, getting rid of old contents.

struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
pure nothrow pure @safe nothrow @nogc
void
clear
()
+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.empty.html b/lu.container.Buffer.empty.html new file mode 100644 index 00000000..bfbdf8fa --- /dev/null +++ b/lu.container.Buffer.empty.html @@ -0,0 +1,37 @@ + + + + Buffer.empty (lu.container.Buffer.empty) + + + + + + + + + + +
+
+

Buffer.empty

Returns whether or not the container is considered empty.

Mind that the buffer may well still contain old contents. Use clear + to zero it out.

struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
pure nothrow const inout
empty
()

Return Value

Type: auto

true if there are items available to get via front, + false if not.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.end.html b/lu.container.Buffer.end.html new file mode 100644 index 00000000..8c351016 --- /dev/null +++ b/lu.container.Buffer.end.html @@ -0,0 +1,35 @@ + + + + Buffer.end (lu.container.Buffer.end) + + + + + + + + + + +
+
+

Buffer.end

Position of last entry in the array.

struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
pure nothrow
ptrdiff_t end;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.front.html b/lu.container.Buffer.front.html new file mode 100644 index 00000000..e066dbb3 --- /dev/null +++ b/lu.container.Buffer.front.html @@ -0,0 +1,35 @@ + + + + Buffer.front (lu.container.Buffer.front) + + + + + + + + + + +
+
+

Buffer.front

Fetches the item at the current position of the buffer.

struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
pure nothrow ref inout pure @safe nothrow @nogc
front
()

Return Value

Type: auto ref

An item T.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.growthFactor.html b/lu.container.Buffer.growthFactor.html new file mode 100644 index 00000000..eb494553 --- /dev/null +++ b/lu.container.Buffer.growthFactor.html @@ -0,0 +1,35 @@ + + + + Buffer.growthFactor (lu.container.Buffer.growthFactor) + + + + + + + + + + +
+
+

Buffer.growthFactor

By how much to grow the buffer when we reach the end of it.

struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
private pure nothrow
static if(dynamic)
enum growthFactor = 1.5;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.html b/lu.container.Buffer.html new file mode 100644 index 00000000..ef9ceb9a --- /dev/null +++ b/lu.container.Buffer.html @@ -0,0 +1,152 @@ + + + + Buffer (lu.container.Buffer) + + + + + + + + + + +
+
+

Buffer

Simple buffer/queue for storing and fetching items of any type T. + Does not use manual memory allocation.

It can use a static array internally to store elements on the stack, which + imposes a hard limit on how many items can be added, or a dynamic heap one + with a resizable buffer.

Members

Aliases

bufferSize
alias bufferSize = originalSize

Static buffer size.

Functions

clear
void clear()

Zeroes out the buffer's elements, getting rid of old contents.

empty
auto empty()

Returns whether or not the container is considered empty.

front
auto ref front()

Fetches the item at the current position of the buffer.

length
auto length()

Returns what amounts to the current length of the buffer; the distance + between the current position pos and the last element end.

opOpAssign
void opOpAssign(T more)

Implements buf ~= someT (appending) by wrapping put.

popFront
void popFront()

Advances the current position to the next item in the buffer.

put
void put(T more)

Append an item to the end of the buffer.

put
void put(T more)

Append an item to the end of the buffer.

reserve
void reserve(size_t reserveSize)

Reserves enough room for the specified number of elements. If there + is already enough room, nothing is done. Otherwise the buffer is grown.

reset
void reset()

Resets the array positions, effectively soft-emptying the buffer.

Manifest constants

growthFactor
enum growthFactor;

By how much to grow the buffer when we reach the end of it.

Variables

buf
T[] buf;

Internal buffer dynamic array.

buf
T[bufferSize] buf;

Internal buffer static array.

bufferSize
size_t bufferSize;

Variable buffer size.

end
ptrdiff_t end;

Position of last entry in the array.

pos
ptrdiff_t pos;

Current position in the array.

Parameters

T

Buffer item type.

dynamic

Whether to use a dynamic array whose size can be grown at + runtime, or to use a static array with a fixed size. Trying to add + more elements than there is room for will cause an assert. + Defaults to No.dynamic; a static array.

originalSize

How many items to allocate space for. If No.dynamic was + passed it will assert if you attempt to store anything past this amount.

Examples

Buffer!(string, No.dynamic, 16) buffer;
+
+buffer.put("abc");
+buffer ~= "def";
+assert(!buffer.empty);
+assert(buffer.front == "abc");
+buffer.popFront();
+assert(buffer.front == "def");
+buffer.popFront();
+assert(buffer.empty);
1 {
+2     Buffer!(bool, No.dynamic, 4) buffer;
+3 
+4     assert(buffer.empty);
+5     buffer.put(true);
+6     buffer.put(false);
+7     assert(buffer.length == 2);
+8     buffer.put(true);
+9     buffer.put(false);
+10 
+11     assert(!buffer.empty);
+12     assert(buffer.front == true);
+13     buffer.popFront();
+14     assert(buffer.front == false);
+15     buffer.popFront();
+16     assert(buffer.front == true);
+17     buffer.popFront();
+18     assert(buffer.front == false);
+19     buffer.popFront();
+20     assert(buffer.empty);
+21     assert(buffer.buf == [ true, false, true, false ]);
+22     buffer.put(false);
+23     assert(buffer.buf == [ false, false, true, false ]);
+24     buffer.reset();
+25     assert(buffer.empty);
+26     buffer.clear();
+27     assert(buffer.buf == [ false, false, false, false ]);
+28 }
+29 {
+30     Buffer!(string, No.dynamic, 4) buffer;
+31 
+32     assert(buffer.empty);
+33     buffer.put("abc");
+34     buffer.put("def");
+35     buffer.put("ghi");
+36 
+37     assert(!buffer.empty);
+38     assert(buffer.front == "abc");
+39     buffer.popFront();
+40     assert(buffer.front == "def");
+41     buffer.popFront();
+42     buffer.put("JKL");
+43     assert(buffer.front == "ghi");
+44     buffer.popFront();
+45     assert(buffer.front == "JKL");
+46     buffer.popFront();
+47     assert(buffer.empty);
+48     assert(buffer.buf == [ "abc", "def", "ghi", "JKL" ]);
+49     buffer.put("MNO");
+50     assert(buffer.buf == [ "MNO", "def", "ghi", "JKL" ]);
+51     buffer.clear();
+52     assert(buffer.buf == [ string.init, string.init, string.init, string.init ]);
+53 }
+54 {
+55     Buffer!(char, No.dynamic, 64) buffer;
+56     buffer ~= 'a';
+57     buffer ~= 'b';
+58     buffer ~= 'c';
+59     assert(buffer.buf[0..3] == "abc");
+60 
+61     foreach (char_; buffer)
+62     {
+63         assert((char_ == 'a') || (char_ == 'b') || (char_ == 'c'));
+64     }
+65 }
+66 {
+67     Buffer!(int, Yes.dynamic, 3) buffer;
+68     assert(!buffer.buf.length);
+69     buffer ~= 1;
+70     assert(buffer.buf.length == 3);
+71     buffer ~= 2;
+72     buffer ~= 3;
+73     assert(buffer.front == 1);
+74     buffer.popFront();
+75     assert(buffer.front == 2);
+76     buffer.popFront();
+77     assert(buffer.front == 3);
+78     buffer.popFront();
+79     assert(buffer.empty);
+80     buffer.reserve(64);
+81     assert(buffer.buf.length == 64);
+82     buffer.reserve(63);
+83     assert(buffer.buf.length == 64);
+84 }
+85 {
+86     Buffer!(char, No.dynamic, 4) buffer;
+87     buffer ~= 'a';
+88     buffer ~= 'b';
+89     buffer ~= 'c';
+90     buffer ~= 'd';
+91     assert(buffer.buf == "abcd");
+92     assert(buffer.length == 4);
+93     buffer.reset();
+94     assert(buffer.buf == "abcd");
+95     buffer.clear();
+96     assert(buffer.buf == typeof(buffer.buf).init);
+97 }
+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.length.html b/lu.container.Buffer.length.html new file mode 100644 index 00000000..1c92efc5 --- /dev/null +++ b/lu.container.Buffer.length.html @@ -0,0 +1,36 @@ + + + + Buffer.length (lu.container.Buffer.length) + + + + + + + + + + +
+
+

Buffer.length

Returns what amounts to the current length of the buffer; the distance + between the current position pos and the last element end.

struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
pure nothrow const inout
length
()

Return Value

Type: auto

The buffer's current length.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.opOpAssign.html b/lu.container.Buffer.opOpAssign.html new file mode 100644 index 00000000..18a02e9d --- /dev/null +++ b/lu.container.Buffer.opOpAssign.html @@ -0,0 +1,35 @@ + + + + Buffer.opOpAssign (lu.container.Buffer.opOpAssign) + + + + + + + + + + +
+
+

Buffer.opOpAssign

Implements buf ~= someT (appending) by wrapping put.

struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
pure nothrow pure @safe nothrow
void
opOpAssign
(
string op : "~"
)
()

Parameters

op

Operation type, here specialised to "~".

more T

Item to add.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.popFront.html b/lu.container.Buffer.popFront.html new file mode 100644 index 00000000..a1733f2d --- /dev/null +++ b/lu.container.Buffer.popFront.html @@ -0,0 +1,35 @@ + + + + Buffer.popFront (lu.container.Buffer.popFront) + + + + + + + + + + +
+
+

Buffer.popFront

Advances the current position to the next item in the buffer.

struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
pure nothrow pure @safe nothrow @nogc
void
popFront
()
+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.pos.html b/lu.container.Buffer.pos.html new file mode 100644 index 00000000..12639e49 --- /dev/null +++ b/lu.container.Buffer.pos.html @@ -0,0 +1,35 @@ + + + + Buffer.pos (lu.container.Buffer.pos) + + + + + + + + + + +
+
+

Buffer.pos

Current position in the array.

struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
pure nothrow
ptrdiff_t pos;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.put.1.html b/lu.container.Buffer.put.1.html new file mode 100644 index 00000000..9c02abbb --- /dev/null +++ b/lu.container.Buffer.put.1.html @@ -0,0 +1,35 @@ + + + + Buffer.put (lu.container.Buffer.put) + + + + + + + + + + +
+
+

Buffer.put

Append an item to the end of the buffer.

If it would be put beyond the end of the buffer, it will be resized to fit.

  1. void put(T more)
    struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
    pure nothrow pure @safe nothrow
    static if(dynamic)
    void
    put
    ()
  2. void put(T more)

Parameters

more T

Item to add.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.put.2.html b/lu.container.Buffer.put.2.html new file mode 100644 index 00000000..0ec6ad49 --- /dev/null +++ b/lu.container.Buffer.put.2.html @@ -0,0 +1,35 @@ + + + + Buffer.put (lu.container.Buffer.put) + + + + + + + + + + +
+
+

Buffer.put

Append an item to the end of the buffer.

If it would be put beyond the end of the buffer, it will assert.

  1. void put(T more)
  2. void put(T more)
    struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
    pure nothrow pure @safe nothrow @nogc
    static if(!(dynamic))
    void
    put
    ()

Parameters

more T

Item to add.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.put.html b/lu.container.Buffer.put.html new file mode 100644 index 00000000..f726f6c0 --- /dev/null +++ b/lu.container.Buffer.put.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.container.Buffer.reserve.html b/lu.container.Buffer.reserve.html new file mode 100644 index 00000000..fbf0ed9f --- /dev/null +++ b/lu.container.Buffer.reserve.html @@ -0,0 +1,36 @@ + + + + Buffer.reserve (lu.container.Buffer.reserve) + + + + + + + + + + +
+
+

Buffer.reserve

Reserves enough room for the specified number of elements. If there + is already enough room, nothing is done. Otherwise the buffer is grown.

struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
pure nothrow pure @safe nothrow
static if(dynamic)
void
reserve
(
const size_t reserveSize
)

Parameters

reserveSize size_t

Number of elements to reserve size for.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.Buffer.reset.html b/lu.container.Buffer.reset.html new file mode 100644 index 00000000..cd7f53c7 --- /dev/null +++ b/lu.container.Buffer.reset.html @@ -0,0 +1,36 @@ + + + + Buffer.reset (lu.container.Buffer.reset) + + + + + + + + + + +
+
+

Buffer.reset

Resets the array positions, effectively soft-emptying the buffer.

The old elements' values are still there, they will just be overwritten + as the buffer is appended to.

struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
pure nothrow pure @safe nothrow @nogc
void
reset
()
+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.buf.1.html b/lu.container.CircularBuffer.buf.1.html new file mode 100644 index 00000000..8f9f5175 --- /dev/null +++ b/lu.container.CircularBuffer.buf.1.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.buf (lu.container.CircularBuffer.buf) + + + + + + + + + + +
+
+

CircularBuffer.buf

Internal buffer dynamic array.

  1. T[] buf;
    struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
    private
    static if(dynamic)
    T[] buf;
  2. T[originalSize] buf;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.buf.2.html b/lu.container.CircularBuffer.buf.2.html new file mode 100644 index 00000000..9575111a --- /dev/null +++ b/lu.container.CircularBuffer.buf.2.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.buf (lu.container.CircularBuffer.buf) + + + + + + + + + + +
+
+

CircularBuffer.buf

Internal buffer static array.

  1. T[] buf;
  2. T[originalSize] buf;
    struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
    private
    static if(!(dynamic))
    T[originalSize] buf;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.buf.html b/lu.container.CircularBuffer.buf.html new file mode 100644 index 00000000..6b677ce7 --- /dev/null +++ b/lu.container.CircularBuffer.buf.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.container.CircularBuffer.caughtUp.html b/lu.container.CircularBuffer.caughtUp.html new file mode 100644 index 00000000..9d9a2277 --- /dev/null +++ b/lu.container.CircularBuffer.caughtUp.html @@ -0,0 +1,36 @@ + + + + CircularBuffer.caughtUp (lu.container.CircularBuffer.caughtUp) + + + + + + + + + + +
+
+

CircularBuffer.caughtUp

Whether or not head and tail point to the same position in the + context of a circular array.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
private
bool caughtUp;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.clear.html b/lu.container.CircularBuffer.clear.html new file mode 100644 index 00000000..659a5665 --- /dev/null +++ b/lu.container.CircularBuffer.clear.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.clear (lu.container.CircularBuffer.clear) + + + + + + + + + + +
+
+

CircularBuffer.clear

Zeroes out the buffer's elements, getting rid of old contents.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
pure @safe @nogc nothrow
void
clear
()
if (
originalSize > 1
)
+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.dup.html b/lu.container.CircularBuffer.dup.html new file mode 100644 index 00000000..a8012127 --- /dev/null +++ b/lu.container.CircularBuffer.dup.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.dup (lu.container.CircularBuffer.dup) + + + + + + + + + + +
+
+

CircularBuffer.dup

Makes a deep(er) duplicate of the container.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
dup
()
if (
originalSize > 1
)

Return Value

Type: auto

A copy of the current container with the internal buffer explicitly .duped.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.empty.html b/lu.container.CircularBuffer.empty.html new file mode 100644 index 00000000..ba1619e8 --- /dev/null +++ b/lu.container.CircularBuffer.empty.html @@ -0,0 +1,37 @@ + + + + CircularBuffer.empty (lu.container.CircularBuffer.empty) + + + + + + + + + + +
+
+

CircularBuffer.empty

Returns whether or not the container is considered empty.

Mind that the buffer may well still contain old contents. Use clear + to zero it out.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
const inout
empty
()
if (
originalSize > 1
)

Return Value

Type: auto

true if there are items available to get via front, + false if not.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.front.html b/lu.container.CircularBuffer.front.html new file mode 100644 index 00000000..5a9a146e --- /dev/null +++ b/lu.container.CircularBuffer.front.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.front (lu.container.CircularBuffer.front) + + + + + + + + + + +
+
+

CircularBuffer.front

Returns the front element.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
ref inout
front
()
if (
originalSize > 1
)

Return Value

Type: auto ref

An item T.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.head.html b/lu.container.CircularBuffer.head.html new file mode 100644 index 00000000..d5e41b19 --- /dev/null +++ b/lu.container.CircularBuffer.head.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.head (lu.container.CircularBuffer.head) + + + + + + + + + + +
+
+

CircularBuffer.head

Head position in the internal buffer.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
private
size_t head;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.html b/lu.container.CircularBuffer.html new file mode 100644 index 00000000..cec443eb --- /dev/null +++ b/lu.container.CircularBuffer.html @@ -0,0 +1,137 @@ + + + + CircularBuffer (lu.container.CircularBuffer) + + + + + + + + + + +
+
+

CircularBuffer

Simple circular-ish buffer for storing items of type T that discards elements + when the maximum size is reached. Does not use manual memory allocation.

It can use a static array internally to store elements on the stack, which + imposes a hard limit on how many items can be added, or a dynamic heap one + with a resizable buffer.

Members

Functions

clear
void clear()

Zeroes out the buffer's elements, getting rid of old contents.

dup
auto dup()

Makes a deep(er) duplicate of the container.

empty
auto empty()

Returns whether or not the container is considered empty.

front
auto ref front()

Returns the front element.

opOpAssign
void opOpAssign(T more)

Implements buf ~= someT (appending) by wrapping put.

popFront
void popFront()

Advances the current position to the next item in the buffer.

put
void put(T item)

Append an item to the buffer.

reset
void reset()

Resets the buffer pointers but doesn't clear the contents.

resize
void resize(size_t size)

Resizes the internal buffer to a specified size.

save
auto save()

Implements Range save.

size
auto size()

Returns the size of the internal buffer.

Variables

buf
T[] buf;

Internal buffer dynamic array.

buf
T[originalSize] buf;

Internal buffer static array.

caughtUp
bool caughtUp;

Whether or not head and tail point to the same position in the + context of a circular array.

head
size_t head;

Head position in the internal buffer.

initialised
bool initialised;

Whether or not at least one element has been added.

tail
size_t tail;

Tail position in the internal buffer.

Parameters

T

Buffer item type.

dynamic

Whether to use a dynamic array whose size can be grown at + runtime, or to use a static array with a fixed size. Trying to add + more elements than there is room for will wrap around and discard elements. + Defaults to No.dynamic; a static buffer.

originalSize

How many items to allocate space for in the case of a + static array.

Examples

CircularBuffer!(int, Yes.dynamic) buf;
+buf.resize(3);
+buf.put(1);
+buf.put(2);
+buf.put(3);
+but.put(4);
+assert(buf.front == 4);
+assert(buf.buf == [ 4, 2, 3 ]);
1 import std.conv : text;
+2 
+3 {
+4     CircularBuffer!(int, Yes.dynamic) buf;
+5     buf.resize(3);
+6 
+7     buf.put(1);
+8     assert((buf.front == 1), buf.front.text);
+9     buf.put(2);
+10     assert((buf.front == 2), buf.front.text);
+11     buf.put(3);
+12     assert((buf.front == 3), buf.front.text);
+13     buf ~= 4;
+14     assert((buf.front == 4), buf.front.text);
+15     assert((buf.buf[] == [ 4, 2, 3 ]), buf.buf.text);
+16     buf ~= 5;
+17     assert((buf.front == 5), buf.front.text);
+18     buf ~= 6;
+19     assert((buf.front == 6), buf.front.text);
+20     assert((buf.buf[] == [ 4, 5, 6 ]), buf.buf.text);
+21     buf.popFront();
+22     buf.popFront();
+23     buf.popFront();
+24     assert(buf.empty);
+25 }
+26 {
+27     CircularBuffer!(int, No.dynamic, 3) buf;
+28     //buf.resize(3);
+29 
+30     buf.put(1);
+31     assert((buf.front == 1), buf.front.text);
+32     buf.put(2);
+33     assert((buf.front == 2), buf.front.text);
+34     buf.put(3);
+35     assert((buf.front == 3), buf.front.text);
+36     buf ~= 4;
+37     assert((buf.front == 4), buf.front.text);
+38     assert((buf.buf[] == [ 4, 2, 3 ]), buf.buf.text);
+39     buf.popFront();
+40     buf.popFront();
+41     buf.popFront();
+42     assert(buf.empty);
+43 }
+44 {
+45     CircularBuffer!(int, No.dynamic, 2) buf;
+46     //buf.resize(2);
+47 
+48     buf.put(1);
+49     assert((buf.front == 1), buf.front.text);
+50     buf.put(2);
+51     assert((buf.front == 2), buf.front.text);
+52     buf.put(3);
+53     assert((buf.front == 3), buf.front.text);
+54     buf ~= 4;
+55     assert((buf.front == 4), buf.front.text);
+56     assert((buf.buf[] == [ 3, 4 ]), buf.buf.text);
+57     buf.popFront();
+58     buf.popFront();
+59     assert(buf.empty);
+60     //buf.popFront();  // AssertError
+61 }
+62 {
+63     CircularBuffer!(int, No.dynamic, 2) buf;
+64     //buf.resize(2);
+65 
+66     buf.put(1);
+67     assert((buf.front == 1), buf.front.text);
+68     buf.put(2);
+69     assert((buf.front == 2), buf.front.text);
+70     buf.put(3);
+71     assert((buf.front == 3), buf.front.text);
+72     buf ~= 4;
+73     assert((buf.front == 4), buf.front.text);
+74     assert((buf.buf[] == [ 3, 4 ]), buf.buf.text);
+75     auto savedBuf = buf.save();
+76     buf.popFront();
+77     buf.popFront();
+78     assert(buf.empty);
+79     assert((savedBuf.front == 4), savedBuf.front.text);
+80     savedBuf.popFront();
+81     auto savedBuf2 = savedBuf.save();
+82     savedBuf.popFront();
+83     assert(savedBuf.empty);
+84     assert((savedBuf2.front == 3), savedBuf2.front.text);
+85     savedBuf2.popFront();
+86     assert(savedBuf2.empty);
+87 }
+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.initialised.html b/lu.container.CircularBuffer.initialised.html new file mode 100644 index 00000000..e5689682 --- /dev/null +++ b/lu.container.CircularBuffer.initialised.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.initialised (lu.container.CircularBuffer.initialised) + + + + + + + + + + +
+
+

CircularBuffer.initialised

Whether or not at least one element has been added.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
private
bool initialised;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.opOpAssign.html b/lu.container.CircularBuffer.opOpAssign.html new file mode 100644 index 00000000..b98d2d3a --- /dev/null +++ b/lu.container.CircularBuffer.opOpAssign.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.opOpAssign (lu.container.CircularBuffer.opOpAssign) + + + + + + + + + + +
+
+

CircularBuffer.opOpAssign

Implements buf ~= someT (appending) by wrapping put.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
pure @safe @nogc nothrow
void
opOpAssign
(
string op : "~"
)
(
const T more
)
if (
originalSize > 1
)

Parameters

op

Operation type, here specialised to "~".

more T

Item to add.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.popFront.html b/lu.container.CircularBuffer.popFront.html new file mode 100644 index 00000000..58a5037d --- /dev/null +++ b/lu.container.CircularBuffer.popFront.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.popFront (lu.container.CircularBuffer.popFront) + + + + + + + + + + +
+
+

CircularBuffer.popFront

Advances the current position to the next item in the buffer.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
pure @safe @nogc nothrow
void
popFront
()
if (
originalSize > 1
)
+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.put.html b/lu.container.CircularBuffer.put.html new file mode 100644 index 00000000..2b969d18 --- /dev/null +++ b/lu.container.CircularBuffer.put.html @@ -0,0 +1,36 @@ + + + + CircularBuffer.put (lu.container.CircularBuffer.put) + + + + + + + + + + +
+
+

CircularBuffer.put

Append an item to the buffer.

If it would be put beyond the end of the buffer, it will wrap around and + truncate old values.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
pure @safe @nogc nothrow
void
put
()
if (
originalSize > 1
)

Parameters

item T

Item to add.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.reset.html b/lu.container.CircularBuffer.reset.html new file mode 100644 index 00000000..c248574f --- /dev/null +++ b/lu.container.CircularBuffer.reset.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.reset (lu.container.CircularBuffer.reset) + + + + + + + + + + +
+
+

CircularBuffer.reset

Resets the buffer pointers but doesn't clear the contents.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
pure @safe @nogc nothrow
void
reset
()
if (
originalSize > 1
)
+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.resize.html b/lu.container.CircularBuffer.resize.html new file mode 100644 index 00000000..b30111ac --- /dev/null +++ b/lu.container.CircularBuffer.resize.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.resize (lu.container.CircularBuffer.resize) + + + + + + + + + + +
+
+

CircularBuffer.resize

Resizes the internal buffer to a specified size.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
pure @safe nothrow
static if(dynamic)
void
resize
(
const size_t size
)
if (
originalSize > 1
)

Parameters

size size_t

New size.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.save.html b/lu.container.CircularBuffer.save.html new file mode 100644 index 00000000..c1fdc55e --- /dev/null +++ b/lu.container.CircularBuffer.save.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.save (lu.container.CircularBuffer.save) + + + + + + + + + + +
+
+

CircularBuffer.save

Implements Range save.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
save
()
if (
originalSize > 1
)

Return Value

Type: auto

A shallow copy of the container.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.size.html b/lu.container.CircularBuffer.size.html new file mode 100644 index 00000000..2c3b9af3 --- /dev/null +++ b/lu.container.CircularBuffer.size.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.size (lu.container.CircularBuffer.size) + + + + + + + + + + +
+
+

CircularBuffer.size

Returns the size of the internal buffer.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
const inout
size
()
if (
originalSize > 1
)

Return Value

Type: auto

Internal buffer size.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.CircularBuffer.tail.html b/lu.container.CircularBuffer.tail.html new file mode 100644 index 00000000..b247f2ca --- /dev/null +++ b/lu.container.CircularBuffer.tail.html @@ -0,0 +1,35 @@ + + + + CircularBuffer.tail (lu.container.CircularBuffer.tail) + + + + + + + + + + +
+
+

CircularBuffer.tail

Tail position in the internal buffer.

struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
private
size_t tail;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.aa.html b/lu.container.MutexedAA.aa.html new file mode 100644 index 00000000..7f43ef4a --- /dev/null +++ b/lu.container.MutexedAA.aa.html @@ -0,0 +1,35 @@ + + + + MutexedAA.aa (lu.container.MutexedAA.aa) + + + + + + + + + + +
+
+

MutexedAA.aa

The internal associative array.

struct MutexedAA(AA : V[K], V, K)
shared
AA aa;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.clear.html b/lu.container.MutexedAA.clear.html new file mode 100644 index 00000000..afebbeed --- /dev/null +++ b/lu.container.MutexedAA.clear.html @@ -0,0 +1,43 @@ + + + + MutexedAA.clear (lu.container.MutexedAA.clear) + + + + + + + + + + +
+
+

MutexedAA.clear

Clears the internal associative array.

struct MutexedAA(AA : V[K], V, K)
void
clear
()

Examples

MutexedAA!(string[int]) aa;
+aa.setup();  // important!
+
+aa[1] = "one";
+aa[2] = "two";
+assert(aa.has(1));
+
+aa.clear();
+assert(!aa.has(2));
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.get.html b/lu.container.MutexedAA.get.html new file mode 100644 index 00000000..274f1649 --- /dev/null +++ b/lu.container.MutexedAA.get.html @@ -0,0 +1,47 @@ + + + + MutexedAA.get (lu.container.MutexedAA.get) + + + + + + + + + + +
+
+

MutexedAA.get

Retrieves the value for the key key, or returns the default value + if there was none.

struct MutexedAA(AA : V[K], V, K)
get
(
K key
,
lazy V value
)

Parameters

key K

Key.

value V

Lazy default value.

Return Value

Type: auto

The value for the key key, or value if there was no value there.

Examples

MutexedAA!(int[int]) aa;
+aa.setup();  // important!
+aa[1] = 42;
+aa[2] = 99;
+
+assert(aa.get(1, 0) == 42);
+assert(aa.get(2, 0) == 99);
+assert(aa.get(0, 0) == 0);
+assert(aa.get(3, 999) == 999);
+
+assert(!aa.has(0));
+assert(!aa.has(3));
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.has.html b/lu.container.MutexedAA.has.html new file mode 100644 index 00000000..e26dbdad --- /dev/null +++ b/lu.container.MutexedAA.has.html @@ -0,0 +1,39 @@ + + + + MutexedAA.has (lu.container.MutexedAA.has) + + + + + + + + + + +
+
+

MutexedAA.has

Returns whether or not the passed key is in the associative array.

struct MutexedAA(AA : V[K], V, K)
has
(
K key
)

Parameters

key K

Key.

Return Value

Type: auto

true if the key is in the associative array; false if not.

Examples

MutexedAA!(string[int]) aa;
+aa.setup();  // important!
+
+aa[1] = "one";
+assert(aa.has(1));
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.html b/lu.container.MutexedAA.html new file mode 100644 index 00000000..8c38ea4d --- /dev/null +++ b/lu.container.MutexedAA.html @@ -0,0 +1,309 @@ + + + + MutexedAA (lu.container.MutexedAA) + + + + + + + + + + +
+
+

MutexedAA

An associative array and a Mutex. Wraps associative + array operations in mutex locks.

Members

Functions

clear
void clear()

Clears the internal associative array.

get
auto get(K key, V value)

Retrieves the value for the key key, or returns the default value + if there was none.

has
auto has(K key)

Returns whether or not the passed key is in the associative array.

isReady
auto isReady()

Returns whether or not this instance has been set up.

keys
auto keys()

Returns a new dynamic array of all the keys in the internal associative array.

length
auto length()

Returns the length of the internal associative array.

opEquals
auto opEquals(typeof(this) other)

Implements opEquals for this type, comparing the internal associative + array with that of another MutexedAA.

opEquals
auto opEquals(AA other)

Implements opEquals for this type, comparing the internal associative + array with a different one.

opIndex
auto opIndex(K key)

aa[key] array retrieve operation, wrapped in a mutex lock.

opIndexAssign
auto opIndexAssign(V value, K key)

aa[key] = value array assign operation, wrapped in a mutex lock.

opIndexOpAssign
void opIndexOpAssign(U value, K key)

Implements index assign operations by mixin strings.

opIndexUnary
auto opIndexUnary(K key)

Implements unary operations by mixin strings.

rehash
auto rehash()

Rehashes the internal associative array.

remove
auto remove(K key)

aa.remove(key) array operation, wrapped in a mutex lock.

require
auto require(K key, V value)

Returns the value for the key key, inserting value lazily if it is not present.

setup
void setup()

Sets up this instance. Does nothing if it has already been set up.

uniqueKey
auto uniqueKey(K min, K max, V value)

Reserves a unique key in the associative array.

update
void update(K key, V delegate() createDg, U delegate(K) updateDg)

Updates the value for the key key in the internal associative array, + invoking the first of the passed delegate to insert a new value if it + doesn't exist, or the second selegate to modify it in place if it does.

values
auto values()

Returns a new dynamic array of all the values in the internal associative array.

Variables

aa
AA aa;

The internal associative array.

mutex
Mutex mutex;

Mutex to lock the associative array with.

Parameters

AA

Associative array type.

V

Value type.

K

Key type.

Examples

MutexedAA!(string[int]) aa;
+aa.setup();  // important!
+
+aa[1] = "one";
+aa[2] = "two";
+aa[3] = "three";
+
+auto hasOne = aa.has(1);
+assert(hasOne);
+assert(aa[1] == "one");
+
+assert(aa[2] == "two");
+
+auto three = aa.get(3);
+assert(three == "three");
+
+auto four = aa.get(4, "four");
+assert(four == "four");
+
+auto five = aa.require(5, "five");
+assert(five == "five");
+assert(aa[5] == "five");
+
+auto keys = aa.keys;
+assert(keys.canFind(1));
+assert(keys.canFind(5));
+assert(!keys.canFind(6));
+
+auto values = aa.values;
+assert(values.canFind("one"));
+assert(values.canFind("four"));
+assert(!values.canFind("six"));
+
+aa.rehash();
1 {
+2     MutexedAA!(string[int]) aa1;
+3     assert(!aa1.isReady);
+4     aa1.setup();
+5     assert(aa1.isReady);
+6     aa1.setup();  // extra setups ignored
+7 
+8     MutexedAA!(string[int]) aa2;
+9     aa2.setup();
+10 
+11     aa1[42] = "hello";
+12     aa2[42] = "world";
+13     assert(aa1 != aa2);
+14 
+15     aa1[42] = "world";
+16     assert(aa1 == aa2);
+17 
+18     aa2[99] = "goodbye";
+19     assert(aa1 != aa2);
+20 }
+21 {
+22     MutexedAA!(string[int]) aa;
+23     aa.setup();
+24 
+25     assert(!aa.has(42));
+26     aa.require(42, "hello");
+27     assert((aa[42] == "hello"), aa[42]);
+28 
+29     bool set1;
+30     assert(!aa.has(99));
+31     string world1 = aa.require(99, { set1 = true; return "world"; }());
+32     assert(set1);
+33     assert((world1 == "world"), world1);
+34     assert((aa[99] == "world"), aa[99]);
+35 
+36     bool set2;
+37     string world2 = aa.require(99, { set2 = true; return "goodbye"; }());
+38     assert(!set2);
+39     assert((world2 != "goodbye"), world2);
+40     assert((aa[99] != "goodbye"), aa[99]);
+41 }
+42 {
+43     import std.concurrency : Tid, send, spawn;
+44     import std.conv : to;
+45     import core.time : MonoTime, seconds;
+46 
+47     static immutable timeout = 1.seconds;
+48 
+49     static void workerFn(MutexedAA!(string[int]) aa)
+50     {
+51         static void _assert(
+52             lazy bool condition,
+53             const string message = "unittest failure",
+54             const string file = __FILE__,
+55             const uint line = __LINE__)
+56         {
+57             if (!condition)
+58             {
+59                 import std.format : format;
+60                 import std.stdio : writeln;
+61 
+62                 enum pattern = "core.exception.AssertError@%s(%d): %s";
+63                 immutable assertMessage = pattern.format(file, line, message);
+64                 writeln(assertMessage);
+65                 assert(0, assertMessage);
+66             }
+67         }
+68 
+69         _assert(aa.isReady, "MutexedAA passed to worker was not set up properly");
+70 
+71         bool halt;
+72 
+73         while (!halt)
+74         {
+75             import std.concurrency : OwnerTerminated, receiveTimeout;
+76             import std.variant : Variant;
+77 
+78             immutable receivedSomething = receiveTimeout(timeout,
+79                 (bool _)
+80                 {
+81                     halt = true;
+82                 },
+83                 (int i)
+84                 {
+85                     _assert((aa.length == i-1), "Incorrect MutexedAA length before insert");
+86                     aa[i] = i.to!string;
+87                     _assert((aa.length == i), "Incorrect MutexedAA length after insert");
+88                 },
+89                 (OwnerTerminated _)
+90                 {
+91                     halt = true;
+92                 },
+93                 (Variant v)
+94                 {
+95                     import std.stdio : writeln;
+96                     writeln("MutexedAA unit test worker received unknown message: ", v);
+97                     halt = true;
+98                 }
+99             );
+100 
+101             if (!receivedSomething) return;
+102         }
+103     }
+104 
+105     MutexedAA!(string[int]) aa;
+106     aa.setup();
+107 
+108     auto worker = spawn(&workerFn, aa);
+109     immutable start = MonoTime.currTime;
+110 
+111     foreach (/*immutable*/ i; 1..10)  // start at 1 to enable length checks in worker
+112     {
+113         worker.send(i);
+114         aa.setup();
+115         auto present = aa.has(i);
+116 
+117         while (!present && (MonoTime.currTime - start) < timeout)
+118         {
+119             import core.thread : Thread;
+120             import core.time : msecs;
+121 
+122             static immutable briefWait = 2.msecs;
+123             Thread.sleep(briefWait);
+124             present = aa.has(i);
+125         }
+126 
+127         assert(present, "MutexedAA unit test worker timed out responding to " ~ i.to!string);
+128         assert((aa[i] == i.to!string), aa[i]);
+129     }
+130 
+131     worker.send(true);  // halt
+132 }
+133 {
+134     import std.algorithm.searching : canFind;
+135 
+136     MutexedAA!(int[int]) aa;
+137     aa.setup();
+138 
+139     aa[1] = 42;
+140     aa[2] = 99;
+141     assert(aa.length == 2);
+142 
+143     auto keys = aa.keys;
+144     assert(keys.canFind(1));
+145     assert(keys.canFind(2));
+146     assert(!keys.canFind(3));
+147 
+148     auto values = aa.values;
+149     assert(values.canFind(42));
+150     assert(values.canFind(99));
+151     assert(!values.canFind(0));
+152 
+153     assert(aa.get(1, 0) == 42);
+154     assert(aa.get(2, 0) == 99);
+155     assert(aa.get(0, 0) == 0);
+156     assert(aa.get(3, 999) == 999);
+157 }
+158 {
+159     MutexedAA!(int[int]) aa1;
+160     aa1.setup();
+161 
+162     aa1[1] = 42;
+163     aa1[2] = 99;
+164 
+165     int[int] aa2;
+166 
+167     aa2[1] = 42;
+168     assert(aa1 != aa2);
+169 
+170     aa2[2] = 99;
+171     assert(aa1 == aa2);
+172 
+173     ++aa2[2];
+174     assert(aa2[2] == 100);
+175 
+176     aa2[1] += 1;
+177     assert(aa2[1] == 43);
+178 
+179     aa2[1] -= 1;
+180     assert(aa2[1] == 42);
+181 
+182     aa2[1] *= 2;
+183     assert(aa2[1] == 84);
+184 
+185     int i = -aa2[1];
+186     assert(i == -84);
+187 }
+188 {
+189     MutexedAA!(char[][int]) aa;
+190     aa.setup();
+191 
+192     aa[1] ~= 'a';
+193     aa[1] ~= 'b';
+194     aa[1] ~= 'c';
+195     assert(aa[1] == "abc".dup);
+196 
+197     aa[1] ~= [ 'd', 'e', 'f' ];
+198     assert(aa[1] == "abcdef".dup);
+199 }
+200 {
+201     MutexedAA!(int[int]) aa;
+202     aa.setup();
+203 
+204     immutable key = aa.uniqueKey;
+205     assert(key > 0);
+206 
+207     assert(aa.has(key));
+208     assert(aa[key] == int.init);
+209     aa.remove(key);
+210     assert(!aa.has(key));
+211 
+212     immutable key2 = aa.uniqueKey(1, 2, -1);
+213     assert(key2 == 1);
+214     assert(aa.has(key2));
+215     assert(aa[key2] == -1);
+216 }
+217 static if (__VERSION__ >= 2088L)
+218 {
+219     MutexedAA!(int[int]) aa;
+220     aa.setup();
+221 
+222     assert(!aa.has(1));
+223 
+224     aa.update(1,
+225         () => 42,
+226         (int i) => i + 1);
+227     assert(aa.has(1));
+228     assert(aa[1] == 42);
+229 
+230     aa.update(1,
+231         () => 42,
+232         (int i) => i + 1);
+233     assert(aa[1] == 43);
+234 }
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.isReady.html b/lu.container.MutexedAA.isReady.html new file mode 100644 index 00000000..a39e81a4 --- /dev/null +++ b/lu.container.MutexedAA.isReady.html @@ -0,0 +1,36 @@ + + + + MutexedAA.isReady (lu.container.MutexedAA.isReady) + + + + + + + + + + +
+
+

MutexedAA.isReady

Returns whether or not this instance has been set up.

struct MutexedAA(AA : V[K], V, K)
inout
isReady
()

Return Value

Type: auto

Whether or not the mutex was instantiated, and thus whether this + instance has been set up.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.keys.html b/lu.container.MutexedAA.keys.html new file mode 100644 index 00000000..4e7890ab --- /dev/null +++ b/lu.container.MutexedAA.keys.html @@ -0,0 +1,43 @@ + + + + MutexedAA.keys (lu.container.MutexedAA.keys) + + + + + + + + + + +
+
+

MutexedAA.keys

Returns a new dynamic array of all the keys in the internal associative array.

struct MutexedAA(AA : V[K], V, K)
keys
()

Return Value

Type: auto

A new K[] of all the AA keys.

Examples

MutexedAA!(int[int]) aa;
+aa.setup();  // important!
+aa[1] = 42;
+aa[2] = 99;
+
+auto keys = aa.keys;
+assert(keys.canFind(1));
+assert(keys.canFind(2));
+assert(!keys.canFind(3));
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.length.html b/lu.container.MutexedAA.length.html new file mode 100644 index 00000000..6d863fe0 --- /dev/null +++ b/lu.container.MutexedAA.length.html @@ -0,0 +1,41 @@ + + + + MutexedAA.length (lu.container.MutexedAA.length) + + + + + + + + + + +
+
+

MutexedAA.length

Returns the length of the internal associative array.

struct MutexedAA(AA : V[K], V, K)
length
()

Return Value

Type: auto

The length of the internal associative array.

Examples

MutexedAA!(string[int]) aa;
+aa.setup();  // important!
+
+assert(aa.length == 0);
+aa[1] = "one";
+aa[2] = "two";
+assert(aa.length == 2);
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.mutex.html b/lu.container.MutexedAA.mutex.html new file mode 100644 index 00000000..6a01f679 --- /dev/null +++ b/lu.container.MutexedAA.mutex.html @@ -0,0 +1,35 @@ + + + + MutexedAA.mutex (lu.container.MutexedAA.mutex) + + + + + + + + + + +
+
+

MutexedAA.mutex

Mutex to lock the associative array with.

struct MutexedAA(AA : V[K], V, K)
private shared
Mutex mutex;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.opEquals.1.html b/lu.container.MutexedAA.opEquals.1.html new file mode 100644 index 00000000..98452943 --- /dev/null +++ b/lu.container.MutexedAA.opEquals.1.html @@ -0,0 +1,50 @@ + + + + MutexedAA.opEquals (lu.container.MutexedAA.opEquals) + + + + + + + + + + +
+
+

MutexedAA.opEquals

Implements opEquals for this type, comparing the internal associative + array with that of another MutexedAA.

  1. auto opEquals(typeof(this) other)
    struct MutexedAA(AA : V[K], V, K)
    opEquals
    ()
  2. auto opEquals(AA other)

Parameters

other typeof(this)

Other MutexedAA whose internal associative array to compare + with the one of this instance.

Return Value

Type: auto

true if the internal associative arrays are equal; false if not.

Examples

MutexedAA!(string[int]) aa1;
+aa1.setup();  // important!
+aa1[1] = "one";
+
+MutexedAA!(string[int]) aa2;
+aa2.setup();  // as above
+aa2[1] = "one";
+assert(aa1 == aa2);
+
+aa2[2] = "two";
+assert(aa1 != aa2);
+
+aa1[2] = "two";
+assert(aa1 == aa2);
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.opEquals.2.html b/lu.container.MutexedAA.opEquals.2.html new file mode 100644 index 00000000..341ef2be --- /dev/null +++ b/lu.container.MutexedAA.opEquals.2.html @@ -0,0 +1,47 @@ + + + + MutexedAA.opEquals (lu.container.MutexedAA.opEquals) + + + + + + + + + + +
+
+

MutexedAA.opEquals

Implements opEquals for this type, comparing the internal associative + array with a different one.

  1. auto opEquals(typeof(this) other)
  2. auto opEquals(AA other)
    struct MutexedAA(AA : V[K], V, K)
    opEquals
    ()

Parameters

other AA

Other associative array to compare the internal one with.

Return Value

Type: auto

true if the internal associative arrays are equal; false if not.

Examples

MutexedAA!(string[int]) aa1;
+aa1.setup();  // important!
+aa1[1] = "one";
+aa1[2] = "two";
+
+string[int] aa2;
+aa2[1] = "one";
+
+assert(aa1 != aa2);
+
+aa2[2] = "two";
+assert(aa1 == aa2);
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.opEquals.html b/lu.container.MutexedAA.opEquals.html new file mode 100644 index 00000000..361656d9 --- /dev/null +++ b/lu.container.MutexedAA.opEquals.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.container.MutexedAA.opIndex.html b/lu.container.MutexedAA.opIndex.html new file mode 100644 index 00000000..35e276b8 --- /dev/null +++ b/lu.container.MutexedAA.opIndex.html @@ -0,0 +1,41 @@ + + + + MutexedAA.opIndex (lu.container.MutexedAA.opIndex) + + + + + + + + + + +
+
+

MutexedAA.opIndex

aa[key] array retrieve operation, wrapped in a mutex lock.

struct MutexedAA(AA : V[K], V, K)
opIndex
(
K key
)

Parameters

key K

Key.

Return Value

Type: auto

The value assigned.

Examples

MutexedAA!(string[int]) aa;
+aa.setup();  // important!
+
+// ...
+
+string one = aa[1];
+writeln(aa[2]);
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.opIndexAssign.html b/lu.container.MutexedAA.opIndexAssign.html new file mode 100644 index 00000000..ef5ba486 --- /dev/null +++ b/lu.container.MutexedAA.opIndexAssign.html @@ -0,0 +1,39 @@ + + + + MutexedAA.opIndexAssign (lu.container.MutexedAA.opIndexAssign) + + + + + + + + + + +
+
+

MutexedAA.opIndexAssign

aa[key] = value array assign operation, wrapped in a mutex lock.

struct MutexedAA(AA : V[K], V, K)
opIndexAssign
(,
K key
)

Parameters

value V

Value.

key K

Key.

Return Value

Type: auto

The value assigned.

Examples

MutexedAA!(string[int]) aa;
+aa.setup();  // important!
+
+aa[1] = "one";
+aa[2] = "two";
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.opIndexOpAssign.html b/lu.container.MutexedAA.opIndexOpAssign.html new file mode 100644 index 00000000..b3a5517d --- /dev/null +++ b/lu.container.MutexedAA.opIndexOpAssign.html @@ -0,0 +1,43 @@ + + + + MutexedAA.opIndexOpAssign (lu.container.MutexedAA.opIndexOpAssign) + + + + + + + + + + +
+
+

MutexedAA.opIndexOpAssign

Implements index assign operations by mixin strings.

struct MutexedAA(AA : V[K], V, K)
void
opIndexOpAssign
(
string op
U
)
(,
K key
)
if (
is(U == V) ||
is(U == ElementEncodingType!V)
)

Parameters

op

Operation, here an index assign operator.

value U

Value.

key K

Key.

Examples

MutexedAA!(int[int]) aa;
+aa.setup();  // important!
+
+aa[1] = 42;
+aa[1] += 1;
+assert(aa[1] == 43);
+
+aa[1] *= 2;
+assert(aa[1] == 86);
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.opIndexUnary.html b/lu.container.MutexedAA.opIndexUnary.html new file mode 100644 index 00000000..3e363a0e --- /dev/null +++ b/lu.container.MutexedAA.opIndexUnary.html @@ -0,0 +1,39 @@ + + + + MutexedAA.opIndexUnary (lu.container.MutexedAA.opIndexUnary) + + + + + + + + + + +
+
+

MutexedAA.opIndexUnary

Implements unary operations by mixin strings.

struct MutexedAA(AA : V[K], V, K)
opIndexUnary
(
string op
)
(
K key
)

Parameters

op

Operation, here a unary operator.

key K

Key.

Return Value

Type: auto

The result of the operation.

Examples

MutexedAA!(int[int]) aa;
+aa.setup();  // important!
+
+aa[1] = 42;
+assert(-aa[1] == -42);
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.rehash.html b/lu.container.MutexedAA.rehash.html new file mode 100644 index 00000000..e30f4628 --- /dev/null +++ b/lu.container.MutexedAA.rehash.html @@ -0,0 +1,40 @@ + + + + MutexedAA.rehash (lu.container.MutexedAA.rehash) + + + + + + + + + + +
+
+

MutexedAA.rehash

Rehashes the internal associative array.

struct MutexedAA(AA : V[K], V, K)
rehash
()

Return Value

Type: auto

A reference to the rehashed internal array.

Examples

MutexedAA!(string[int]) aa;
+aa.setup();  // important!
+
+aa[1] = "one";
+aa[2] = "two";
+aa.rehash();
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.remove.html b/lu.container.MutexedAA.remove.html new file mode 100644 index 00000000..a86e42b7 --- /dev/null +++ b/lu.container.MutexedAA.remove.html @@ -0,0 +1,42 @@ + + + + MutexedAA.remove (lu.container.MutexedAA.remove) + + + + + + + + + + +
+
+

MutexedAA.remove

aa.remove(key) array operation, wrapped in a mutex lock.

struct MutexedAA(AA : V[K], V, K)
remove
(
K key
)

Parameters

key K

Key.

Return Value

Type: auto

Whatever aa.remove(key) returns.

Examples

MutexedAA!(string[int]) aa;
+aa.setup();  // important!
+
+aa[1] = "one";
+assert(aa.has(1));
+
+aa.remove(1);
+assert(!aa.has(1));
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.require.html b/lu.container.MutexedAA.require.html new file mode 100644 index 00000000..800e0c55 --- /dev/null +++ b/lu.container.MutexedAA.require.html @@ -0,0 +1,41 @@ + + + + MutexedAA.require (lu.container.MutexedAA.require) + + + + + + + + + + +
+
+

MutexedAA.require

Returns the value for the key key, inserting value lazily if it is not present.

struct MutexedAA(AA : V[K], V, K)
require
(
K key
,
lazy V value
)

Parameters

key K

Key.

value V

Lazy value.

Return Value

Type: auto

The value for the key key, or value if there was no value there.

Examples

MutexedAA!(string[int]) aa;
+aa.setup();  // important!
+
+assert(!aa.has(42));
+string hello = aa.require(42, "hello");
+assert(hello == "hello");
+assert(aa[42] == "hello");
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.setup.html b/lu.container.MutexedAA.setup.html new file mode 100644 index 00000000..8829c38c --- /dev/null +++ b/lu.container.MutexedAA.setup.html @@ -0,0 +1,36 @@ + + + + MutexedAA.setup (lu.container.MutexedAA.setup) + + + + + + + + + + +
+
+

MutexedAA.setup

Sets up this instance. Does nothing if it has already been set up.

Instantiates the mutex and minimally initialises the associative array + by assigning and removing a dummy value.

struct MutexedAA(AA : V[K], V, K)
nothrow
void
setup
()
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.uniqueKey.html b/lu.container.MutexedAA.uniqueKey.html new file mode 100644 index 00000000..314fe995 --- /dev/null +++ b/lu.container.MutexedAA.uniqueKey.html @@ -0,0 +1,44 @@ + + + + MutexedAA.uniqueKey (lu.container.MutexedAA.uniqueKey) + + + + + + + + + + +
+
+

MutexedAA.uniqueKey

Reserves a unique key in the associative array.

Note: The key type must be an integral type.

struct MutexedAA(AA : V[K], V, K)
static if(isIntegral!K)
uniqueKey
()
(
K min = 1
,
K max = K.max
,
V value = V.init
)

Parameters

min K

Optional minimum key value; defaults to 1`.

max K

Optional maximum key value; defaults to K.max, where K is + the key type of the passed associative array.

value V

Optional value to assign to the key; defaults to V.init, + where V is the value type of the passed associative array.

Return Value

Type: auto

A unique key for the passed associative array, for which there is now + a value of value.`

Examples

MutexedAA!(string[int]) aa;
+aa.setup();  // important!
+
+int i = aa.uniqueKey;
+assert(i > 0);
+assert(aa.has(i));
+assert(aa[i] == string.init);

See Also

+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.update.html b/lu.container.MutexedAA.update.html new file mode 100644 index 00000000..ff87ac07 --- /dev/null +++ b/lu.container.MutexedAA.update.html @@ -0,0 +1,50 @@ + + + + MutexedAA.update (lu.container.MutexedAA.update) + + + + + + + + + + +
+
+

MutexedAA.update

Updates the value for the key key in the internal associative array, + invoking the first of the passed delegate to insert a new value if it + doesn't exist, or the second selegate to modify it in place if it does.

Note: Doesn't compile with compilers earlier than version 2.088.

struct MutexedAA(AA : V[K], V, K)
static if(__VERSION__ >= 2088L)
void
update
(
U
)
(
K key
,
scope V delegate
()
createDg
,
scope U delegate
(
K
)
updateDg
)
if (
is(U == V) ||
is(U == void)
)

Parameters

key K

Key.

createDg V delegate
()

Delegate to invoke to create a new value if it doesn't exist.

updateDg U delegate
(
K
)

Delegate to invoke to update an existing value.

Examples

MutexedAA!(int[int]) aa;
+aa.setup();  // important!
+
+assert(!aa.has(1));
+
+aa.update(1,
+    () => 42,
+    (int i) => i + 1);
+assert(aa[1] == 42);
+
+aa.update(1,
+    () => 42,
+    (int i) => i + 1);
+assert(aa[1] == 43);
+ +
+ + + \ No newline at end of file diff --git a/lu.container.MutexedAA.values.html b/lu.container.MutexedAA.values.html new file mode 100644 index 00000000..bb463937 --- /dev/null +++ b/lu.container.MutexedAA.values.html @@ -0,0 +1,43 @@ + + + + MutexedAA.values (lu.container.MutexedAA.values) + + + + + + + + + + +
+
+

MutexedAA.values

Returns a new dynamic array of all the values in the internal associative array.

struct MutexedAA(AA : V[K], V, K)
values
()

Return Value

Type: auto

A new V[] of all the AA values.

Examples

MutexedAA!(int[int]) aa;
+aa.setup();  // important!
+aa[1] = 42;
+aa[2] = 99;
+
+auto values = aa.values;
+assert(values.canFind(42));
+assert(values.canFind(99));
+assert(!values.canFind(0));
+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA._lengthAtLastRehash.html b/lu.container.RehashingAA._lengthAtLastRehash.html new file mode 100644 index 00000000..4ea84583 --- /dev/null +++ b/lu.container.RehashingAA._lengthAtLastRehash.html @@ -0,0 +1,36 @@ + + + + RehashingAA._lengthAtLastRehash (lu.container.RehashingAA._lengthAtLastRehash) + + + + + + + + + + +
+
+

RehashingAA._lengthAtLastRehash

The number of keys (and length of the array) when the last rehash took place. + Private value.

struct RehashingAA(AA : V[K], V, K)
private
size_t _lengthAtLastRehash;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA._newKeysSinceLastRehash.html b/lu.container.RehashingAA._newKeysSinceLastRehash.html new file mode 100644 index 00000000..521de871 --- /dev/null +++ b/lu.container.RehashingAA._newKeysSinceLastRehash.html @@ -0,0 +1,35 @@ + + + + RehashingAA._newKeysSinceLastRehash (lu.container.RehashingAA._newKeysSinceLastRehash) + + + + + + + + + + +
+
+

RehashingAA._newKeysSinceLastRehash

The number of new entries that has been added since the last rehash. Private value.

struct RehashingAA(AA : V[K], V, K)
private
uint _newKeysSinceLastRehash;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA._numRehashes.html b/lu.container.RehashingAA._numRehashes.html new file mode 100644 index 00000000..5c272baa --- /dev/null +++ b/lu.container.RehashingAA._numRehashes.html @@ -0,0 +1,35 @@ + + + + RehashingAA._numRehashes (lu.container.RehashingAA._numRehashes) + + + + + + + + + + +
+
+

RehashingAA._numRehashes

The number of times this instance has rehashed itself. Private value.

struct RehashingAA(AA : V[K], V, K)
private
uint _numRehashes;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.aa.html b/lu.container.RehashingAA.aa.html new file mode 100644 index 00000000..8ed5f671 --- /dev/null +++ b/lu.container.RehashingAA.aa.html @@ -0,0 +1,35 @@ + + + + RehashingAA.aa (lu.container.RehashingAA.aa) + + + + + + + + + + +
+
+

RehashingAA.aa

Internal associative array.

struct RehashingAA(AA : V[K], V, K)
private
AA aa;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.aaOf.html b/lu.container.RehashingAA.aaOf.html new file mode 100644 index 00000000..d54a228a --- /dev/null +++ b/lu.container.RehashingAA.aaOf.html @@ -0,0 +1,35 @@ + + + + RehashingAA.aaOf (lu.container.RehashingAA.aaOf) + + + + + + + + + + +
+
+

RehashingAA.aaOf

Returns the internal associative array, for when the wrapper is insufficient.

struct RehashingAA(AA : V[K], V, K)
inout
aaOf
()

Return Value

Type: auto

The internal associative array.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.clear.html b/lu.container.RehashingAA.clear.html new file mode 100644 index 00000000..e63eb2e6 --- /dev/null +++ b/lu.container.RehashingAA.clear.html @@ -0,0 +1,35 @@ + + + + RehashingAA.clear (lu.container.RehashingAA.clear) + + + + + + + + + + +
+
+

RehashingAA.clear

Clears the internal associative array and all counters.

struct RehashingAA(AA : V[K], V, K)
void
clear
()
+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.dup.html b/lu.container.RehashingAA.dup.html new file mode 100644 index 00000000..a9260eb0 --- /dev/null +++ b/lu.container.RehashingAA.dup.html @@ -0,0 +1,35 @@ + + + + RehashingAA.dup (lu.container.RehashingAA.dup) + + + + + + + + + + +
+
+

RehashingAA.dup

Duplicates this. Explicitly copies the internal associative array.

struct RehashingAA(AA : V[K], V, K)
dup
()

Return Value

Type: auto

A duplicate of this object.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.html b/lu.container.RehashingAA.html new file mode 100644 index 00000000..88848d9b --- /dev/null +++ b/lu.container.RehashingAA.html @@ -0,0 +1,68 @@ + + + + RehashingAA (lu.container.RehashingAA) + + + + + + + + + + +
+
+

RehashingAA

A wrapper around a native associative array that you can controllably set to + automatically rehash as entries are added.

Constructors

this
this(AA aa)

Constructor.

Members

Functions

aaOf
auto aaOf()

Returns the internal associative array, for when the wrapper is insufficient.

clear
void clear()

Clears the internal associative array and all counters.

dup
auto dup()

Duplicates this. Explicitly copies the internal associative array.

length
auto length()

Returns the length of the internal associative array.

maybeRehash
auto maybeRehash()

Bumps the internal counter of new keys since the last rehash, and depending + on the resulting value of it, maybe rehashes.

newKeysSinceLastRehash
auto newKeysSinceLastRehash()

The number of new entries that has been added since the last rehash. Accessor.

numRehashes
auto numRehashes()

The number of times this instance has rehashed itself. Accessor.

opAssign
void opAssign(V[K] aa)

Inherit a native associative array into aa.

opBinaryRight
auto opBinaryRight(K key)

Wraps key in aa to the internal associative array.

opCast
auto opCast()

Allows for casting this into the base associative array type.

opIndexAssign
void opIndexAssign(V value, K key)

Assigns a value into the internal associative array. If it created a new + entry, then call maybeRehash to bump the internal counter and maybe rehash.

rehash
auto ref rehash()

Rehashes the internal associative array, bumping the rehash counter and + zeroing the keys-added counter. Additionally invokes the onRehashDg delegate.

remove
auto remove(K key)

Removes a key from the aa associative array by merely + invoking .remove.

Variables

_lengthAtLastRehash
size_t _lengthAtLastRehash;

The number of keys (and length of the array) when the last rehash took place. + Private value.

_newKeysSinceLastRehash
uint _newKeysSinceLastRehash;

The number of new entries that has been added since the last rehash. Private value.

_numRehashes
uint _numRehashes;

The number of times this instance has rehashed itself. Private value.

aa
AA aa;

Internal associative array.

minimumNeededForRehash
uint minimumNeededForRehash;

The minimum number of additions needed before the first rehash takes place.

onRehashDg
void delegate() onRehashDg;

Delegate called when rehashing takes place.

rehashThresholdMultiplier
double rehashThresholdMultiplier;

The modifier by how much more entries must be added before another rehash + takes place, with regards to the current aa length.

Parameters

AA

Associative array type.

V

Value type.

K

Key type.

Examples

import std.conv : to;
+
+RehashingAA!(int[string]) aa;
+aa.minimumNeededForRehash = 2;
+
+aa["abc"] = 123;
+aa["def"] = 456;
+assert((aa.newKeysSinceLastRehash == 2), aa.newKeysSinceLastRehash.to!string);
+assert((aa.numRehashes == 0), aa.numRehashes.to!string);
+aa["ghi"] = 789;
+assert((aa.numRehashes == 1), aa.numRehashes.to!string);
+assert((aa.newKeysSinceLastRehash == 0), aa.newKeysSinceLastRehash.to!string);
+aa.rehash();
+assert((aa.numRehashes == 2), aa.numRehashes.to!string);
+
+auto realAA = cast(int[string])aa;
+assert("abc" in realAA);
+assert("def" in realAA);
+
+auto alsoRealAA = aa.aaOf;
+assert("ghi" in realAA);
+assert("jkl" !in realAA);
+
+auto aa2 = aa.dup;
+aa2["jkl"] = 123;
+assert("jkl" in aa2);
+assert("jkl" !in aa);
+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.length.html b/lu.container.RehashingAA.length.html new file mode 100644 index 00000000..2927b84c --- /dev/null +++ b/lu.container.RehashingAA.length.html @@ -0,0 +1,35 @@ + + + + RehashingAA.length (lu.container.RehashingAA.length) + + + + + + + + + + +
+
+

RehashingAA.length

Returns the length of the internal associative array.

struct RehashingAA(AA : V[K], V, K)
const inout
length
()

Return Value

Type: auto

The length of the internal associative array.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.maybeRehash.html b/lu.container.RehashingAA.maybeRehash.html new file mode 100644 index 00000000..f44d0338 --- /dev/null +++ b/lu.container.RehashingAA.maybeRehash.html @@ -0,0 +1,36 @@ + + + + RehashingAA.maybeRehash (lu.container.RehashingAA.maybeRehash) + + + + + + + + + + +
+
+

RehashingAA.maybeRehash

Bumps the internal counter of new keys since the last rehash, and depending + on the resulting value of it, maybe rehashes.

struct RehashingAA(AA : V[K], V, K)
maybeRehash
()

Return Value

Type: auto

true if the associative array was rehashed; false if not.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.minimumNeededForRehash.html b/lu.container.RehashingAA.minimumNeededForRehash.html new file mode 100644 index 00000000..48a5a291 --- /dev/null +++ b/lu.container.RehashingAA.minimumNeededForRehash.html @@ -0,0 +1,35 @@ + + + + RehashingAA.minimumNeededForRehash (lu.container.RehashingAA.minimumNeededForRehash) + + + + + + + + + + +
+
+

RehashingAA.minimumNeededForRehash

The minimum number of additions needed before the first rehash takes place.

struct RehashingAA(AA : V[K], V, K)
uint minimumNeededForRehash;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.newKeysSinceLastRehash.html b/lu.container.RehashingAA.newKeysSinceLastRehash.html new file mode 100644 index 00000000..03da0168 --- /dev/null +++ b/lu.container.RehashingAA.newKeysSinceLastRehash.html @@ -0,0 +1,35 @@ + + + + RehashingAA.newKeysSinceLastRehash (lu.container.RehashingAA.newKeysSinceLastRehash) + + + + + + + + + + +
+
+

RehashingAA.newKeysSinceLastRehash

The number of new entries that has been added since the last rehash. Accessor.

struct RehashingAA(AA : V[K], V, K)
inout
newKeysSinceLastRehash
()

Return Value

Type: auto

The number of new entries that has been added since the last rehash.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.numRehashes.html b/lu.container.RehashingAA.numRehashes.html new file mode 100644 index 00000000..ed383fa8 --- /dev/null +++ b/lu.container.RehashingAA.numRehashes.html @@ -0,0 +1,35 @@ + + + + RehashingAA.numRehashes (lu.container.RehashingAA.numRehashes) + + + + + + + + + + +
+
+

RehashingAA.numRehashes

The number of times this instance has rehashed itself. Accessor.

struct RehashingAA(AA : V[K], V, K)
inout
numRehashes
()

Return Value

Type: auto

The number of times this instance has rehashed itself.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.onRehashDg.html b/lu.container.RehashingAA.onRehashDg.html new file mode 100644 index 00000000..23811545 --- /dev/null +++ b/lu.container.RehashingAA.onRehashDg.html @@ -0,0 +1,35 @@ + + + + RehashingAA.onRehashDg (lu.container.RehashingAA.onRehashDg) + + + + + + + + + + +
+
+

RehashingAA.onRehashDg

Delegate called when rehashing takes place.

struct RehashingAA(AA : V[K], V, K)
void delegate() onRehashDg;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.opAssign.html b/lu.container.RehashingAA.opAssign.html new file mode 100644 index 00000000..027eda04 --- /dev/null +++ b/lu.container.RehashingAA.opAssign.html @@ -0,0 +1,35 @@ + + + + RehashingAA.opAssign (lu.container.RehashingAA.opAssign) + + + + + + + + + + +
+
+

RehashingAA.opAssign

Inherit a native associative array into aa.

struct RehashingAA(AA : V[K], V, K)
void
opAssign
(
V[K] aa
)

Parameters

aa V[K]

Other associative array.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.opBinaryRight.html b/lu.container.RehashingAA.opBinaryRight.html new file mode 100644 index 00000000..4ac6ebf3 --- /dev/null +++ b/lu.container.RehashingAA.opBinaryRight.html @@ -0,0 +1,36 @@ + + + + RehashingAA.opBinaryRight (lu.container.RehashingAA.opBinaryRight) + + + + + + + + + + +
+
+

RehashingAA.opBinaryRight

Wraps key in aa to the internal associative array.

struct RehashingAA(AA : V[K], V, K)
inout
opBinaryRight
(
string op : "in"
)
(
K key
)

Parameters

op

Operation, here "in".

key K

Key.

Return Value

Type: auto

A pointer to the value of the key passed, or null if it isn't in + the associative array

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.opCast.html b/lu.container.RehashingAA.opCast.html new file mode 100644 index 00000000..1837d0f5 --- /dev/null +++ b/lu.container.RehashingAA.opCast.html @@ -0,0 +1,35 @@ + + + + RehashingAA.opCast (lu.container.RehashingAA.opCast) + + + + + + + + + + +
+
+

RehashingAA.opCast

Allows for casting this into the base associative array type.

struct RehashingAA(AA : V[K], V, K)
inout
opCast
(
T : AA
)
()

Parameters

T

Type to cast to, here the same as the type of aa.

Return Value

Type: auto

The internal associative array.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.opIndexAssign.html b/lu.container.RehashingAA.opIndexAssign.html new file mode 100644 index 00000000..50331eca --- /dev/null +++ b/lu.container.RehashingAA.opIndexAssign.html @@ -0,0 +1,36 @@ + + + + RehashingAA.opIndexAssign (lu.container.RehashingAA.opIndexAssign) + + + + + + + + + + +
+
+

RehashingAA.opIndexAssign

Assigns a value into the internal associative array. If it created a new + entry, then call maybeRehash to bump the internal counter and maybe rehash.

struct RehashingAA(AA : V[K], V, K)
void
opIndexAssign
(,
K key
)

Parameters

value V

Value.

key K

Key.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.rehash.html b/lu.container.RehashingAA.rehash.html new file mode 100644 index 00000000..83a4b425 --- /dev/null +++ b/lu.container.RehashingAA.rehash.html @@ -0,0 +1,36 @@ + + + + RehashingAA.rehash (lu.container.RehashingAA.rehash) + + + + + + + + + + +
+
+

RehashingAA.rehash

Rehashes the internal associative array, bumping the rehash counter and + zeroing the keys-added counter. Additionally invokes the onRehashDg delegate.

struct RehashingAA(AA : V[K], V, K)
ref
rehash
()

Return Value

Type: auto ref

A reference to the rehashed internal array.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.rehashThresholdMultiplier.html b/lu.container.RehashingAA.rehashThresholdMultiplier.html new file mode 100644 index 00000000..e79a78ff --- /dev/null +++ b/lu.container.RehashingAA.rehashThresholdMultiplier.html @@ -0,0 +1,37 @@ + + + + RehashingAA.rehashThresholdMultiplier (lu.container.RehashingAA.rehashThresholdMultiplier) + + + + + + + + + + +
+
+

RehashingAA.rehashThresholdMultiplier

The modifier by how much more entries must be added before another rehash + takes place, with regards to the current aa length.

A multiplier of 2.0 means the associative array will be rehashed as + soon as its length doubles in size. Must be more than 1.

struct RehashingAA(AA : V[K], V, K)
double rehashThresholdMultiplier;
+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.remove.html b/lu.container.RehashingAA.remove.html new file mode 100644 index 00000000..ff5bd083 --- /dev/null +++ b/lu.container.RehashingAA.remove.html @@ -0,0 +1,36 @@ + + + + RehashingAA.remove (lu.container.RehashingAA.remove) + + + + + + + + + + +
+
+

RehashingAA.remove

Removes a key from the aa associative array by merely + invoking .remove.

struct RehashingAA(AA : V[K], V, K)
remove
(
K key
)

Parameters

key K

The key to remove.

Return Value

Type: auto

Whatever aa.remove(key) returns.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.RehashingAA.this.html b/lu.container.RehashingAA.this.html new file mode 100644 index 00000000..59dd80a1 --- /dev/null +++ b/lu.container.RehashingAA.this.html @@ -0,0 +1,35 @@ + + + + RehashingAA.this (lu.container.RehashingAA.this) + + + + + + + + + + +
+
+

RehashingAA.this

Constructor.

struct RehashingAA(AA : V[K], V, K)
pure @safe nothrow @nogc
this
(
AA aa
)

Parameters

aa AA

Associative arary to inherit. Taken by reference for now.

+ +
+ + + \ No newline at end of file diff --git a/lu.container.html b/lu.container.html new file mode 100644 index 00000000..e78fa3e2 --- /dev/null +++ b/lu.container.html @@ -0,0 +1,128 @@ + + + + lu.container (lu.container) + + + + + + + + + + +
+
+

lu.container

Containers.

Members

Structs

Buffer
struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)

Simple buffer/queue for storing and fetching items of any type T. + Does not use manual memory allocation.

CircularBuffer
struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)

Simple circular-ish buffer for storing items of type T that discards elements + when the maximum size is reached. Does not use manual memory allocation.

MutexedAA
struct MutexedAA(AA : V[K], V, K)

An associative array and a Mutex. Wraps associative + array operations in mutex locks.

RehashingAA
struct RehashingAA(AA : V[K], V, K)

A wrapper around a native associative array that you can controllably set to + automatically rehash as entries are added.

Examples

1 {
+2     Buffer!string buffer;
+3 
+4     buffer.put("abc");
+5     buffer.put("def");
+6     assert(!buffer.empty);
+7     assert(buffer.front == "abc");
+8     buffer.popFront();
+9     assert(buffer.front == "def");
+10     buffer.popFront();
+11     assert(buffer.empty);
+12 }
+13 {
+14     Buffer!(char, Yes.dynamic, 3) buffer;
+15 
+16     assert(!buffer.buf.length);
+17     buffer ~= 'a';
+18     assert(buffer.buf.length == 3);
+19     buffer ~= 'b';
+20     buffer ~= 'c';
+21     assert(buffer.length == 3);
+22     buffer ~= 'd';
+23     assert(buffer.buf.length > 3);
+24     assert(buffer[0..5] == "abcd");
+25     buffer.clear();
+26     assert(buffer.empty);
+27 }
+28 {
+29     RehashingAA!(int[string]) aa;
+30     aa.minimumNeededForRehash = 2;
+31 
+32     aa["abc"] = 123;
+33     aa["def"] = 456;
+34     assert((aa.newKeysSinceLastRehash == 2), aa.newKeysSinceLastRehash.to!string);
+35     assert((aa.numRehashes == 0), aa.numRehashes.to!string);
+36     aa["ghi"] = 789;
+37     assert((aa.numRehashes == 1), aa.numRehashes.to!string);
+38     assert((aa.newKeysSinceLastRehash == 0), aa.newKeysSinceLastRehash.to!string);
+39     aa.rehash();
+40     assert((aa.numRehashes == 2), aa.numRehashes.to!string);
+41 
+42     auto realAA = cast(int[string])aa;
+43     assert("abc" in realAA);
+44     assert("def" in realAA);
+45 
+46     auto alsoRealAA = aa.aaOf;
+47     assert("ghi" in realAA);
+48     assert("jkl" !in realAA);
+49 
+50     auto aa2 = aa.dup;
+51     aa2["jkl"] = 123;
+52     assert("jkl" in aa2);
+53     assert("jkl" !in aa);
+54 }
+55 {
+56     MutexedAA!(string[int]) aa;
+57     aa.setup();  // important!
+58 
+59     aa[1] = "one";
+60     aa[2] = "two";
+61     aa[3] = "three";
+62 
+63     auto hasOne = aa.has(1);
+64     assert(hasOne);
+65     assert(aa[1] == "one");
+66 
+67     assert(aa[2] == "two");
+68 
+69     auto three = aa.get(3);
+70     assert(three == "three");
+71 
+72     auto four = aa.get(4, "four");
+73     assert(four == "four");
+74 
+75     auto five = aa.require(5, "five");
+76     assert(five == "five");
+77     assert(aa[5] == "five");
+78 
+79     auto keys = aa.keys;
+80     assert(keys.canFind(1));
+81     assert(keys.canFind(5));
+82     assert(!keys.canFind(6));
+83 
+84     auto values = aa.values;
+85     assert(values.canFind("one"));
+86     assert(values.canFind("four"));
+87     assert(!values.canFind("six"));
+88 
+89     aa.rehash();
+90 }

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.conv.Enum.fromString.html b/lu.conv.Enum.fromString.html new file mode 100644 index 00000000..f41bc520 --- /dev/null +++ b/lu.conv.Enum.fromString.html @@ -0,0 +1,48 @@ + + + + Enum.fromString (lu.conv.Enum.fromString) + + + + + + + + + + +
+
+

Enum.fromString

Takes the member of an enum by string and returns that enum member.

It lowers to a big switch of the enum member strings. It is faster than + std.conv.to and generates less template bloat. However, it does not work + with enums where multiple members share the same values, as the big switch + ends up getting duplicate cases.

Taken from: https://forum.dlang.org/post/bfnwstkafhfgihavtzsz@forum.dlang.org + written by Stephan Koch (https://github.com/UplinkCoder). + Used with permission.

template Enum(E)
@safe pure
E
fromString
(
const string enumstring
)
if (
is(E == enum)
)

Parameters

enumstring string

the string name of an enum member.

Return Value

Type: E

The enum member whose name matches the enumstring string (not whose + *value* matches the string).

Throws

ConvException if no matching enum member with the + passed name could be found.

Bugs

Does not work with enums that have members with duplicate values.

Examples

enum SomeEnum { one, two, three };
+
+SomeEnum foo = Enum!SomeEnum.fromString("one");
+SomeEnum bar = Enum!SomeEnum.fromString("three");
+
+assert(foo == SomeEnum.one);
+assert(bar == SomeEnum.three);
+ +
+ + + \ No newline at end of file diff --git a/lu.conv.Enum.html b/lu.conv.Enum.html new file mode 100644 index 00000000..dc01a653 --- /dev/null +++ b/lu.conv.Enum.html @@ -0,0 +1,63 @@ + + + + Enum (lu.conv.Enum) + + + + + + + + + + +
+
+

Enum

Template housing optimised functions to get the string name of an enum + member, or the enum member of a name string.

std.conv.to is typically the go-to for this job; however it quickly bloats + the binary and is not performant on larger enums.

@safe
template Enum (
E
) if (
is(E == enum)
) {}

Members

Functions

fromString
E fromString(string enumstring)

Takes the member of an enum by string and returns that enum member.

toString
string toString(E value)

The inverse of fromString, this function takes an enum member value + and returns its string identifier.

Parameters

E

enum to base this template on.

Examples

import std.conv : ConvException;
+import std.exception  : assertThrown;
+
+enum T
+{
+    UNSET,
+    QUERY,
+    PRIVMSG,
+    RPL_ENDOFMOTD
+}
+
+with (T)
+{
+    static assert(Enum!T.fromString("QUERY") == QUERY);
+    static assert(Enum!T.fromString("PRIVMSG") == PRIVMSG);
+    static assert(Enum!T.fromString("RPL_ENDOFMOTD") == RPL_ENDOFMOTD);
+    static assert(Enum!T.fromString("UNSET") == UNSET);
+    assertThrown!ConvException(Enum!T.fromString("DOESNTEXIST"));  // needs @system
+}
+
+with (T)
+{
+    static assert(Enum!T.toString(QUERY) == "QUERY");
+    static assert(Enum!T.toString(PRIVMSG) == "PRIVMSG");
+    static assert(Enum!T.toString(RPL_ENDOFMOTD) == "RPL_ENDOFMOTD");
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.conv.Enum.toString.html b/lu.conv.Enum.toString.html new file mode 100644 index 00000000..83e88e57 --- /dev/null +++ b/lu.conv.Enum.toString.html @@ -0,0 +1,42 @@ + + + + Enum.toString (lu.conv.Enum.toString) + + + + + + + + + + +
+
+

Enum.toString

The inverse of fromString, this function takes an enum member value + and returns its string identifier.

It lowers to a big switch of the enum members. It is faster than + std.conv.to and generates less template bloat.

Taken from: https://forum.dlang.org/post/bfnwstkafhfgihavtzsz@forum.dlang.org + written by Stephan Koch (https://github.com/UplinkCoder). + Used with permission.

template Enum(E)
@safe pure nothrow
string
toString
()
if (
is(E == enum)
)

Parameters

value E

Enum member whose string name we want.

Return Value

Type: string

The string name of the passed enum member.

Examples

enum SomeEnum { one, two, three };
+
+string foo = Enum!SomeEnum.toString(one);
+assert(foo == "one");
+ +
+ + + \ No newline at end of file diff --git a/lu.conv.enumToString.html b/lu.conv.enumToString.html new file mode 100644 index 00000000..ed27da11 --- /dev/null +++ b/lu.conv.enumToString.html @@ -0,0 +1,48 @@ + + + + enumToString (lu.conv.enumToString) + + + + + + + + + + +
+
+

enumToString

Convenience wrapper around Enum that infers the type of the passed enum member.

@safe
enumToString
(
E
)
(
const E value
)
if (
is(E == enum)
)

Parameters

value E

Enum member whose string name we want.

Return Value

Type: auto

The string name of the passed enum member.

Examples

enum T
+{
+    UNSET,
+    QUERY,
+    PRIVMSG,
+    RPL_ENDOFMOTD
+}
+
+with (T)
+{
+    static assert(enumToString(QUERY) == "QUERY");
+    static assert(enumToString(PRIVMSG) == "PRIVMSG");
+    static assert(enumToString(RPL_ENDOFMOTD) == "RPL_ENDOFMOTD");
+}

See Also

+ +
+ + + \ No newline at end of file diff --git a/lu.conv.html b/lu.conv.html new file mode 100644 index 00000000..54365925 --- /dev/null +++ b/lu.conv.html @@ -0,0 +1,46 @@ + + + + lu.conv (lu.conv) + + + + + + + + + + +
+
+

lu.conv

This module contains functions that in one way or another converts its + arguments into something else.

Credit for Enum goes to Stephan Koch (https://github.com/UplinkCoder).

Members

Functions

enumToString
auto enumToString(E value)

Convenience wrapper around Enum that infers the type of the passed enum member.

numFromHex
auto numFromHex(string hex, Flag!"acceptLowercase" acceptLowercase)

Returns the decimal value of a hex number in string form.

rgbFromHex
auto rgbFromHex(string hexString, Flag!"acceptLowercase" acceptLowercase)

Convenience wrapper that takes a hex string and populates a Voldemort + struct with its RR, GG and BB components.

toAlpha
string toAlpha(Num num)

Translates an integer into an alphanumeric string. Assumes ASCII. + Overload that returns the string.

toAlphaInto
void toAlphaInto(Num num, Sink sink)

Translates an integer into an alphanumeric string. Assumes ASCII. + Overload that takes an output range sink.

Templates

Enum
template Enum(E)

Template housing optimised functions to get the string name of an enum + member, or the enum member of a name string.

Examples

enum SomeEnum { one, two, three };
+
+SomeEnum foo = Enum!SomeEnum.fromString("one");
+SomeEnum bar = Enum!SomeEnum.fromString("three");
+
+assert(foo == SomeEnum.one);
+assert(bar == SomeEnum.three);

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.conv.numFromHex.html b/lu.conv.numFromHex.html new file mode 100644 index 00000000..7b7d75e6 --- /dev/null +++ b/lu.conv.numFromHex.html @@ -0,0 +1,36 @@ + + + + numFromHex (lu.conv.numFromHex) + + + + + + + + + + +
+
+

numFromHex

Returns the decimal value of a hex number in string form.

@safe pure
numFromHex
(
const string hex
,
const Flag!"acceptLowercase" acceptLowercase = Yes.acceptLowercase
)

Parameters

hex string

Hexadecimal number in string form.

acceptLowercase Flag!"acceptLowercase"

Flag of whether or not to accept rrggbb in lowercase form.

Return Value

Type: auto

An integer equalling the value of the passed hexadecimal string.

Throws

ConvException if the hex string was malformed.

Examples

int fifteen = numFromHex("F");
+int twofiftyfive = numFromHex("FF");
+ +
+ + + \ No newline at end of file diff --git a/lu.conv.rgbFromHex.html b/lu.conv.rgbFromHex.html new file mode 100644 index 00000000..a1f14af5 --- /dev/null +++ b/lu.conv.rgbFromHex.html @@ -0,0 +1,66 @@ + + + + rgbFromHex (lu.conv.rgbFromHex) + + + + + + + + + + +
+
+

rgbFromHex

Convenience wrapper that takes a hex string and populates a Voldemort + struct with its RR, GG and BB components.

This is to be used when mapping a #RRGGBB colour to their decimal + red/green/blue equivalents.

@safe
rgbFromHex
(
const string hexString
,
const Flag!"acceptLowercase" acceptLowercase = No.acceptLowercase
)

Parameters

hexString string

Hexadecimal number (colour) in string form.

acceptLowercase Flag!"acceptLowercase"

Whether or not to accept the rrggbb string in + lowercase letters.

Return Value

Type: auto

A Voldemort struct with r, g and b members,

Examples

import std.conv : text;
+{
+    auto rgb = rgbFromHex("000102");
+
+    assert((rgb.r == 0), rgb.r.text);
+    assert((rgb.g == 1), rgb.g.text);
+    assert((rgb.b == 2), rgb.b.text);
+}
+{
+    auto rgb = rgbFromHex("#FFFFFF");
+
+    assert((rgb.r == 255), rgb.r.text);
+    assert((rgb.g == 255), rgb.g.text);
+    assert((rgb.b == 255), rgb.b.text);
+}
+{
+    auto rgb = rgbFromHex("#3C507D");
+
+    assert((rgb.r == 60), rgb.r.text);
+    assert((rgb.g == 80), rgb.b.text);
+    assert((rgb.b == 125), rgb.b.text);
+}
+{
+    auto rgb = rgbFromHex("9a4B7c", Yes.acceptLowercase);
+
+    assert((rgb.r == 154), rgb.r.text);
+    assert((rgb.g == 75), rgb.g.text);
+    assert((rgb.b == 124), rgb.b.text);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.conv.toAlpha.html b/lu.conv.toAlpha.html new file mode 100644 index 00000000..2dde8f52 --- /dev/null +++ b/lu.conv.toAlpha.html @@ -0,0 +1,79 @@ + + + + toAlpha (lu.conv.toAlpha) + + + + + + + + + + +
+
+

toAlpha

Translates an integer into an alphanumeric string. Assumes ASCII. + Overload that returns the string.

Merely leverages toAlphaInto.

@safe pure
string
toAlpha
(
size_t maxDigits = 19
uint leadingZeroes = 0
Num
)
(
const Num num
)

Parameters

maxDigits

The maximum number of digits to expect input of.

leadingZeroes

The minimum amount of leading zeroes to include in the + output, mirroring the format specifier "%0nd".

num Num

Integer to translate into string.

Return Value

Type: string

The passed integer num in string form.

Examples

int num = 12345;
+string asString = num.toAlpha;
+assert(asString == "12345");
+assert(asString == num.to!string);
{
+    enum num = 123_456;
+    immutable translated = num.toAlpha;
+    assert((translated == "123456"), translated);
+}
+{
+    enum num = 0;
+    immutable translated = num.toAlpha;
+    assert((translated == "0"), translated);
+}
+{
+    enum num = 999;
+    immutable translated = num.toAlpha;
+    assert((translated == "999"), translated);
+}
+{
+    enum num = -987;
+    immutable translated = num.toAlpha;
+    assert((translated == "-987"), translated);
+}
+{
+    enum num = 123;
+    immutable translated = num.toAlpha!(12, 6);
+    assert((translated == "000123"), translated);
+}
+{
+    enum num = -1;
+    immutable translated = num.toAlpha!(3, 3);
+    assert((translated == "-001"), translated);
+}
+{
+    enum num = -123_456_789_012_345L;
+    immutable translated = num.toAlpha!15;
+    assert((translated == "-123456789012345"), translated);
+}
+{
+    enum num = long.min;
+    immutable translated = num.toAlpha;
+    assert((translated == "-9223372036854775808"), translated);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.conv.toAlphaInto.html b/lu.conv.toAlphaInto.html new file mode 100644 index 00000000..8503a458 --- /dev/null +++ b/lu.conv.toAlphaInto.html @@ -0,0 +1,92 @@ + + + + toAlphaInto (lu.conv.toAlphaInto) + + + + + + + + + + +
+
+

toAlphaInto

Translates an integer into an alphanumeric string. Assumes ASCII. + Overload that takes an output range sink.

@safe
void
toAlphaInto
(
size_t maxDigits = 19
uint leadingZeroes = 0
Num
Sink
)
(
const Num num
,
auto ref Sink sink
)
if (
isIntegral!Num &&
isOutputRange!(Sink, char[])
)

Parameters

maxDigits

The maximum number of digits to expect input of.

leadingZeroes

The minimum amount of leading zeroes to include in the + output, mirroring the format specifier "%0nd".

num Num

Integer to translate into string.

sink Sink

Output range sink.

Examples

Appender!(char[]) sink;
+int num = 12345;
+num.toAlphaInto(sink);
+assert(sink.data == "12345");
+assert(sink.data == num.to!string);
import std.array : Appender;
+
+Appender!(char[]) sink;
+
+{
+    enum num = 123_456;
+    num.toAlphaInto(sink);
+    assert((sink.data == "123456"), sink.data);
+    sink.clear();
+}
+{
+    enum num = 0;
+    num.toAlphaInto(sink);
+    assert((sink.data == "0"), sink.data);
+    sink.clear();
+}
+{
+    enum num = 999;
+    num.toAlphaInto(sink);
+    assert((sink.data == "999"), sink.data);
+    sink.clear();
+}
+{
+    enum num = -987;
+    num.toAlphaInto(sink);
+    assert((sink.data == "-987"), sink.data);
+    sink.clear();
+}
+{
+    enum num = 123;
+    num.toAlphaInto!(12, 6)(sink);
+    assert((sink.data == "000123"), sink.data);
+    sink.clear();
+}
+{
+    enum num = -1;
+    num.toAlphaInto!(3, 3)(sink);
+    assert((sink.data == "-001"), sink.data);
+    sink.clear();
+}
+{
+    enum num = -123_456_789_012_345L;
+    num.toAlphaInto!15(sink);
+    assert((sink.data == "-123456789012345"), sink.data);
+    sink.clear();
+}
+{
+    enum num = long.min;
+    num.toAlphaInto(sink);
+    assert((sink.data == "-9223372036854775808"), sink.data);
+    //sink.clear();
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.deltastrings.formatDeltaInto.html b/lu.deltastrings.formatDeltaInto.html new file mode 100644 index 00000000..0f29baf5 --- /dev/null +++ b/lu.deltastrings.formatDeltaInto.html @@ -0,0 +1,223 @@ + + + + formatDeltaInto (lu.deltastrings.formatDeltaInto) + + + + + + + + + + +
+
+

formatDeltaInto

Constructs statement lines for each changed field (or the delta) between two + instances of a struct and stores them into a passed output sink.

void
formatDeltaInto
(
Flag!"asserts" asserts = No.asserts
Sink
QualThing
)
(
auto ref Sink sink
,
auto ref QualThing before
,
auto ref QualThing after
,
const uint indents = 0
,
const string submember = string.init
)
if (
isOutputRange!(Sink, char[]) &&
isAggregateType!QualThing
)

Parameters

asserts

Whether or not to build assert statements or assignment statements.

sink Sink

Output buffer to write to.

before QualThing

Original struct object.

after QualThing

Changed struct object.

indents uint

The number of tabs to indent the lines with.

submember string

The string name of a recursing symbol, if applicable.

Examples

struct Foo
+{
+    string s;
+    int i;
+    bool b;
+}
+
+Foo altered;
+
+altered.s = "some string";
+altered.i = 42;
+altered.b = true;
+
+Appender!(char[]) sink;
+sink.formatDeltaInto!(No.asserts)(Foo.init, altered);
1     import lu.uda : Hidden;
+2     import std.array : Appender;
+3 
+4     Appender!(char[]) sink;
+5     sink.reserve(1024);
+6 
+7     struct Server
+8     {
+9         string address;
+10         ushort port;
+11         bool connected;
+12     }
+13 
+14     struct Connection
+15     {
+16         enum State
+17         {
+18             unset,
+19             disconnected,
+20             connected,
+21         }
+22 
+23         State state;
+24         string nickname;
+25         @Hidden string user;
+26         @Hidden string password;
+27         Server server;
+28     }
+29 
+30     Connection conn;
+31 
+32     with (conn)
+33     {
+34         state = Connection.State.connected;
+35         nickname = "NICKNAME";
+36         user = "USER";
+37         password = "hunter2";
+38         server.address = "address.tld";
+39         server.port = 1337;
+40     }
+41 
+42     sink.formatDeltaInto!(No.asserts)(Connection.init, conn, 0, "conn");
+43 
+44     assert(sink.data ==
+45 `conn.state = Connection.State.connected;
+46 conn.nickname = "NICKNAME";
+47 conn.server.address = "address.tld";
+48 conn.server.port = 1337;
+49 `, '\n' ~ sink.data);
+50 
+51     sink = typeof(sink).init;
+52 
+53     sink.formatDeltaInto!(Yes.asserts)(Connection.init, conn, 0, "conn");
+54 
+55     assert(sink.data ==
+56 `assert((conn.state == Connection.State.connected), Enum!(Connection.State).toString(conn.state));
+57 assert((conn.nickname == "NICKNAME"), conn.nickname);
+58 assert((conn.server.address == "address.tld"), conn.server.address);
+59 assert((conn.server.port == 1337), conn.server.port.to!string);
+60 `, '\n' ~ sink.data);
+61 
+62     struct Foo
+63     {
+64         string s;
+65         int i;
+66         bool b;
+67         char c;
+68     }
+69 
+70     Foo f1;
+71     f1.s = "string";
+72     f1.i = 42;
+73     f1.b = true;
+74     f1.c = '$';
+75 
+76     Foo f2 = f1;
+77     f2.s = "yarn";
+78     f2.b = false;
+79     f2.c = '#';
+80 
+81     sink = typeof(sink).init;
+82 
+83     sink.formatDeltaInto!(No.asserts)(f1, f2);
+84     assert(sink.data ==
+85 `s = "yarn";
+86 b = false;
+87 c = '#';
+88 `, '\n' ~ sink.data);
+89 
+90     sink = typeof(sink).init;
+91 
+92     sink.formatDeltaInto!(Yes.asserts)(f1, f2);
+93     assert(sink.data ==
+94 `assert((s == "yarn"), s);
+95 assert(!b);
+96 assert((c == '#'), c.to!string);
+97 `, '\n' ~ sink.data);
+98 
+99     sink = typeof(sink).init;
+100 
+101     {
+102         struct S
+103         {
+104             int i;
+105         }
+106 
+107         class C
+108         {
+109             string s;
+110             bool b;
+111             S child;
+112         }
+113 
+114         C c1 = new C;
+115         C c2 = new C;
+116 
+117         c2.s = "harbl";
+118         c2.b = true;
+119         c2.child.i = 42;
+120 
+121         sink.formatDeltaInto!(No.asserts)(c1, c2);
+122         assert(sink.data ==
+123 `s = "harbl";
+124 b = true;
+125 child.i = 42;
+126 `, '\n' ~ sink.data);
+127 
+128         sink = typeof(sink).init;
+129 
+130         sink.formatDeltaInto!(Yes.asserts)(c1, c2);
+131         assert(sink.data ==
+132 `assert((s == "harbl"), s);
+133 assert(b);
+134 assert((child.i == 42), child.i.to!string);
+135 `, '\n' ~ sink.data);
+136     }
+137     {
+138         struct Blah
+139         {
+140             int[5] arr;
+141             string[3] sarr;
+142             char[2] carr;
+143         }
+144 
+145         Blah b1;
+146         Blah b2;
+147         b2.arr = [ 1, 0, 3, 0, 5 ];
+148         b2.sarr = [ "hello", string.init, "world" ];
+149         b2.carr = [ 'a', char.init ];
+150 
+151         sink = typeof(sink).init;
+152 
+153         sink.formatDeltaInto(b1, b2);
+154         assert(sink.data ==
+155 `arr[0] = 1;
+156 arr[2] = 3;
+157 arr[4] = 5;
+158 sarr[0] = "hello";
+159 sarr[2] = "world";
+160 carr[0] = 'a';
+161 `);
+162 
+163         sink = typeof(sink).init;
+164 
+165         sink.formatDeltaInto!(Yes.asserts)(b1, b2);
+166         assert(sink.data ==
+167 `assert((arr[0] == 1), arr[0].to!string);
+168 assert((arr[2] == 3), arr[2].to!string);
+169 assert((arr[4] == 5), arr[4].to!string);
+170 assert((sarr[0] == "hello"), sarr[0]);
+171 assert((sarr[2] == "world"), sarr[2]);
+172 assert((carr[0] == 'a'), carr[0].to!string);
+173 `);
+174     }
+ +
+ + + \ No newline at end of file diff --git a/lu.deltastrings.html b/lu.deltastrings.html new file mode 100644 index 00000000..23ef05e3 --- /dev/null +++ b/lu.deltastrings.html @@ -0,0 +1,82 @@ + + + + lu.deltastrings (lu.deltastrings) + + + + + + + + + + +
+
+

lu.deltastrings

Functions used to generate strings of statements describing the differences + (or delta) between two instances of a struct or class of the same type. + They can be either assignment statements or assert statements.

Members

Enums

Hidden (from lu.uda)
enum Hidden via public +import lu.uda : Hidden;

UDA conveying that this member contains sensitive information and should not + be printed in clear text; e.g. passwords.

Functions

formatDeltaInto
void formatDeltaInto(Sink sink, QualThing before, QualThing after, uint indents, string submember)

Constructs statement lines for each changed field (or the delta) between two + instances of a struct and stores them into a passed output sink.

Examples

struct Foo
+{
+    string s;
+    int i;
+    bool b;
+}
+
+Foo altered;
+
+altered.s = "some string";
+altered.i = 42;
+altered.b = true;
+
+Appender!(char[]) sink;
+
+// Fill with delta between `Foo.init` and modified `altered`
+sink.formatDeltaInto!(No.asserts)(Foo.init, altered);
+
+assert(sink.data ==
+`s = "some string";
+i = 42;
+b = true;
+`);
+sink.clear();
+
+// Do the same but prepend the name "altered" to the member names
+sink.formatDeltaInto!(No.asserts)(Foo.init, altered, 0, "altered");
+
+assert(sink.data ==
+`altered.s = "some string";
+altered.i = 42;
+altered.b = true;
+`);
+sink.clear();
+
+// Generate assert statements instead, for easy copy/pasting into unittest blocks
+sink.formatDeltaInto!(Yes.asserts)(Foo.init, altered, 0, "altered");
+
+assert(sink.data ==
+`assert((altered.s == "some string"), altered.s);
+assert((altered.i == 42), altered.i.to!string);
+assert(altered.b, altered.b.to!string);
+`);

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.html b/lu.html new file mode 100644 index 00000000..0a63192e --- /dev/null +++ b/lu.html @@ -0,0 +1,45 @@ + + + + lu (lu) + + + + + + + + + + +
+
+

lu

lu is a general purpose library, doing a little bit of everything.

It complements the standard library and is not a replacement for it.

Modules

array
module lu.array

Simple array utilities.

common
module lu.common

Functionality generic enough to be used in several places.

container
module lu.container

Containers.

conv
module lu.conv

This module contains functions that in one way or another converts its + arguments into something else.

deltastrings
module lu.deltastrings

Functions used to generate strings of statements describing the differences + (or delta) between two instances of a struct or class of the same type. + They can be either assignment statements or assert statements.

json
module lu.json

Simple JSON wrappers around Phobos' std.json to make keeping JSON storages easier. + This is not a replacement for std.json; it merely extends it.

meld
module lu.meld

This module contains the meldInto functions; functions that take two + structs or classes of the same type and combine them, creating a resulting + object with the union of the members of both parents. Array and associative + array variants exist too.

numeric
module lu.numeric

Functions and templates that do numeric calculations or other manipulation, + in some way or another.

objmanip
module lu.objmanip

This module contains functions that in some way or another manipulates + struct and class instances, as well as (associative) arrays.

semver
module lu.semver

SemVer information about the current release.

serialisation
module lu.serialisation

Various functions related to serialising and deserialising structs into/from + .ini-like files.

string
module lu.string

String manipulation functions complementing the standard library.

traits
module lu.traits

Various compile-time traits and cleverness.

typecons
module lu.typecons

Type constructors.

uda
module lu.uda

Common user-defined attributes (UDAs).

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.json.JSONStorage.KeyOrderStrategy.html b/lu.json.JSONStorage.KeyOrderStrategy.html new file mode 100644 index 00000000..66105efb --- /dev/null +++ b/lu.json.JSONStorage.KeyOrderStrategy.html @@ -0,0 +1,38 @@ + + + + JSONStorage.KeyOrderStrategy (lu.json.JSONStorage.KeyOrderStrategy) + + + + + + + + + + +
+
+

JSONStorage.KeyOrderStrategy

Strategy in which to sort object-type JSON keys when we format/serialise + the stored storage to string.

Values

ValueMeaning
passthrough

Order is as JSONValue.toPrettyString + formats it.

sorted

Sorted by key.

reverse

Reversely sorted by key.

inGivenOrder

Keys are listed in the order given in a passed string[] array.

Actual keys not present in the array are not included in the output, + and keys not existing yet present in the array are added as empty.

+ +
+ + + \ No newline at end of file diff --git a/lu.json.JSONStorage.html b/lu.json.JSONStorage.html new file mode 100644 index 00000000..0cdca980 --- /dev/null +++ b/lu.json.JSONStorage.html @@ -0,0 +1,63 @@ + + + + JSONStorage (lu.json.JSONStorage) + + + + + + + + + + +
+
+

JSONStorage

A wrapped JSONValue with helper functions.

Alias This

storage

Members

Enums

KeyOrderStrategy
enum KeyOrderStrategy

Strategy in which to sort object-type JSON keys when we format/serialise + the stored storage to string.

Functions

load
void load(string filename)

Loads JSON from disk.

reset
void reset()

Initialises and clears the JSONValue, preparing + it for object storage.

save
void save(string filename, string[] givenOrder)

Saves the JSON storage to disk. Formatting is done as specified by the + passed KeyOrderStrategy argument.

serialiseInto
void serialiseInto(Sink sink, string[] givenOrder)

Formats an object-type JSON storage into an output range sink.

serialiseInto
void serialiseInto(Sink sink)

Formats an object-type JSON storage into an output range sink.

Variables

storage
JSONValue storage;

The underlying JSONValue storage of this JSONStorage.

Examples

JSONStorage s;
+
+s.reset();  // not always necessary
+
+s.storage["foo"] = null;  // JSONValue quirk
+s.storage["foo"]["abc"] = JSONValue(42);
+s.storage["foo"]["def"] = JSONValue(3.14f);
+s.storage["foo"]["ghi"] = JSONValue([ "bar", "baz", "qux" ]);
+s.storage["bar"] = JSONValue("asdf");
+
+assert(s.storage.length == 2);
import std.conv : text;
+import std.json : JSONValue;
+
+JSONStorage s;
+s.reset();
+
+s.storage["key"] = null;
+s.storage["key"]["subkey1"] = "abc";
+s.storage["key"]["subkey2"] = "def";
+s.storage["key"]["subkey3"] = "ghi";
+assert((s.storage["key"].object.length == 3), s.storage["key"].object.length.text);
+
+s.storage["foo"] = null;
+s.storage["foo"]["arr"] = JSONValue([ "blah "]);
+s.storage["foo"]["arr"].array ~= JSONValue("bluh");
+assert((s.storage["foo"]["arr"].array.length == 2), s.storage["foo"]["arr"].array.length.text);
+ +
+ + + \ No newline at end of file diff --git a/lu.json.JSONStorage.load.html b/lu.json.JSONStorage.load.html new file mode 100644 index 00000000..e1e1630e --- /dev/null +++ b/lu.json.JSONStorage.load.html @@ -0,0 +1,39 @@ + + + + JSONStorage.load (lu.json.JSONStorage.load) + + + + + + + + + + +
+
+

JSONStorage.load

Loads JSON from disk.

In the case where the file doesn't exist or is otherwise invalid, then + JSONValue is initialised to null (by way of + JSONStorage.reset).

struct JSONStorage
@safe
void
load
(
const string filename
)

Parameters

filename string

Filename of file to read from.

Throws

Whatever readText and/or + parseJSON throws.

lu.common.FileTypeMismatchException if the filename exists + but is not a file.

+ +
+ + + \ No newline at end of file diff --git a/lu.json.JSONStorage.reset.html b/lu.json.JSONStorage.reset.html new file mode 100644 index 00000000..ce0d41db --- /dev/null +++ b/lu.json.JSONStorage.reset.html @@ -0,0 +1,36 @@ + + + + JSONStorage.reset (lu.json.JSONStorage.reset) + + + + + + + + + + +
+
+

JSONStorage.reset

Initialises and clears the JSONValue, preparing + it for object storage.

struct JSONStorage
@safe pure nothrow @nogc
void
reset
()
+ +
+ + + \ No newline at end of file diff --git a/lu.json.JSONStorage.save.html b/lu.json.JSONStorage.save.html new file mode 100644 index 00000000..3c7379a9 --- /dev/null +++ b/lu.json.JSONStorage.save.html @@ -0,0 +1,38 @@ + + + + JSONStorage.save (lu.json.JSONStorage.save) + + + + + + + + + + +
+
+

JSONStorage.save

Saves the JSON storage to disk. Formatting is done as specified by the + passed KeyOrderStrategy argument.

Merely leverages serialiseInto and writeln.

struct JSONStorage
@safe
void
save
(
const string filename
,
const string[] givenOrder = string[].init
)

Parameters

strategy

Key order strategy in which to sort object-type JSON keys.

filename string

Filename of the file to save to.

givenOrder string[]

The order in which object-type keys should be listed in + the output file. Non-existent keys are represented as empty. Not + specified keys are omitted.

+ +
+ + + \ No newline at end of file diff --git a/lu.json.JSONStorage.serialiseInto.1.html b/lu.json.JSONStorage.serialiseInto.1.html new file mode 100644 index 00000000..7755cb92 --- /dev/null +++ b/lu.json.JSONStorage.serialiseInto.1.html @@ -0,0 +1,38 @@ + + + + JSONStorage.serialiseInto (lu.json.JSONStorage.serialiseInto) + + + + + + + + + + +
+
+

JSONStorage.serialiseInto

Formats an object-type JSON storage into an output range sink.

Top-level keys are sorted as per the passed KeyOrderStrategy. This + overload is specialised for KeyOrderStrategy.inGivenOrder.

  1. void serialiseInto(Sink sink, string[] givenOrder)
    struct JSONStorage
    @safe
    void
    serialiseInto
    (
    auto ref Sink sink
    ,
    const string[] givenOrder
    )
    if (
    isOutputRange!(Sink, char[])
    )
  2. void serialiseInto(Sink sink)

Parameters

strategy

Order strategy in which to sort top-level keys.

sink Sink

Output sink to fill with formatted output.

givenOrder string[]

The order in which object-type keys should be listed in + the output file. Non-existent keys are represented as empty. + Not specified keys are omitted.

+ +
+ + + \ No newline at end of file diff --git a/lu.json.JSONStorage.serialiseInto.2.html b/lu.json.JSONStorage.serialiseInto.2.html new file mode 100644 index 00000000..b689527e --- /dev/null +++ b/lu.json.JSONStorage.serialiseInto.2.html @@ -0,0 +1,138 @@ + + + + JSONStorage.serialiseInto (lu.json.JSONStorage.serialiseInto) + + + + + + + + + + +
+
+

JSONStorage.serialiseInto

Formats an object-type JSON storage into an output range sink.

Top-level keys are sorted as per the passed KeyOrderStrategy. This + overload is specialised for strategies other than + KeyOrderStrategy.inGivenOrder, and as such takes one parameter fewer.

  1. void serialiseInto(Sink sink, string[] givenOrder)
  2. void serialiseInto(Sink sink)
    struct JSONStorage
    @safe
    void
    serialiseInto
    (
    auto ref Sink sink
    )
    if (
    isOutputRange!(Sink, char[])
    )

Parameters

strategy

Order strategy in which to sort top-level keys.

sink Sink

Output sink to fill with formatted output.

Examples

1         import std.array : Appender;
+2         import std.json;
+3 
+4         JSONStorage this_;
+5         Appender!(char[]) sink;
+6 
+7         // Original JSON
+8         this_.storage = parseJSON(
+9 `{
+10 "#abc":
+11 {
+12 "hirrsteff" : "o",
+13 "foobar" : "v"
+14 },
+15 "#def":
+16 {
+17 "harrsteff": "v",
+18 "flerpeloso" : "o"
+19 },
+20 "#zzz":
+21 {
+22 "asdf" : "v"
+23 }
+24 }`);
+25 
+26         // KeyOrderStrategy.passthrough
+27         this_.serialiseInto!(KeyOrderStrategy.passthrough)(sink);
+28         assert((sink.data ==
+29 `{
+30     "#abc": {
+31         "foobar": "v",
+32         "hirrsteff": "o"
+33     },
+34     "#def": {
+35         "flerpeloso": "o",
+36         "harrsteff": "v"
+37     },
+38     "#zzz": {
+39         "asdf": "v"
+40     }
+41 }`), '\n' ~ sink.data);
+42         sink.clear();
+43 
+44         // KeyOrderStrategy.sorted
+45         this_.serialiseInto!(KeyOrderStrategy.sorted)(sink);
+46         assert((sink.data ==
+47 `{
+48     "#abc": {
+49         "foobar": "v",
+50         "hirrsteff": "o"
+51     },
+52     "#def": {
+53         "flerpeloso": "o",
+54         "harrsteff": "v"
+55     },
+56     "#zzz": {
+57         "asdf": "v"
+58     }
+59 }`), '\n' ~ sink.data);
+60         sink.clear();
+61 
+62         // KeyOrderStrategy.reverse
+63         this_.serialiseInto!(KeyOrderStrategy.reverse)(sink);
+64         assert((sink.data ==
+65 `{
+66     "#zzz": {
+67         "asdf": "v"
+68     },
+69     "#def": {
+70         "flerpeloso": "o",
+71         "harrsteff": "v"
+72     },
+73     "#abc": {
+74         "foobar": "v",
+75         "hirrsteff": "o"
+76     }
+77 }`), '\n' ~ sink.data);
+78         sink.clear();
+79 
+80         // KeyOrderStrategy.inGivenOrder
+81         this_.serialiseInto!(KeyOrderStrategy.inGivenOrder)(sink, [ "#def", "#abc", "#foo", "#fighters" ]);
+82         assert((sink.data ==
+83 `{
+84     "#def": {
+85         "flerpeloso": "o",
+86         "harrsteff": "v"
+87     },
+88     "#abc": {
+89         "foobar": "v",
+90         "hirrsteff": "o"
+91     },
+92     "#foo": {},
+93     "#fighters": {}
+94 }`), '\n' ~ sink.data);
+95         sink.clear();
+96 
+97         // Empty JSONValue
+98         JSONStorage this2;
+99         this2.serialiseInto(sink);
+100         assert((sink.data ==
+101 `{}`), '\n' ~ sink.data);
+102 
+ +
+ + + \ No newline at end of file diff --git a/lu.json.JSONStorage.serialiseInto.html b/lu.json.JSONStorage.serialiseInto.html new file mode 100644 index 00000000..13abdfda --- /dev/null +++ b/lu.json.JSONStorage.serialiseInto.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.json.JSONStorage.storage.html b/lu.json.JSONStorage.storage.html new file mode 100644 index 00000000..a73e2f27 --- /dev/null +++ b/lu.json.JSONStorage.storage.html @@ -0,0 +1,35 @@ + + + + JSONStorage.storage (lu.json.JSONStorage.storage) + + + + + + + + + + +
+
+

JSONStorage.storage

The underlying JSONValue storage of this JSONStorage.

struct JSONStorage
JSONValue storage;
+ +
+ + + \ No newline at end of file diff --git a/lu.json.html b/lu.json.html new file mode 100644 index 00000000..ad1430d2 --- /dev/null +++ b/lu.json.html @@ -0,0 +1,76 @@ + + + + lu.json (lu.json) + + + + + + + + + + +
+
+

lu.json

Simple JSON wrappers around Phobos' std.json to make keeping JSON storages easier. + This is not a replacement for std.json; it merely extends it.

Members

Functions

populateFromJSON
void populateFromJSON(T target, JSONValue json, Flag!"lowercaseKeys" lowercaseKeys, Flag!"lowercaseValues" lowercaseValues)

Recursively populates a passed associative or dynamic array with the + contents of a JSONValue.

Structs

JSONStorage
struct JSONStorage

A wrapped JSONValue with helper functions.

Examples

JSONStorage json;
+assert(json.storage.type == JSONType.null_);
+
+json.load("somefile.json");
+assert(json.storage.type == JSONType.object);
+
+json.serialiseInto!(JSONStorage.KeyOrderStrategy.inGivenOrder)
+    (stdout.lockingTextWriter, [ "foo", "bar", "baz" ]);
+
+// Printed to screen, regardless how `.toPrettyString` would have ordered it:
+/*
+    {
+        "foo": {
+            1,
+            2,
+        },
+        "bar": {
+            3,
+            4,
+        },
+        "baz": {
+            5,
+            6,
+        }
+    }
+*/
+
+// Prints keys in sorted order.
+json.serialiseInto!(JSONStorage.KeyOrderStrategy.sorted)(stdout.lockingTextWriter)
+
+// Use a [std.array.Appender|Appender] to serialise into a string.
+
+// Adding and removing values still needs the same dance as with std.json.
+// Room for future improvement.
+json.storage["qux"] = null;
+json.storage["qux"].array = null;
+json.storage["qux"].array ~= 7;
+json.storage["qux"].array ~= 8;
+
+json.save("somefile.json");

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.json.populateFromJSON.html b/lu.json.populateFromJSON.html new file mode 100644 index 00000000..26e020b7 --- /dev/null +++ b/lu.json.populateFromJSON.html @@ -0,0 +1,161 @@ + + + + populateFromJSON (lu.json.populateFromJSON) + + + + + + + + + + +
+
+

populateFromJSON

Recursively populates a passed associative or dynamic array with the + contents of a JSONValue.

This is used where we want to store information on disk but keep it in + memory without the overhead of dealing with JSONValues.

Note: This only works with JSONValues that conform to + arrays and associative arrays, not such that mix element/value types.

@safe
void
populateFromJSON
(
T
)
(
ref T target
,
const JSONValue json
,
const Flag!"lowercaseKeys" lowercaseKeys = No.lowercaseKeys
,
const Flag!"lowercaseValues" lowercaseValues = No.lowercaseValues
)
if (
isMutable!T
)

Parameters

target T

Reference to target array or associative array to write to.

json JSONValue

Source JSONValue to sync the contents with.

lowercaseKeys Flag!"lowercaseKeys"

Whether or not to save string keys in lowercase.

lowercaseValues Flag!"lowercaseValues"

Whether or not to save final string values in lowercase.

Throws

Exception if the passed JSONValue + had unexpected types.

Examples

1 import std.json : JSONType, JSONValue;
+2 
+3 {
+4     long[string] aa =
+5     [
+6         "abc" : 123,
+7         "def" : 456,
+8         "ghi" : 789,
+9     ];
+10 
+11     JSONValue j = JSONValue(aa);
+12     typeof(aa) fromJSON;
+13 
+14     foreach (immutable key, const value; j.objectNoRef)
+15     {
+16         fromJSON[key] = value.integer;
+17     }
+18 
+19     assert(aa == fromJSON);  // not is
+20 
+21     auto aaCopy = aa.dup;
+22 
+23     aa["jlk"] = 12;
+24     assert(aa != fromJSON);
+25 
+26     aa = typeof(aa).init;
+27     populateFromJSON(aa, j);
+28     assert(aa == aaCopy);
+29 }
+30 {
+31     auto aa =
+32     [
+33         "abc" : true,
+34         "def" : false,
+35         "ghi" : true,
+36     ];
+37 
+38     JSONValue j = JSONValue(aa);
+39     typeof(aa) fromJSON;
+40 
+41     foreach (immutable key, const value; j.objectNoRef)
+42     {
+43         if (value.type == JSONType.true_) fromJSON[key] = true;
+44         else if (value.type == JSONType.false_) fromJSON[key] = false;
+45         else
+46         {
+47             assert(0);
+48         }
+49     }
+50 
+51     assert(aa == fromJSON);  // not is
+52 
+53     auto aaCopy = aa.dup;
+54 
+55     aa["jkl"] = false;
+56     assert(aa != fromJSON);
+57 
+58     aa = typeof(aa).init;
+59     populateFromJSON(aa, j);
+60     assert(aa == aaCopy);
+61 }
+62 {
+63     auto arr = [ "abc", "def", "ghi", "jkl" ];
+64 
+65     JSONValue j = JSONValue(arr);
+66     typeof(arr) fromJSON;
+67 
+68     foreach (const value; j.arrayNoRef)
+69     {
+70         fromJSON ~= value.str;
+71     }
+72 
+73     assert(arr == fromJSON);  // not is
+74 
+75     auto arrCopy = arr.dup;
+76 
+77     arr[0] = "no";
+78     assert(arr != arrCopy);
+79 
+80     arr = [];
+81     populateFromJSON(arr, j);
+82     assert(arr == arrCopy);
+83 }
+84 {
+85     auto aa =
+86     [
+87         "abc" : [ "def", "ghi", "jkl" ],
+88         "def" : [ "MNO", "PQR", "STU" ],
+89     ];
+90 
+91     JSONValue j = JSONValue(aa);
+92     typeof(aa)fromJSON;
+93 
+94     foreach (immutable key, const arrJSON; j.objectNoRef)
+95     {
+96         foreach (const entry; arrJSON.arrayNoRef)
+97         {
+98             fromJSON[key] ~= entry.str;
+99         }
+100     }
+101 
+102     assert(aa == fromJSON);  // not is
+103 
+104     auto aaCopy = aa.dup;
+105     aaCopy["abc"] = aa["abc"].dup;
+106 
+107     aa["abc"][0] = "no";
+108     aa["ghi"] ~= "VWXYZ";
+109     assert(aa != fromJSON);
+110 
+111     aa = typeof(aa).init;
+112     populateFromJSON(aa, j);
+113     assert(aa == aaCopy);
+114 }
+115 {
+116     int[3] arr = [ 1, 2, 3 ];
+117 
+118     JSONValue j = JSONValue(arr);
+119 
+120     int[3] arr2;
+121     arr2.populateFromJSON(j);
+122     assert(arr2 == arr);
+123 }
+ +
+ + + \ No newline at end of file diff --git a/lu.meld.MeldingStrategy.html b/lu.meld.MeldingStrategy.html new file mode 100644 index 00000000..80818372 --- /dev/null +++ b/lu.meld.MeldingStrategy.html @@ -0,0 +1,39 @@ + + + + MeldingStrategy (lu.meld.MeldingStrategy) + + + + + + + + + + +
+
+

MeldingStrategy

To what extent a source should overwrite a target when melding.

Values

ValueMeaning
conservative

Takes care not to overwrite settings when either the source or the + target is .init.

aggressive

Only considers the init-ness of the source, so as not to overwrite + things with empty strings, but otherwise always considers the source to + trump the target.

overwriting

Works like aggressive but also always overwrites bools, regardless of + falseness.

+ +
+ + + \ No newline at end of file diff --git a/lu.meld.Unmeldable.html b/lu.meld.Unmeldable.html new file mode 100644 index 00000000..ec2d472e --- /dev/null +++ b/lu.meld.Unmeldable.html @@ -0,0 +1,35 @@ + + + + Unmeldable (lu.meld.Unmeldable) + + + + + + + + + + +
+
+

Unmeldable

UDA conveying that this member's value cannot or should not be melded.

+ +
+ + + \ No newline at end of file diff --git a/lu.meld.html b/lu.meld.html new file mode 100644 index 00000000..075d9c48 --- /dev/null +++ b/lu.meld.html @@ -0,0 +1,69 @@ + + + + lu.meld (lu.meld) + + + + + + + + + + +
+
+

lu.meld

This module contains the meldInto functions; functions that take two + structs or classes of the same type and combine them, creating a resulting + object with the union of the members of both parents. Array and associative + array variants exist too.

Members

Enums

MeldingStrategy
enum MeldingStrategy

To what extent a source should overwrite a target when melding.

Unmeldable
enum Unmeldable

UDA conveying that this member's value cannot or should not be melded.

Functions

meldInto
void meldInto(QualThing meldThis, Thing intoThis)

Takes two structs or classes of the same type and melds them together, + making the members a union of the two.

meldInto
void meldInto(Array1 meldThis, Array2 intoThis)

Takes two arrays and melds them together, making a union of the two.

meldInto
void meldInto(QualAA meldThis, AA intoThis)

Takes two associative arrays and melds them together, making a union of the two.

Examples

struct Foo
+{
+    string abc;
+    string def;
+    int i;
+    float f;
+    double d;
+}
+
+Foo f1; // = new Foo;
+f1.abc = "ABC";
+f1.def = "DEF";
+
+Foo f2; // = new Foo;
+f2.abc = "this won't get copied";
+f2.def = "neither will this";
+f2.i = 42;
+f2.f = 3.14f;
+
+f2.meldInto(f1);
+
+with (f1)
+{
+    import std.math : isNaN;
+
+    assert(abc == "ABC");
+    assert(def == "DEF");
+    assert(i == 42);
+    assert(f == 3.14f);
+    assert(d.isNaN);
+}

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.meld.meldInto.1.html b/lu.meld.meldInto.1.html new file mode 100644 index 00000000..23d8ffa7 --- /dev/null +++ b/lu.meld.meldInto.1.html @@ -0,0 +1,352 @@ + + + + meldInto (lu.meld.meldInto) + + + + + + + + + + +
+
+

meldInto

Takes two structs or classes of the same type and melds them together, + making the members a union of the two.

In the case of classes it only overwrites members in intoThis that are + typeof(member).init, so only unset members get their values overwritten by + the melding class. It also does not work with static members.

In the case of structs it also overwrites members that still have their + default values, in cases where such is applicable.

Supply a template parameter MeldingStrategy to decide to which extent + values are overwritten.

  1. void meldInto(QualThing meldThis, Thing intoThis)
    void
    meldInto
    (
    QualThing
    Thing
    )
    (
    auto ref QualThing meldThis
    ,
    ref Thing intoThis
    )
    if (
    isAggregateType!Thing &&
    is(QualThing : Thing)
    &&
    isMutable!Thing
    )
  2. void meldInto(Array1 meldThis, Array2 intoThis)
  3. void meldInto(QualAA meldThis, AA intoThis)

Parameters

strategy

To what extent the source object should overwrite set + (non-init) values in the receiving object.

meldThis QualThing

Object to meld (source).

intoThis Thing

Reference to object to meld (target).

Examples

struct Foo
+{
+    string abc;
+    int def;
+    bool b = true;
+}
+
+Foo foo, bar;
+foo.abc = "from foo"
+foo.b = false;
+bar.def = 42;
+foo.meldInto(bar);
+
+assert(bar.abc == "from foo");
+assert(bar.def == 42);
+assert(!bar.b);  // false overwrote default value true
1 import std.conv : to;
+2 
+3 static struct TestFoo
+4 {
+5     string abc;
+6     string def;
+7     int i;
+8     float f;
+9     double d;
+10     int[string] aa;
+11     int[] arr;
+12     int* ip;
+13 
+14     void blah() {}
+15 
+16     const string kek;
+17     immutable bool bur;
+18 
+19     this(bool bur)
+20     {
+21         kek = "uden lo";
+22         this.bur = bur;
+23     }
+24 }
+25 
+26 TestFoo f1; // = new TestFoo;
+27 f1.abc = "ABC";
+28 f1.def = "DEF";
+29 f1.aa = [ "abc" : 123, "ghi" : 789 ];
+30 f1.arr = [ 1, 0, 3, 0, 5 ];
+31 
+32 TestFoo f2; // = new TestFoo;
+33 f2.abc = "this won't get copied";
+34 f2.def = "neither will this";
+35 f2.i = 42;
+36 f2.f = 3.14f;
+37 f2.aa = [ "abc" : 999, "def" : 456 ];
+38 f2.arr = [ 0, 2, 0, 4 ];
+39 
+40 f2.meldInto(f1);
+41 
+42 with (f1)
+43 {
+44     import std.math : isNaN;
+45 
+46     assert((abc == "ABC"), abc);
+47     assert((def == "DEF"), def);
+48     assert((i == 42), i.to!string);
+49     assert((f == 3.14f), f.to!string);
+50     assert(d.isNaN, d.to!string);
+51     assert((aa == [ "abc" : 123, "def" : 456, "ghi" : 789 ]), aa.to!string);
+52     assert((arr == [ 1, 2, 3, 4, 5 ]), arr.to!string);
+53 }
+54 
+55 TestFoo f3; // new TestFoo;
+56 f3.abc = "abc";
+57 f3.def = "def";
+58 f3.i = 100_135;
+59 f3.f = 99.9f;
+60 f3.aa = [ "abc" : 123, "ghi" : 789 ];
+61 f3.arr = [ 1, 0, 3, 0, 5 ];
+62 
+63 TestFoo f4; // new TestFoo;
+64 f4.abc = "OVERWRITTEN";
+65 f4.def = "OVERWRITTEN TOO";
+66 f4.i = 0;
+67 f4.f = 0.1f;
+68 f4.d = 99.999;
+69 f4.aa = [ "abc" : 999, "def" : 456 ];
+70 f4.arr = [ 9, 2, 0, 4 ];
+71 
+72 f4.meldInto!(MeldingStrategy.aggressive)(f3);
+73 
+74 with (f3)
+75 {
+76     static if (__VERSION__ >= 2091)
+77     {
+78         import std.math : isClose;
+79     }
+80     else
+81     {
+82         import std.math : approxEqual;
+83         alias isClose = approxEqual;
+84     }
+85 
+86     assert((abc == "OVERWRITTEN"), abc);
+87     assert((def == "OVERWRITTEN TOO"), def);
+88     assert((i == 100_135), i.to!string); // 0 is int.init
+89     assert((f == 0.1f), f.to!string);
+90     assert(isClose(d, 99.999), d.to!string);
+91     assert((aa == [ "abc" : 999, "def" : 456, "ghi" : 789 ]), aa.to!string);
+92     assert((arr == [ 9, 2, 3, 4, 5 ]), arr.to!string);
+93 }
+94 
+95 // Overwriting is just aggressive but always overwrites bools.
+96 
+97 struct User
+98 {
+99     enum Class { anyone, blacklist, whitelist, admin }
+100     string nickname;
+101     string alias_;
+102     string ident;
+103     string address;
+104     string login;
+105     bool special;
+106     Class class_;
+107 }
+108 
+109 User one;
+110 with (one)
+111 {
+112     nickname = "foobar";
+113     ident = "NaN";
+114     address = "herpderp.net";
+115     special = false;
+116     class_ = User.Class.whitelist;
+117 }
+118 
+119 User two;
+120 with (two)
+121 {
+122     nickname = "foobar^";
+123     alias_ = "FooBar";
+124     address = "asdf.org";
+125     login = "kamelusu";
+126     special = true;
+127     class_ = User.Class.blacklist;
+128 }
+129 
+130 //import lu.conv : Enum;
+131 
+132 User twoCopy = two;
+133 
+134 one.meldInto!(MeldingStrategy.conservative)(two);
+135 with (two)
+136 {
+137     assert((nickname == "foobar^"), nickname);
+138     assert((alias_ == "FooBar"), alias_);
+139     assert((ident == "NaN"), ident);
+140     assert((address == "asdf.org"), address);
+141     assert((login == "kamelusu"), login);
+142     assert(special);
+143     assert(class_ == User.Class.whitelist);//, Enum!(User.Class).toString(class_));
+144 }
+145 
+146 one.class_ = User.Class.blacklist;
+147 
+148 one.meldInto!(MeldingStrategy.overwriting)(twoCopy);
+149 with (twoCopy)
+150 {
+151     assert((nickname == "foobar"), nickname);
+152     assert((alias_ == "FooBar"), alias_);
+153     assert((ident == "NaN"), ident);
+154     assert((address == "herpderp.net"), address);
+155     assert((login == "kamelusu"), login);
+156     assert(!special);
+157     assert(class_ == User.Class.blacklist);//, Enum!(User.Class).toString(class_));
+158 }
+159 
+160 struct EnumThing
+161 {
+162     enum Enum { unset, one, two, three }
+163     Enum enum_;
+164 }
+165 
+166 EnumThing e1;
+167 EnumThing e2;
+168 e2.enum_ = EnumThing.Enum.three;
+169 assert(e1.enum_ == EnumThing.Enum.init);//, Enum!(EnumThing.Enum).toString(e1.enum_));
+170 e2.meldInto(e1);
+171 assert(e1.enum_ == EnumThing.Enum.three);//, Enum!(EnumThing.Enum).toString(e1.enum_));
+172 
+173 struct WithArray
+174 {
+175     string[] arr;
+176 }
+177 
+178 WithArray w1, w2;
+179 w1.arr = [ "arr", "matey", "I'ma" ];
+180 w2.arr = [ "pirate", "stereotype", "unittest" ];
+181 w2.meldInto(w1);
+182 assert((w1.arr == [ "arr", "matey", "I'ma", "pirate", "stereotype", "unittest" ]), w1.arr.to!string);
+183 
+184 WithArray w3, w4;
+185 w3.arr = [ "arr", "matey", "I'ma" ];
+186 w4.arr = [ "arr", "matey", "I'ma" ];
+187 w4.meldInto(w3);
+188 assert((w3.arr == [ "arr", "matey", "I'ma" ]), w3.arr.to!string);
+189 
+190 struct Server
+191 {
+192     string address;
+193 }
+194 
+195 struct Bot
+196 {
+197     string nickname;
+198     Server server;
+199 }
+200 
+201 Bot b1, b2;
+202 b1.nickname = "foobar";
+203 b1.server.address = "freenode.net";
+204 
+205 assert(!b2.nickname.length, b2.nickname);
+206 assert(!b2.server.address.length, b2.nickname);
+207 b1.meldInto(b2);
+208 assert((b2.nickname == "foobar"), b2.nickname);
+209 assert((b2.server.address == "freenode.net"), b2.server.address);
+210 
+211 b2.nickname = "harbl";
+212 b2.server.address = "rizon.net";
+213 
+214 b2.meldInto!(MeldingStrategy.aggressive)(b1);
+215 assert((b1.nickname == "harbl"), b1.nickname);
+216 assert((b1.server.address == "rizon.net"), b1.server.address);
+217 
+218 class Class
+219 {
+220     static int i;
+221     string s;
+222     bool b;
+223 }
+224 
+225 Class abc = new Class;
+226 abc.i = 42;
+227 abc.s = "some string";
+228 abc.b = true;
+229 
+230 Class def = new Class;
+231 def.s = "other string";
+232 abc.meldInto(def);
+233 
+234 assert((def.i == 42), def.i.to!string);
+235 assert((def.s == "other string"), def.s);
+236 assert(def.b);
+237 
+238 abc.meldInto!(MeldingStrategy.aggressive)(def);
+239 assert((def.s == "some string"), def.s);
+240 
+241 struct Bools
+242 {
+243     bool a = true;
+244     bool b = false;
+245 }
+246 
+247 Bools bools1, bools2, inverted, backupInverted;
+248 
+249 bools2.a = false;
+250 
+251 inverted.a = false;
+252 inverted.b = true;
+253 backupInverted = inverted;
+254 
+255 bools2.meldInto(bools1);
+256 assert(!bools1.a);
+257 assert(!bools1.b);
+258 
+259 bools2.meldInto(inverted);
+260 assert(!inverted.a);
+261 assert(inverted.b);
+262 inverted = backupInverted;
+263 
+264 bools2.meldInto!(MeldingStrategy.overwriting)(inverted);
+265 assert(!inverted.a);
+266 assert(!inverted.b);
+267 inverted = backupInverted;
+268 
+269 struct Asdf
+270 {
+271     string nickname = "sadf";
+272     string server = "asdf.net";
+273 }
+274 
+275 Asdf a, b;
+276 a.server = "a";
+277 b.server = "b";
+278 b.meldInto!(MeldingStrategy.aggressive)(a);
+279 assert((a.server == "b"), a.server);
+280 
+281 a.server = "a";
+282 b.server = Asdf.init.server;
+283 b.meldInto!(MeldingStrategy.aggressive)(a);
+284 assert((a.server == "a"), a.server);
+285 
+286 struct Blah
+287 {
+288     int yes = 42;
+289     @Unmeldable int no = 24;
+290 }
+291 
+292 Blah blah1, blah2;
+293 blah1.yes = 5;
+294 blah1.no = 42;
+295 blah1.meldInto!(MeldingStrategy.aggressive)(blah2);
+296 assert((blah2.yes == 5), blah2.yes.to!string);
+297 assert((blah2.no == 24), blah2.no.to!string);
+ +
+ + + \ No newline at end of file diff --git a/lu.meld.meldInto.2.html b/lu.meld.meldInto.2.html new file mode 100644 index 00000000..c32e4cf2 --- /dev/null +++ b/lu.meld.meldInto.2.html @@ -0,0 +1,71 @@ + + + + meldInto (lu.meld.meldInto) + + + + + + + + + + +
+
+

meldInto

Takes two arrays and melds them together, making a union of the two.

It only overwrites members that are T.init, so only unset + fields get their values overwritten by the melding array. Supply a + template parameter MeldingStrategy.aggressive to make it overwrite if the + melding array's field is not T.init. Furthermore use + MeldingStrategy.overwriting if working with bool members.

  1. void meldInto(QualThing meldThis, Thing intoThis)
  2. void meldInto(Array1 meldThis, Array2 intoThis)
    pure nothrow
    void
    meldInto
    ()
    (
    auto ref Array1 meldThis
    ,
    ref Array2 intoThis
    )
    if (
    isMerelyArray!Array1 &&
    &&
    isMutable!Array2
    )
  3. void meldInto(QualAA meldThis, AA intoThis)

Parameters

strategy

To what extent the source object should overwrite set + (non-init) values in the receiving object.

meldThis Array1

Array to meld (source).

intoThis Array2

Reference to the array to meld (target).

Examples

int[] arr1 = [ 1, 2, 3, 0, 0, 0 ];
+int[] arr2 = [ 0, 0, 0, 4, 5, 6 ];
+arr1.meldInto!(MeldingStrategy.conservative)(arr2);
+
+assert(arr2 == [ 1, 2, 3, 4, 5, 6 ]);
import std.conv : to;
+
+auto arr1 = [ 123, 0, 789, 0, 456, 0 ];
+auto arr2 = [ 0, 456, 0, 123, 0, 789 ];
+arr1.meldInto!(MeldingStrategy.conservative)(arr2);
+assert((arr2 == [ 123, 456, 789, 123, 456, 789 ]), arr2.to!string);
+
+auto yarr1 = [ 'Z', char.init, 'Z', char.init, 'Z' ];
+auto yarr2 = [ 'A', 'B', 'C', 'D', 'E', 'F' ];
+yarr1.meldInto!(MeldingStrategy.aggressive)(yarr2);
+assert((yarr2 == [ 'Z', 'B', 'Z', 'D', 'Z', 'F' ]), yarr2.to!string);
+
+auto harr1 = [ char.init, 'X' ];
+yarr1.meldInto(harr1);
+assert((harr1 == [ 'Z', 'X', 'Z', char.init, 'Z' ]), harr1.to!string);
+
+char[5] harr2 = [ '1', '2', '3', '4', '5' ];
+char[] harr3;
+harr2.meldInto(harr3);
+assert((harr2 == harr3), harr3.to!string);
+
+int[3] asdf;
+int[3] hasdf;
+asdf.meldInto(hasdf);
+
+int[] dyn = new int[2];
+int[3] stat;
+dyn.meldInto(stat);
+ +
+ + + \ No newline at end of file diff --git a/lu.meld.meldInto.3.html b/lu.meld.meldInto.3.html new file mode 100644 index 00000000..be5f02b0 --- /dev/null +++ b/lu.meld.meldInto.3.html @@ -0,0 +1,76 @@ + + + + meldInto (lu.meld.meldInto) + + + + + + + + + + +
+
+

meldInto

Takes two associative arrays and melds them together, making a union of the two.

This is largely the same as the array-version meldInto but doesn't need + the extensive template constraints it employs, so it might as well be kept separate.

  1. void meldInto(QualThing meldThis, Thing intoThis)
  2. void meldInto(Array1 meldThis, Array2 intoThis)
  3. void meldInto(QualAA meldThis, AA intoThis)
    pure
    void
    meldInto
    (
    QualAA meldThis
    ,
    ref AA intoThis
    )
    if (
    isAssociativeArray!AA &&
    is(QualAA : AA)
    &&
    isMutable!AA
    )

Parameters

strategy

To what extent the source object should overwrite set + (non-init) values in the receiving object.

meldThis QualAA

Associative array to meld (source).

intoThis AA

Reference to the associative array to meld (target).

Examples

int[string] aa1 = [ "abc" : 42, "def" : -1 ];
+int[string] aa2 = [ "ghi" : 10, "jkl" : 7 ];
+arr1.meldInto(arr2);
+
+assert("abc" in aa2);
+assert("def" in aa2);
+assert("ghi" in aa2);
+assert("jkl" in aa2);
bool[string] aa1;
+bool[string] aa2;
+
+aa1["a"] = true;
+aa1["b"] = false;
+aa2["c"] = true;
+aa2["d"] = false;
+
+assert("a" in aa1);
+assert("b" in aa1);
+assert("c" in aa2);
+assert("d" in aa2);
+
+aa1.meldInto!(MeldingStrategy.overwriting)(aa2);
+
+assert("a" in aa2);
+assert("b" in aa2);
+
+string[string] saa1;
+string[string] saa2;
+
+saa1["a"] = "a";
+saa1["b"] = "b";
+saa2["c"] = "c";
+saa2["d"] = "d";
+
+saa1.meldInto!(MeldingStrategy.conservative)(saa2);
+assert("a" in saa2);
+assert("b" in saa2);
+
+saa1["a"] = "A";
+saa1.meldInto!(MeldingStrategy.aggressive)(saa2);
+assert(saa2["a"] == "A");
+ +
+ + + \ No newline at end of file diff --git a/lu.meld.meldInto.html b/lu.meld.meldInto.html new file mode 100644 index 00000000..0e79c7a8 --- /dev/null +++ b/lu.meld.meldInto.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.numeric.getMultipleOf.html b/lu.numeric.getMultipleOf.html new file mode 100644 index 00000000..3738aee8 --- /dev/null +++ b/lu.numeric.getMultipleOf.html @@ -0,0 +1,68 @@ + + + + getMultipleOf (lu.numeric.getMultipleOf) + + + + + + + + + + +
+
+

getMultipleOf

Given a number, calculate the largest multiple of n needed to reach that number.

It rounds up, and if supplied Yes.alwaysOneUp it will always overshoot. + This is good for when calculating format pattern widths.

@safe pure nothrow @nogc
Number
getMultipleOf
(
Number
)
(
const Number num
,
const int n
,
const Flag!"alwaysOneUp" oneUp = No.alwaysOneUp
)

Parameters

num Number

Number to reach.

n int

Base value to find a multiplier for.

oneUp Flag!"alwaysOneUp"

Whether or not to always overshoot.

Return Value

Type: Number

The multiple of n that reaches and possibly overshoots num.

Examples

immutable width = 15.getMultipleOf(4);
+assert(width == 16);
+immutable width2 = 16.getMultipleOf(4, Yes.alwaysOneUp);
+assert(width2 == 20);
import std.conv : text;
+
+immutable n1 = 15.getMultipleOf(4);
+assert((n1 == 16), n1.text);
+
+immutable n2 = 16.getMultipleOf(4, Yes.alwaysOneUp);
+assert((n2 == 20), n2.text);
+
+immutable n3 = 16.getMultipleOf(4);
+assert((n3 == 16), n3.text);
+immutable n4 = 0.getMultipleOf(5);
+assert((n4 == 0), n4.text);
+
+immutable n5 = 1.getMultipleOf(1);
+assert((n5 == 1), n5.text);
+
+immutable n6 = 1.getMultipleOf(1, Yes.alwaysOneUp);
+assert((n6 == 2), n6.text);
+
+immutable n7 = 5.getMultipleOf(5, Yes.alwaysOneUp);
+assert((n7 == 6), n7.text);
+
+immutable n8 = 5L.getMultipleOf(5L, Yes.alwaysOneUp);
+assert((n8 == 6L), n8.text);
+
+immutable n9 = 5UL.getMultipleOf(5UL, No.alwaysOneUp);
+assert((n9 == 5UL), n9.text);
+
+immutable n10 = (5.0).getMultipleOf(5UL, Yes.alwaysOneUp);
+assert((n10 == (6.0)), n10.text);
+ +
+ + + \ No newline at end of file diff --git a/lu.numeric.html b/lu.numeric.html new file mode 100644 index 00000000..a04921ef --- /dev/null +++ b/lu.numeric.html @@ -0,0 +1,39 @@ + + + + lu.numeric (lu.numeric) + + + + + + + + + + +
+
+

lu.numeric

Functions and templates that do numeric calculations or other manipulation, + in some way or another.

Members

Functions

getMultipleOf
Number getMultipleOf(Number num, int n, Flag!"alwaysOneUp" oneUp)

Given a number, calculate the largest multiple of n needed to reach that number.

Examples

immutable width = 15.getMultipleOf(4);
+assert(width == 16);
+immutable width2 = 16.getMultipleOf(4, Yes.alwaysOneUp);
+assert(width2 == 20);

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.SetMemberException.html b/lu.objmanip.SetMemberException.html new file mode 100644 index 00000000..b83ad3b1 --- /dev/null +++ b/lu.objmanip.SetMemberException.html @@ -0,0 +1,36 @@ + + + + SetMemberException (lu.objmanip.SetMemberException) + + + + + + + + + + +
+
+

SetMemberException

Exception, to be thrown when setMemberByName fails for some given reason.

It is a normal Exception but with attached strings of + the type name, name of member and the value that was attempted to set.

Constructors

this
this(string message, string file, size_t line, Throwable nextInChain)

Create a new SetMemberException, without attaching anything.

this
this(string message, string typeName, string memberToSet, string valueToSet, string file, size_t line, Throwable nextInChain)

Create a new SetMemberException, attaching extra set-member information.

Members

Variables

memberToSet
string memberToSet;

Name of the member that was attempted to set.

typeName
string typeName;

Name of type that was attempted to set the member of.

valueToSet
string valueToSet;

String representation of the value that was attempted to assign.

+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.SetMemberException.memberToSet.html b/lu.objmanip.SetMemberException.memberToSet.html new file mode 100644 index 00000000..867da756 --- /dev/null +++ b/lu.objmanip.SetMemberException.memberToSet.html @@ -0,0 +1,35 @@ + + + + SetMemberException.memberToSet (lu.objmanip.SetMemberException.memberToSet) + + + + + + + + + + +
+
+

SetMemberException.memberToSet

Name of the member that was attempted to set.

class SetMemberException
string memberToSet;
+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.SetMemberException.this.1.html b/lu.objmanip.SetMemberException.this.1.html new file mode 100644 index 00000000..9483c1c4 --- /dev/null +++ b/lu.objmanip.SetMemberException.this.1.html @@ -0,0 +1,35 @@ + + + + SetMemberException.this (lu.objmanip.SetMemberException.this) + + + + + + + + + + +
+
+

SetMemberException.this

Create a new SetMemberException, without attaching anything.

  1. this(string message, string file, size_t line, Throwable nextInChain)
    class SetMemberException
    pure nothrow @nogc @safe
    this
    (
    const string message
    ,
    const string file = __FILE__
    ,
    const size_t line = __LINE__
    ,
    Throwable nextInChain = null
    )
  2. this(string message, string typeName, string memberToSet, string valueToSet, string file, size_t line, Throwable nextInChain)
+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.SetMemberException.this.2.html b/lu.objmanip.SetMemberException.this.2.html new file mode 100644 index 00000000..9bb29316 --- /dev/null +++ b/lu.objmanip.SetMemberException.this.2.html @@ -0,0 +1,35 @@ + + + + SetMemberException.this (lu.objmanip.SetMemberException.this) + + + + + + + + + + +
+
+

SetMemberException.this

Create a new SetMemberException, attaching extra set-member information.

  1. this(string message, string file, size_t line, Throwable nextInChain)
  2. this(string message, string typeName, string memberToSet, string valueToSet, string file, size_t line, Throwable nextInChain)
    class SetMemberException
    pure nothrow @nogc @safe
    this
    (
    const string message
    ,
    const string typeName
    ,
    const string memberToSet
    ,
    const string valueToSet
    ,
    const string file = __FILE__
    ,
    const size_t line = __LINE__
    ,
    Throwable nextInChain = null
    )
+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.SetMemberException.this.html b/lu.objmanip.SetMemberException.this.html new file mode 100644 index 00000000..e0634955 --- /dev/null +++ b/lu.objmanip.SetMemberException.this.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.objmanip.SetMemberException.typeName.html b/lu.objmanip.SetMemberException.typeName.html new file mode 100644 index 00000000..8eca5e98 --- /dev/null +++ b/lu.objmanip.SetMemberException.typeName.html @@ -0,0 +1,35 @@ + + + + SetMemberException.typeName (lu.objmanip.SetMemberException.typeName) + + + + + + + + + + +
+
+

SetMemberException.typeName

Name of type that was attempted to set the member of.

class SetMemberException
string typeName;
+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.SetMemberException.valueToSet.html b/lu.objmanip.SetMemberException.valueToSet.html new file mode 100644 index 00000000..f679196d --- /dev/null +++ b/lu.objmanip.SetMemberException.valueToSet.html @@ -0,0 +1,35 @@ + + + + SetMemberException.valueToSet (lu.objmanip.SetMemberException.valueToSet) + + + + + + + + + + +
+
+

SetMemberException.valueToSet

String representation of the value that was attempted to assign.

class SetMemberException
string valueToSet;
+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.html b/lu.objmanip.html new file mode 100644 index 00000000..dae9e84e --- /dev/null +++ b/lu.objmanip.html @@ -0,0 +1,64 @@ + + + + lu.objmanip (lu.objmanip) + + + + + + + + + + +
+
+

lu.objmanip

This module contains functions that in some way or another manipulates + struct and class instances, as well as (associative) arrays.

Members

Classes

SetMemberException
class SetMemberException

Exception, to be thrown when setMemberByName fails for some given reason.

Functions

pruneAA
void pruneAA(AA aa)

Iterates an associative array and deletes invalid entries, either if the value + is in a default .init state or as per the optionally passed predicate.

replaceMembers
void replaceMembers(Thing thing, Token token, Token replacement)

Inspects a passed struct or class for members whose values match that of the + passed token. Matches members are set to a replacement value, which is + an optional parameter that defaults to the .init value of the token's type.

setMemberByName
bool setMemberByName(Thing thing, string memberToSet, string valueToSet)

Given a struct/class object, sets one of its members by its string name to a + specified value. Overload that takes the value as a string and tries to + convert it into the target type.

setMemberByName
bool setMemberByName(Thing thing, string memberToSet, Val valueToSet)

Given a struct/class object, sets one of its members by its string name to a + specified value. Overload that takes a value of the same type as the target + member, rather than a string to convert. Integer promotion applies.

Structs

Separator (from lu.uda)
struct Separator via public +import lu.uda : Separator;

UDA conveying that the annotated array should have this token as separator + when formatted to a string.

Examples

struct Foo
+{
+    string nickname;
+    string address;
+}
+
+Foo foo;
+
+foo.setMemberByName("nickname", "foobar");
+foo.setMemberByName("address", "subdomain.address.tld");
+
+assert(foo.nickname == "foobar");
+assert(foo.address == "subdomain.address.tld");
+
+foo.replaceMembers("subdomain.address.tld", "foobar");
+assert(foo.address == "foobar");
+
+foo.replaceMembers("foobar", string.init);
+assert(foo.nickname.length == 0);
+assert(foo.address.length == 0);

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.pruneAA.html b/lu.objmanip.pruneAA.html new file mode 100644 index 00000000..d480d44c --- /dev/null +++ b/lu.objmanip.pruneAA.html @@ -0,0 +1,118 @@ + + + + pruneAA (lu.objmanip.pruneAA) + + + + + + + + + + +
+
+

pruneAA

Iterates an associative array and deletes invalid entries, either if the value + is in a default .init state or as per the optionally passed predicate.

It is supposedly undefined behaviour to remove an associative array's fields + when foreaching through it. So far we have been doing a simple mark-sweep + garbage collection whenever we encounter this use-case in the code, so why + not just make a generic solution instead and deduplicate code?

@safe
void
pruneAA
(
alias pred = null
AA
)
(
ref AA aa
)
if (
isAssociativeArray!AA &&
isMutable!AA
)

Parameters

pred

Optional predicate if special logic is needed to determine whether + an entry is to be removed or not.

aa AA

The associative array to modify.

Examples

auto aa =
+[
+    "abc" : "def",
+    "ghi" : string.init;
+    "mno" : "123",
+    "pqr" : string.init,
+];
+
+pruneAA(aa);
+
+assert("ghi" !in aa);
+assert("pqr" !in aa);
+
+pruneAA!((entry) => entry.length > 0)(aa);
+
+assert("abc" !in aa);
+assert("mno" !in aa);
1 import std.conv : text;
+2 
+3 {
+4     auto aa =
+5     [
+6         "abc" : "def",
+7         "ghi" : "jkl",
+8         "mno" : "123",
+9         "pqr" : string.init,
+10     ];
+11 
+12     pruneAA!((a) => a == "def")(aa);
+13     assert("abc" !in aa);
+14 
+15     pruneAA!((a,b) => a == "pqr")(aa);
+16     assert("pqr" !in aa);
+17 
+18     pruneAA!`a == "123"`(aa);
+19     assert("mno" !in aa);
+20 }
+21 {
+22     struct Record
+23     {
+24         string name;
+25         int id;
+26     }
+27 
+28     auto aa =
+29     [
+30         "rhubarb" : Record("rhubarb", 100),
+31         "raspberry" : Record("raspberry", 80),
+32         "blueberry" : Record("blueberry", 0),
+33         "apples" : Record("green apples", 60),
+34         "yakisoba"  : Record("yakisoba", 78),
+35         "cabbage" : Record.init,
+36     ];
+37 
+38     pruneAA(aa);
+39     assert("cabbage" !in aa);
+40 
+41     pruneAA!((entry) => entry.id < 80)(aa);
+42     assert("blueberry" !in aa);
+43     assert("apples" !in aa);
+44     assert("yakisoba" !in aa);
+45     assert((aa.length == 2), aa.length.text);
+46 }
+47 {
+48     import std.algorithm.searching : canFind;
+49 
+50     string[][string] aa =
+51     [
+52         "abc" : [ "a", "b", "c" ],
+53         "def" : [ "d", "e", "f" ],
+54         "ghi" : [ "g", "h", "i" ],
+55         "jkl" : [ "j", "k", "l" ],
+56     ];
+57 
+58     pruneAA(aa);
+59     assert((aa.length == 4), aa.length.text);
+60 
+61     pruneAA!((entry) => entry.canFind("a"))(aa);
+62     assert("abc" !in aa);
+63 }
+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.replaceMembers.html b/lu.objmanip.replaceMembers.html new file mode 100644 index 00000000..7fbd3fa1 --- /dev/null +++ b/lu.objmanip.replaceMembers.html @@ -0,0 +1,119 @@ + + + + replaceMembers (lu.objmanip.replaceMembers) + + + + + + + + + + +
+
+

replaceMembers

Inspects a passed struct or class for members whose values match that of the + passed token. Matches members are set to a replacement value, which is + an optional parameter that defaults to the .init value of the token's type.

@safe pure nothrow @nogc
void
replaceMembers
(
Flag!"recurse" recurse = No.recurse
Thing
Token
)
(
ref Thing thing
,
Token token
,
Token replacement = Token.init
)
if (
isAggregateType!Thing &&
isMutable!Thing
&&
isEqualityComparable!Token
)

Parameters

recurse

Whether or not to recurse into aggregate members.

thing Thing

Reference to a struct or class whose members to iterate over.

token Token

What value to look for in members, be it a string or an integer + or whatever; anything that can be compared to.

replacement Token

What to assign matched values. Defaults to the .init + of the matched type.

Examples

1 struct Bar
+2 {
+3     string s = "content";
+4 }
+5 
+6 struct Foo
+7 {
+8     Bar b;
+9     string s = "more content";
+10 }
+11 
+12 Foo foo1, foo2;
+13 foo1.replaceMembers("-");
+14 assert(foo1 == foo2);
+15 
+16 foo2.s = "-";
+17 foo2.replaceMembers("-");
+18 assert(!foo2.s.length);
+19 foo2.b.s = "-";
+20 foo2.replaceMembers!(Yes.recurse)("-", "herblp");
+21 assert((foo2.b.s == "herblp"), foo2.b.s);
+22 
+23 Foo foo3;
+24 foo3.s = "---";
+25 foo3.b.s = "---";
+26 foo3.replaceMembers!(No.recurse)("---");
+27 assert(!foo3.s.length);
+28 assert((foo3.b.s == "---"), foo3.b.s);
+29 foo3.replaceMembers!(Yes.recurse)("---");
+30 assert(!foo3.b.s.length);
+31 
+32 class Baz
+33 {
+34     string barS = "init";
+35     string barT = "*";
+36     Foo f;
+37 }
+38 
+39 Baz b1 = new Baz;
+40 Baz b2 = new Baz;
+41 
+42 b1.replaceMembers("-");
+43 assert((b1.barS == b2.barS), b1.barS);
+44 assert((b1.barT == b2.barT), b1.barT);
+45 
+46 b1.replaceMembers("*");
+47 assert(b1.barS.length, b1.barS);
+48 assert(!b1.barT.length, b1.barT);
+49 assert(b1.f.s.length, b1.f.s);
+50 
+51 b1.replaceMembers!(Yes.recurse)("more content");
+52 assert(!b1.f.s.length, b1.f.s);
+53 
+54 import std.conv : to;
+55 
+56 struct Qux
+57 {
+58     int i = 42;
+59 }
+60 
+61 Qux q;
+62 
+63 q.replaceMembers("*");
+64 assert(q.i == 42);
+65 
+66 q.replaceMembers(43);
+67 assert(q.i == 42);
+68 
+69 q.replaceMembers(42, 99);
+70 assert((q.i == 99), q.i.to!string);
+71 
+72 struct Flerp
+73 {
+74     string[] arr;
+75 }
+76 
+77 Flerp flerp;
+78 flerp.arr = [ "-" ];
+79 assert(flerp.arr.length == 1);
+80 flerp.replaceMembers("-");
+81 assert(!flerp.arr.length);
+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.setMemberByName.1.html b/lu.objmanip.setMemberByName.1.html new file mode 100644 index 00000000..f6f42517 --- /dev/null +++ b/lu.objmanip.setMemberByName.1.html @@ -0,0 +1,239 @@ + + + + setMemberByName (lu.objmanip.setMemberByName) + + + + + + + + + + +
+
+

setMemberByName

Given a struct/class object, sets one of its members by its string name to a + specified value. Overload that takes the value as a string and tries to + convert it into the target type.

It does not currently recurse into other struct/class members.

  1. bool setMemberByName(Thing thing, string memberToSet, string valueToSet)
    bool
    setMemberByName
    (
    Thing
    )
    (
    ref Thing thing
    ,
    const string memberToSet
    ,
    const string valueToSet
    )
    if (
    isAggregateType!Thing &&
    isMutable!Thing
    )
  2. bool setMemberByName(Thing thing, string memberToSet, Val valueToSet)

Parameters

thing Thing

Reference object whose members to set.

memberToSet string

String name of the thing's member to set.

valueToSet string

String contents of the value to set the member to; string + even if the member is of a different type.

Return Value

Type: bool

true if a member was found and set, false if nothing was done.

Throws

ConvException if a string could not be + converted into an array, if a passed string could not be converted into + a bool, or if std.conv.to failed to convert a string into wanted type T. + SetMemberException if an unexpected exception was thrown.

Examples

struct Foo
+{
+    string name;
+    int number;
+    bool alive;
+}
+
+Foo foo;
+
+foo.setMemberByName("name", "James Bond");
+foo.setMemberByName("number", "007");
+foo.setMemberByName("alive", "false");
+
+assert(foo.name == "James Bond");
+assert(foo.number == 7);
+assert(!foo.alive);
1 import lu.uda : Separator;
+2 import std.conv : to;
+3 
+4 struct Foo
+5 {
+6     string bar;
+7     int baz;
+8     float* f;
+9     string[string] aa;
+10 
+11     @Separator("|")
+12     @Separator(" ")
+13     {
+14         string[] arr;
+15         string[] matey;
+16     }
+17 
+18     @Separator(";;")
+19     {
+20         string[] parrots;
+21         string[] withSpaces;
+22     }
+23 
+24     @Separator(`\o/`)
+25     {
+26         string[] blurgh;
+27     }
+28 
+29     static if (__VERSION__ >= 2087L)
+30     {
+31         @(`\o/`)
+32         {
+33             int[] blargh;
+34         }
+35     }
+36 }
+37 
+38 Foo foo;
+39 bool success;
+40 
+41 success = foo.setMemberByName("bar", "asdf fdsa adf");
+42 assert(success);
+43 assert((foo.bar == "asdf fdsa adf"), foo.bar);
+44 
+45 success = foo.setMemberByName("baz", "42");
+46 assert(success);
+47 assert((foo.baz == 42), foo.baz.to!string);
+48 
+49 success = foo.setMemberByName("aa", `["abc":"def", "ghi":"jkl"]`);
+50 assert(success);
+51 assert((foo.aa == [ "abc":"def", "ghi":"jkl" ]), foo.aa.to!string);
+52 
+53 success = foo.setMemberByName("arr", "herp|derp|dirp|darp");
+54 assert(success);
+55 assert((foo.arr == [ "herp", "derp", "dirp", "darp"]), foo.arr.to!string);
+56 
+57 success = foo.setMemberByName("arr", "herp derp dirp|darp");
+58 assert(success);
+59 assert((foo.arr == [ "herp", "derp", "dirp", "darp"]), foo.arr.to!string);
+60 
+61 success = foo.setMemberByName("matey", "this,should,not,be,separated");
+62 assert(success);
+63 assert((foo.matey == [ "this,should,not,be,separated" ]), foo.matey.to!string);
+64 
+65 success = foo.setMemberByName("parrots", "squaawk;;parrot sounds;;repeating");
+66 assert(success);
+67 assert((foo.parrots == [ "squaawk", "parrot sounds", "repeating"]),
+68     foo.parrots.to!string);
+69 
+70 success = foo.setMemberByName("withSpaces", `         squoonk         ;;"  spaced  ";;" "`);
+71 assert(success);
+72 assert((foo.withSpaces == [ "squoonk", `  spaced  `, " "]),
+73     foo.withSpaces.to!string);
+74 
+75 success = foo.setMemberByName("invalid", "oekwpo");
+76 assert(!success);
+77 
+78 /*success = foo.setMemberByName("", "true");
+79 assert(!success);*/
+80 
+81 success = foo.setMemberByName("matey", "hirr steff\\ stuff staff\\|stirf hooo");
+82 assert(success);
+83 assert((foo.matey == [ "hirr", "steff stuff", "staff|stirf", "hooo" ]), foo.matey.to!string);
+84 
+85 success = foo.setMemberByName("matey", "hirr steff\\\\ stuff staff\\\\|stirf hooo");
+86 assert(success);
+87 assert((foo.matey == [ "hirr", "steff\\", "stuff", "staff\\", "stirf", "hooo" ]), foo.matey.to!string);
+88 
+89 success = foo.setMemberByName("matey", "asdf\\ fdsa\\\\ hirr                                steff");
+90 assert(success);
+91 assert((foo.matey == [ "asdf fdsa\\", "hirr", "steff" ]), foo.matey.to!string);
+92 
+93 success = foo.setMemberByName("blurgh", "asdf\\\\o/fdsa\\\\\\o/hirr\\o/\\o/\\o/\\o/\\o/\\o/\\o/\\o/steff");
+94 assert(success);
+95 assert((foo.blurgh == [ "asdf\\o/fdsa\\", "hirr", "steff" ]), foo.blurgh.to!string);
+96 
+97 static if (__VERSION__ >= 2087L)
+98 {
+99     success = foo.setMemberByName("blargh", `1\o/2\o/3\o/4\o/5`);
+100     assert(success);
+101     assert((foo.blargh == [ 1, 2, 3, 4, 5 ]), foo.blargh.to!string);
+102 }
+103 
+104 class C
+105 {
+106     string abc;
+107     int def;
+108 }
+109 
+110 C c = new C;
+111 
+112 success = c.setMemberByName("abc", "this is abc");
+113 assert(success);
+114 assert((c.abc == "this is abc"), c.abc);
+115 
+116 success = c.setMemberByName("def", "42");
+117 assert(success);
+118 assert((c.def == 42), c.def.to!string);
+119 
+120 import lu.conv : Enum;
+121 
+122 enum E { abc, def, ghi }
+123 
+124 struct S
+125 {
+126     E e = E.ghi;
+127 }
+128 
+129 S s;
+130 
+131 assert(s.e == E.ghi);
+132 success = s.setMemberByName("e", "def");
+133 assert(success);
+134 assert((s.e == E.def), Enum!E.toString(s.e));
+135 
+136 struct StructWithOpAssign
+137 {
+138     string thing = "init";
+139 
+140     void opAssign(const string thing)
+141     {
+142         this.thing = thing;
+143     }
+144 }
+145 
+146 StructWithOpAssign assignable;
+147 assert((assignable.thing == "init"), assignable.thing);
+148 assignable = "new thing";
+149 assert((assignable.thing == "new thing"), assignable.thing);
+150 
+151 struct StructWithAssignableMember
+152 {
+153     StructWithOpAssign child;
+154 }
+155 
+156 StructWithAssignableMember parent;
+157 success = parent.setMemberByName("child", "flerp");
+158 assert(success);
+159 assert((parent.child.thing == "flerp"), parent.child.thing);
+160 
+161 class ClassWithOpAssign
+162 {
+163     string thing = "init";
+164 
+165     void opAssign(const string thing) //@safe pure nothrow @nogc
+166     {
+167         this.thing = thing;
+168     }
+169 }
+170 
+171 class ClassWithAssignableMember
+172 {
+173     ClassWithOpAssign child;
+174 
+175     this()
+176     {
+177         child = new ClassWithOpAssign;
+178     }
+179 }
+180 
+181 ClassWithAssignableMember parent2 = new ClassWithAssignableMember;
+182 success = parent2.setMemberByName("child", "flerp");
+183 assert(success);
+184 assert((parent2.child.thing == "flerp"), parent2.child.thing);
+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.setMemberByName.2.html b/lu.objmanip.setMemberByName.2.html new file mode 100644 index 00000000..d2c3eb06 --- /dev/null +++ b/lu.objmanip.setMemberByName.2.html @@ -0,0 +1,80 @@ + + + + setMemberByName (lu.objmanip.setMemberByName) + + + + + + + + + + +
+
+

setMemberByName

Given a struct/class object, sets one of its members by its string name to a + specified value. Overload that takes a value of the same type as the target + member, rather than a string to convert. Integer promotion applies.

It does not currently recurse into other struct/class members.

  1. bool setMemberByName(Thing thing, string memberToSet, string valueToSet)
  2. bool setMemberByName(Thing thing, string memberToSet, Val valueToSet)
    bool
    setMemberByName
    (
    Thing
    Val
    )
    (
    ref Thing thing
    ,
    const string memberToSet
    ,)
    if (
    isAggregateType!Thing &&
    isMutable!Thing
    &&
    !is(Val : string)
    )

Parameters

thing Thing

Reference object whose members to set.

memberToSet string

String name of the thing's member to set.

valueToSet Val

Value, of the same type as the target member.

Return Value

Type: bool

true if a member was found and set, false if not.

Throws

SetMemberException if the passed valueToSet was not the same type + (or implicitly convertible to) the member to set.

Examples

struct Foo
+{
+    int i;
+    double d;
+}
+
+Foo foo;
+
+foo.setMemberByName("i", 42);
+foo.setMemberByName("d", 3.14);
+
+assert(foo.i == 42);
+assert(foo.d = 3.14);
import std.conv : to;
+import std.exception : assertThrown;
+
+struct Foo
+{
+    string s;
+    int i;
+    bool b;
+    const double d;
+}
+
+Foo foo;
+
+bool success;
+
+success = foo.setMemberByName("s", "harbl");
+assert(success);
+assert((foo.s == "harbl"), foo.s);
+
+success = foo.setMemberByName("i", 42);
+assert(success);
+assert((foo.i == 42), foo.i.to!string);
+
+success = foo.setMemberByName("b", true);
+assert(success);
+assert(foo.b);
+
+success = foo.setMemberByName("d", 3.14);
+assert(!success);
+
+assertThrown!SetMemberException(foo.setMemberByName("b", 3.14));
+ +
+ + + \ No newline at end of file diff --git a/lu.objmanip.setMemberByName.html b/lu.objmanip.setMemberByName.html new file mode 100644 index 00000000..09e24575 --- /dev/null +++ b/lu.objmanip.setMemberByName.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.semver.LuSemVer.html b/lu.semver.LuSemVer.html new file mode 100644 index 00000000..8496b260 --- /dev/null +++ b/lu.semver.LuSemVer.html @@ -0,0 +1,35 @@ + + + + LuSemVer (lu.semver.LuSemVer) + + + + + + + + + + +
+
+

LuSemVer

SemVer versioning of this build.

Values

ValueMeaning
major2

SemVer major version of the library.

minor0

SemVer minor version of the library.

patch0

SemVer patch version of the library.

+ +
+ + + \ No newline at end of file diff --git a/lu.semver.LuSemVerPrerelease.html b/lu.semver.LuSemVerPrerelease.html new file mode 100644 index 00000000..17eacd65 --- /dev/null +++ b/lu.semver.LuSemVerPrerelease.html @@ -0,0 +1,35 @@ + + + + LuSemVerPrerelease (lu.semver.LuSemVerPrerelease) + + + + + + + + + + +
+
+

LuSemVerPrerelease

Pre-release SemVer subversion of this build.

enum LuSemVerPrerelease = string.init;
+ +
+ + + \ No newline at end of file diff --git a/lu.semver.html b/lu.semver.html new file mode 100644 index 00000000..9877033f --- /dev/null +++ b/lu.semver.html @@ -0,0 +1,36 @@ + + + + lu.semver (lu.semver) + + + + + + + + + + +
+
+

lu.semver

SemVer information about the current release.

Contains only definitions, no code. Helps importing projects tell what + features are available.

Members

Enums

LuSemVer
enum LuSemVer

SemVer versioning of this build.

Manifest constants

LuSemVerPrerelease
enum LuSemVerPrerelease;

Pre-release SemVer subversion of this build.

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.DeserialisationException.html b/lu.serialisation.DeserialisationException.html new file mode 100644 index 00000000..74435fc1 --- /dev/null +++ b/lu.serialisation.DeserialisationException.html @@ -0,0 +1,36 @@ + + + + DeserialisationException (lu.serialisation.DeserialisationException) + + + + + + + + + + +
+
+

DeserialisationException

Exception, to be thrown when the specified serialised text could not be + parsed, for whatever reason.

@safe final
class DeserialisationException : Exception {}

Constructors

this
this(string message, string file, size_t line, Throwable nextInChain)

Create a new DeserialisationException.

+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.DeserialisationException.this.html b/lu.serialisation.DeserialisationException.this.html new file mode 100644 index 00000000..a80636e8 --- /dev/null +++ b/lu.serialisation.DeserialisationException.this.html @@ -0,0 +1,35 @@ + + + + DeserialisationException.this (lu.serialisation.DeserialisationException.this) + + + + + + + + + + +
+
+

DeserialisationException.this

class DeserialisationException
pure nothrow @nogc @safe
this
(
const string message
,
const string file = __FILE__
,
const size_t line = __LINE__
,
Throwable nextInChain = null
)
+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.SerialisationUDAs.arrayPattern.html b/lu.serialisation.SerialisationUDAs.arrayPattern.html new file mode 100644 index 00000000..7ac21a42 --- /dev/null +++ b/lu.serialisation.SerialisationUDAs.arrayPattern.html @@ -0,0 +1,36 @@ + + + + SerialisationUDAs.arrayPattern (lu.serialisation.SerialisationUDAs.arrayPattern) + + + + + + + + + + +
+
+

SerialisationUDAs.arrayPattern

The format pattern used to format the array this struct + refers to. This is separator-specific.

enum arrayPattern = "%-(%s" ~ separator ~ "%)";
struct SerialisationUDAs
string arrayPattern;
+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.SerialisationUDAs.escapedSeparator.html b/lu.serialisation.SerialisationUDAs.escapedSeparator.html new file mode 100644 index 00000000..9cba8b1b --- /dev/null +++ b/lu.serialisation.SerialisationUDAs.escapedSeparator.html @@ -0,0 +1,35 @@ + + + + SerialisationUDAs.escapedSeparator (lu.serialisation.SerialisationUDAs.escapedSeparator) + + + + + + + + + + +
+
+

SerialisationUDAs.escapedSeparator

The escaped form of separator.

enum escapedSeparator = '\\' ~ separator;
struct SerialisationUDAs
string escapedSeparator;
+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.SerialisationUDAs.html b/lu.serialisation.SerialisationUDAs.html new file mode 100644 index 00000000..a5d07e01 --- /dev/null +++ b/lu.serialisation.SerialisationUDAs.html @@ -0,0 +1,37 @@ + + + + SerialisationUDAs (lu.serialisation.SerialisationUDAs) + + + + + + + + + + +
+
+

SerialisationUDAs

Summary of UDAs that an array to be serialised is annotated with.

UDAs do not persist across function calls, so they must be summarised + (such as in a struct like this) and separately passed, at compile-time or runtime.

Members

Variables

arrayPattern
string arrayPattern;

The format pattern used to format the array this struct + refers to. This is separator-specific.

escapedSeparator
string escapedSeparator;

The escaped form of separator.

separator
string separator;

Whether or not the member was annotated with a Separator.

unserialisable
bool unserialisable;

Whether or not the member was annotated Unserialisable.

+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.SerialisationUDAs.separator.html b/lu.serialisation.SerialisationUDAs.separator.html new file mode 100644 index 00000000..682244ff --- /dev/null +++ b/lu.serialisation.SerialisationUDAs.separator.html @@ -0,0 +1,35 @@ + + + + SerialisationUDAs.separator (lu.serialisation.SerialisationUDAs.separator) + + + + + + + + + + +
+
+

SerialisationUDAs.separator

Whether or not the member was annotated with a Separator.

struct SerialisationUDAs
string separator;
+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.SerialisationUDAs.unserialisable.html b/lu.serialisation.SerialisationUDAs.unserialisable.html new file mode 100644 index 00000000..8ac8db8e --- /dev/null +++ b/lu.serialisation.SerialisationUDAs.unserialisable.html @@ -0,0 +1,35 @@ + + + + SerialisationUDAs.unserialisable (lu.serialisation.SerialisationUDAs.unserialisable) + + + + + + + + + + +
+
+

SerialisationUDAs.unserialisable

Whether or not the member was annotated Unserialisable.

struct SerialisationUDAs
bool unserialisable;
+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.deserialise.html b/lu.serialisation.deserialise.html new file mode 100644 index 00000000..0ad5b8ec --- /dev/null +++ b/lu.serialisation.deserialise.html @@ -0,0 +1,290 @@ + + + + deserialise (lu.serialisation.deserialise) + + + + + + + + + + +
+
+

deserialise

Takes an input range containing serialised entry-value text and applies the + contents therein to one or more passed struct/class objects.

@safe pure
void
deserialise
(
Range
Things...
)
(
auto ref Range range
,
out string[][string] missingEntries
,
out string[][string] invalidEntries
,
ref Things things
)
if (
allSatisfy!(isAggregateType, Things) &&
allSatisfy!(isMutable, Things)
)

Parameters

range Range

Input range from which to read the serialised text.

missingEntries string[][string]

Out reference of an associative array of string arrays + of expected entries that were missing.

invalidEntries string[][string]

Out reference of an associative array of string arrays + of unexpected entries that did not belong.

things Things

Reference variadic list of one or more objects to apply the + deserialised values to.

Throws

DeserialisationException if there were bad lines.

Examples

struct Foo
+{
+    // ...
+}
+
+struct Bar
+{
+    // ...
+}
+
+Foo foo;
+Bar bar;
+
+string[][string] missingEntries;
+string[][string] invalidEntries;
+
+string fromFile = readText("configuration.conf");
+
+fromFile
+    .splitter("\n")
+    .deserialise(missingEntries, invalidEntries, foo, bar);
1     import lu.uda : Separator;
+2     import std.algorithm.iteration : splitter;
+3     import std.conv : text;
+4 
+5     struct FooSettings
+6     {
+7         enum Bar { blaawp = 5, oorgle = -1 }
+8         int i;
+9         string s;
+10         bool b;
+11         float f;
+12         double d;
+13         Bar bar;
+14         string commented;
+15         string slashed;
+16         int missing;
+17         //bool invalid;
+18 
+19         @Separator(",")
+20         {
+21             int[] ia;
+22             string[] sa;
+23             bool[] ba;
+24             float[] fa;
+25             double[] da;
+26             Bar[] bara;
+27         }
+28     }
+29 
+30     enum serialisedFileContents =
+31 `[Foo]
+32 i       42
+33 ia      1,2,-3,4,5
+34 s       hello world!
+35 sa      hello,world,!
+36 b       true
+37 ba      true,false,true
+38 invalid name
+39 
+40 # comment
+41 ; other type of comment
+42 // third type of comment
+43 
+44 f       3.14 #hirp
+45 fa      0.0,1.1,-2.2,3.3 ;herp
+46 d       99.9 //derp
+47 da      99.9999,0.0001,-1
+48 bar     oorgle
+49 bara    blaawp,oorgle,blaawp
+50 #commented hi
+51 // slashed also commented
+52 invalid ho
+53 
+54 [DifferentSection]
+55 ignored completely
+56 because no DifferentSection struct was passed
+57 nil     5
+58 naN     !"¤%&/`;
+59 
+60     string[][string] missing;
+61     string[][string] invalid;
+62 
+63     FooSettings foo;
+64     serialisedFileContents
+65         .splitter("\n")
+66         .deserialise(missing, invalid, foo);
+67 
+68     with (foo)
+69     {
+70         assert((i == 42), i.text);
+71         assert((ia == [ 1, 2, -3, 4, 5 ]), ia.text);
+72         assert((s == "hello world!"), s);
+73         assert((sa == [ "hello", "world", "!" ]), sa.text);
+74         assert(b);
+75         assert((ba == [ true, false, true ]), ba.text);
+76         assert((f == 3.14f), f.text);
+77         assert((fa == [ 0.0f, 1.1f, -2.2f, 3.3f ]), fa.text);
+78         assert((d == 99.9), d.text);
+79 
+80         static if (__VERSION__ >= 2091)
+81         {
+82             import std.math : isClose;
+83         }
+84         else
+85         {
+86             import std.math : approxEqual;
+87             alias isClose = approxEqual;
+88         }
+89 
+90         // rounding errors with LDC on Windows
+91         assert(isClose(da[0], 99.9999), da[0].text);
+92         assert(isClose(da[1], 0.0001), da[1].text);
+93         assert(isClose(da[2], -1.0), da[2].text);
+94 
+95         with (FooSettings.Bar)
+96         {
+97             assert((bar == oorgle), bar.text);
+98             assert((bara == [ blaawp, oorgle, blaawp ]), bara.text);
+99         }
+100     }
+101 
+102     import std.algorithm.searching : canFind;
+103 
+104     assert("Foo" in missing);
+105     assert(missing["Foo"].canFind("missing"));
+106     assert(!missing["Foo"].canFind("commented"));
+107     assert(!missing["Foo"].canFind("slashed"));
+108     assert("Foo" in invalid);
+109     assert(invalid["Foo"].canFind("invalid"));
+110 
+111     struct DifferentSection
+112     {
+113         string ignored;
+114         string because;
+115         int nil;
+116         string naN;
+117     }
+118 
+119     // Can read other structs from the same file
+120 
+121     DifferentSection diff;
+122     serialisedFileContents
+123         .splitter("\n")
+124         .deserialise(missing, invalid, diff);
+125 
+126     with (diff)
+127     {
+128         assert((ignored == "completely"), ignored);
+129         assert((because == "no DifferentSection struct was passed"), because);
+130         assert((nil == 5), nil.text);
+131         assert((naN == `!"¤%&/`), naN);
+132     }
+133 
+134     enum Letters { abc, def, ghi, }
+135 
+136     struct Struct
+137     {
+138         Letters lt = Letters.def;
+139     }
+140 
+141     enum configContents =
+142 `[Struct]
+143 lt ghi
+144 `;
+145     Struct st;
+146     configContents
+147         .splitter("\n")
+148         .deserialise(missing, invalid, st);
+149 
+150     assert(st.lt == Letters.ghi);
+151 
+152     class Class
+153     {
+154         enum Bar { blaawp = 5, oorgle = -1 }
+155         int i;
+156         string s;
+157         bool b;
+158         float f;
+159         double d;
+160         Bar bar;
+161         string omitted;
+162 
+163         @Separator(",")
+164         {
+165             int[] ia;
+166             string[] sa;
+167             bool[] ba;
+168             float[] fa;
+169             double[] da;
+170             Bar[] bara;
+171         }
+172     }
+173 
+174     enum serialisedFileContentsClass =
+175 `[Class]
+176 i       42
+177 ia      1,2,-3,4,5
+178 s       hello world!
+179 sa      hello,world,!
+180 b       true
+181 ba      true,false,true
+182 wrong   name
+183 
+184 # comment
+185 ; other type of comment
+186 // third type of comment
+187 
+188 f       3.14 #hirp
+189 fa      0.0,1.1,-2.2,3.3 ;herp
+190 d       99.9 //derp
+191 da      99.9999,0.0001,-1
+192 bar     oorgle
+193 bara    blaawp,oorgle,blaawp`;
+194 
+195     Class c = new Class;
+196     serialisedFileContentsClass
+197         .splitter("\n")
+198         .deserialise(missing, invalid, c);
+199 
+200     with (c)
+201     {
+202         assert((i == 42), i.text);
+203         assert((ia == [ 1, 2, -3, 4, 5 ]), ia.text);
+204         assert((s == "hello world!"), s);
+205         assert((sa == [ "hello", "world", "!" ]), sa.text);
+206         assert(b);
+207         assert((ba == [ true, false, true ]), ba.text);
+208         assert((f == 3.14f), f.text);
+209         assert((fa == [ 0.0f, 1.1f, -2.2f, 3.3f ]), fa.text);
+210         assert((d == 99.9), d.text);
+211 
+212         static if (__VERSION__ >= 2091)
+213         {
+214             import std.math : isClose;
+215         }
+216         else
+217         {
+218             import std.math : approxEqual;
+219             alias isClose = approxEqual;
+220         }
+221 
+222         // rounding errors with LDC on Windows
+223         assert(isClose(da[0], 99.9999), da[0].text);
+224         assert(isClose(da[1], 0.0001), da[1].text);
+225         assert(isClose(da[2], -1.0), da[2].text);
+226 
+227         with (Class.Bar)
+228         {
+229             assert((bar == oorgle), b.text);
+230             assert((bara == [ blaawp, oorgle, blaawp ]), bara.text);
+231         }
+232     }
+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.html b/lu.serialisation.html new file mode 100644 index 00000000..de3b6ee0 --- /dev/null +++ b/lu.serialisation.html @@ -0,0 +1,90 @@ + + + + lu.serialisation (lu.serialisation) + + + + + + + + + + +
+
+

lu.serialisation

Various functions related to serialising and deserialising structs into/from + .ini-like files.

Members

Classes

DeserialisationException
class DeserialisationException

Exception, to be thrown when the specified serialised text could not be + parsed, for whatever reason.

Enums

CannotContainComments (from lu.uda)
enum CannotContainComments via public +import lu.uda : CannotContainComments, Quoted, Separator, Unserialisable;

UDA conveying that this member may contain characters that would otherwise + indicate a comment, but isn't.

Quoted (from lu.uda)
enum Quoted via public +import lu.uda : CannotContainComments, Quoted, Separator, Unserialisable;

UDA conveying that this member's value must be quoted when serialised.

Unserialisable (from lu.uda)
enum Unserialisable via public +import lu.uda : CannotContainComments, Quoted, Separator, Unserialisable;

UDA conveying that a field cannot (or should not) be serialised.

Functions

deserialise
void deserialise(Range range, string[][string] missingEntries, string[][string] invalidEntries, Things things)

Takes an input range containing serialised entry-value text and applies the + contents therein to one or more passed struct/class objects.

justifiedEntryValueText
string justifiedEntryValueText(string origLines)

Takes an unformatted string of serialised entry-value text and justifies it + into two neat columns.

serialise
void serialise(Sink sink, Things things)

Convenience function to call serialise on several objects.

serialise
void serialise(Sink sink, QualThing thing)

Serialises the fields of an object into an .ini file-like format.

serialiseArrayImpl
string serialiseArrayImpl(T array, SerialisationUDAs udas)

Serialises a non-string array into a single row. To be used when serialising + an aggregate with serialise.

splitEntryValue
auto splitEntryValue(string line)

Splits a line into an entry and a value component.

Structs

Separator (from lu.uda)
struct Separator via public +import lu.uda : CannotContainComments, Quoted, Separator, Unserialisable;

UDA conveying that the annotated array should have this token as separator + when formatted to a string.

SerialisationUDAs
struct SerialisationUDAs

Summary of UDAs that an array to be serialised is annotated with.

Examples

 struct FooSettings
+ {
+     string fooasdf;
+     string bar;
+     string bazzzzzzz;
+     @Quoted flerrp;
+     double pi;
+ }
+
+ FooSettings f;
+
+ f.fooasdf = "foo";
+ f.bar = "bar";
+ f.bazzzzzzz = "baz";
+ f.flerrp = "hirr steff  ";
+ f.pi = 3.14159;
+
+ enum fooSerialised =
+`[Foo]
+ fooasdf foo
+ bar bar
+ bazzzzzzz baz
+ flerrp "hirr steff  "
+ pi 3.14159`;
+
+ enum fooJustified =
+ `[Foo]
+ fooasdf                 foo
+ bar                     bar
+ bazzzzzzz               baz
+ flerrp                  "hirr steff  "
+ pi                      3.14159`;
+
+ Appender!(char[]) sink;
+
+ sink.serialise(f);
+ assert(sink.data.justifiedEntryValueText == fooJustified);
+
+ FooSettings mirror;
+ deserialise(fooSerialised, mirror);
+ assert(mirror == f);
+
+ FooSettings mirror2;
+ deserialise(fooJustified, mirror2);
+ assert(mirror2 == mirror);

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.justifiedEntryValueText.html b/lu.serialisation.justifiedEntryValueText.html new file mode 100644 index 00000000..59a0d183 --- /dev/null +++ b/lu.serialisation.justifiedEntryValueText.html @@ -0,0 +1,142 @@ + + + + justifiedEntryValueText (lu.serialisation.justifiedEntryValueText) + + + + + + + + + + +
+
+

justifiedEntryValueText

Takes an unformatted string of serialised entry-value text and justifies it + into two neat columns.

It does one pass through it all first to determine the maximum width of the + entry names, then another to format it and eventually return a flat string.

@safe pure
string
justifiedEntryValueText
(
const string origLines
)

Parameters

origLines string

Unjustified raw serialised text.

Return Value

Type: string

.ini file-like text, justified into two columns.

Examples

struct Foo
+{
+    // ...
+}
+
+struct Bar
+{
+    // ...
+}
+
+Foo foo;
+Bar bar;
+
+Appender!(char[]) sink;
+
+sink.serialise(foo, bar);
+immutable justified = sink.data.justifiedEntryValueText;
1     import std.algorithm.iteration : splitter;
+2     import std.array : Appender;
+3     import lu.uda : Separator;
+4 
+5     struct Foo
+6     {
+7         enum Bar { blaawp = 5, oorgle = -1 }
+8         int someInt = 42;
+9         string someString = "hello world!";
+10         bool someBool = true;
+11         float someFloat = 3.14f;
+12         double someDouble = 99.9;
+13         Bar someBars = Bar.oorgle;
+14         string harbl;
+15 
+16         @Separator(",")
+17         {
+18             int[] intArray = [ 1, 2, -3, 4, 5 ];
+19             string[] stringArrayy = [ "hello", "world", "!" ];
+20             bool[] boolArray = [ true, false, true ];
+21             float[] floatArray = [ 0.0, 1.1, -2.2, 3.3 ];
+22             double[] doubleArray = [ 99.9999, 0.0001, -1.0 ];
+23             Bar[] barArray = [ Bar.blaawp, Bar.oorgle, Bar.blaawp ];
+24             string[] yarn;
+25         }
+26     }
+27 
+28     struct DifferentSection
+29     {
+30         string ignored = "completely";
+31         string because = "   no DifferentSection struct was passed";
+32         int nil = 5;
+33         string naN = `!"#¤%&/`;
+34     }
+35 
+36     Appender!(char[]) sink;
+37     sink.reserve(512);
+38     Foo foo;
+39     DifferentSection diff;
+40     enum unjustified =
+41 `[Foo]
+42 someInt 42
+43 someString hello world!
+44 someBool true
+45 someFloat 3.14
+46 someDouble 99.9
+47 someBars oorgle
+48 #harbl
+49 intArray 1,2,-3,4,5
+50 stringArrayy hello,world,!
+51 boolArray true,false,true
+52 floatArray 0,1.1,-2.2,3.3
+53 doubleArray 99.9999,0.0001,-1
+54 barArray blaawp,oorgle,blaawp
+55 #yarn
+56 
+57 [DifferentSection]
+58 ignored completely
+59 because    no DifferentSection struct was passed
+60 nil 5
+61 naN !"#¤%&/`;
+62 
+63     enum justified =
+64 `[Foo]
+65 someInt                 42
+66 someString              hello world!
+67 someBool                true
+68 someFloat               3.14
+69 someDouble              99.9
+70 someBars                oorgle
+71 #harbl
+72 intArray                1,2,-3,4,5
+73 stringArrayy            hello,world,!
+74 boolArray               true,false,true
+75 floatArray              0,1.1,-2.2,3.3
+76 doubleArray             99.9999,0.0001,-1
+77 barArray                blaawp,oorgle,blaawp
+78 #yarn
+79 
+80 [DifferentSection]
+81 ignored                 completely
+82 because                 no DifferentSection struct was passed
+83 nil                     5
+84 naN                     !"#¤%&/`;
+85 
+86     sink.serialise(foo, diff);
+87     assert((sink.data == unjustified), '\n' ~ sink.data);
+88     immutable configText = justifiedEntryValueText(sink.data.idup);
+89 
+90     assert((configText == justified), '\n' ~ configText);
+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.serialise.1.html b/lu.serialisation.serialise.1.html new file mode 100644 index 00000000..5b74ddb0 --- /dev/null +++ b/lu.serialisation.serialise.1.html @@ -0,0 +1,52 @@ + + + + serialise (lu.serialisation.serialise) + + + + + + + + + + +
+
+

serialise

Convenience function to call serialise on several objects.

  1. void serialise(Sink sink, Things things)
    void
    serialise
    (
    Sink
    Things...
    )
    (
    auto ref Sink sink
    ,
    auto ref Things things
    )
    if (
    (Things.length > 1) &&
    isOutputRange!(Sink, char[])
    &&
    allSatisfy!(isAggregateType, Things)
    )
  2. void serialise(Sink sink, QualThing thing)

Parameters

sink Sink

Reference output range to write the serialised objects to (in + their .ini file-like format).

things Things

Variadic list of objects to serialise.

Examples

struct Foo
+{
+    // ...
+}
+
+struct Bar
+{
+    // ...
+}
+
+Foo foo;
+Bar bar;
+
+Appender!(char[]) sink;
+
+sink.serialise(foo, bar);
+assert(!sink.data.empty);
+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.serialise.2.html b/lu.serialisation.serialise.2.html new file mode 100644 index 00000000..982d28a5 --- /dev/null +++ b/lu.serialisation.serialise.2.html @@ -0,0 +1,162 @@ + + + + serialise (lu.serialisation.serialise) + + + + + + + + + + +
+
+

serialise

Serialises the fields of an object into an .ini file-like format.

It only serialises fields not annotated with + Unserialisable, and it doesn't recurse into other + structs or classes.

  1. void serialise(Sink sink, Things things)
  2. void serialise(Sink sink, QualThing thing)
    void
    serialise
    (
    Sink
    QualThing
    )
    (
    auto ref Sink sink
    ,
    auto ref QualThing thing
    )
    if (
    isOutputRange!(Sink, char[]) &&
    isAggregateType!QualThing
    )

Parameters

sink Sink

Reference output range to write to, usually an + Appender.

thing QualThing

Object to serialise.

Examples

struct Foo
+{
+    // ...
+}
+
+Foo foo;
+
+Appender!(char[]) sink;
+
+sink.serialise(foo);
+assert(!sink.data.empty);
1     import lu.uda : Separator, Quoted;
+2     import std.array : Appender;
+3 
+4     struct FooSettings
+5     {
+6         string fooasdf = "foo 1";
+7         string bar = "foo 1";
+8         string bazzzzzzz = "foo 1";
+9         @Quoted flerrp = "hirr steff  ";
+10         double pi = 3.14159;
+11         @Separator(",") int[] arr = [ 1, 2, 3 ];
+12         @Separator(";") string[] harbl = [ "harbl;;", ";snarbl;", "dirp" ];
+13 
+14         static if (__VERSION__ >= 2087L)
+15         {
+16             @("|") string[] matey = [ "a", "b", "c" ];
+17         }
+18     }
+19 
+20     struct BarSettings
+21     {
+22         string foofdsa = "foo 2";
+23         string bar = "bar 2";
+24         string bazyyyyyyy = "baz 2";
+25         @Quoted flarrp = "   hirrsteff";
+26         double pipyon = 3.0;
+27     }
+28 
+29     static if (__VERSION__ >= 2087L)
+30     {
+31         enum fooSerialised =
+32 `[Foo]
+33 fooasdf foo 1
+34 bar foo 1
+35 bazzzzzzz foo 1
+36 flerrp "hirr steff  "
+37 pi 3.14159
+38 arr 1,2,3
+39 harbl harbl\;\;;\;snarbl\;;dirp
+40 matey a|b|c`;
+41     }
+42     else
+43     {
+44         enum fooSerialised =
+45 `[Foo]
+46 fooasdf foo 1
+47 bar foo 1
+48 bazzzzzzz foo 1
+49 flerrp "hirr steff  "
+50 pi 3.14159
+51 arr 1,2,3
+52 harbl harbl\;\;;\;snarbl\;;dirp`;
+53     }
+54 
+55     Appender!(char[]) fooSink;
+56     fooSink.reserve(64);
+57 
+58     fooSink.serialise(FooSettings.init);
+59     assert((fooSink.data == fooSerialised), '\n' ~ fooSink.data);
+60 
+61     enum barSerialised =
+62 `[Bar]
+63 foofdsa foo 2
+64 bar bar 2
+65 bazyyyyyyy baz 2
+66 flarrp "   hirrsteff"
+67 pipyon 3`;
+68 
+69     Appender!(char[]) barSink;
+70     barSink.reserve(64);
+71 
+72     barSink.serialise(BarSettings.init);
+73     assert((barSink.data == barSerialised), '\n' ~ barSink.data);
+74 
+75     // try two at once
+76     Appender!(char[]) bothSink;
+77     bothSink.reserve(128);
+78     bothSink.serialise(FooSettings.init, BarSettings.init);
+79     assert(bothSink.data == fooSink.data ~ "\n\n" ~ barSink.data);
+80 
+81     class C
+82     {
+83         int i;
+84         bool b;
+85     }
+86 
+87     C c = new C;
+88     c.i = 42;
+89     c.b = true;
+90 
+91     enum cSerialised =
+92 `[C]
+93 i 42
+94 b true`;
+95 
+96     Appender!(char[]) cSink;
+97     cSink.reserve(128);
+98     cSink.serialise(c);
+99     assert((cSink.data == cSerialised), '\n' ~ cSink.data);
+100 
+101     enum Letters { abc, def, ghi, }
+102 
+103     struct Struct
+104     {
+105         Letters let = Letters.def;
+106     }
+107 
+108     enum enumTestSerialised =
+109 `[Struct]
+110 let def`;
+111 
+112     Struct st;
+113     Appender!(char[]) enumTestSink;
+114     enumTestSink.serialise(st);
+115     assert((enumTestSink.data == enumTestSerialised), '\n' ~ enumTestSink.data);
+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.serialise.html b/lu.serialisation.serialise.html new file mode 100644 index 00000000..ee73b6bb --- /dev/null +++ b/lu.serialisation.serialise.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.serialisation.serialiseArrayImpl.html b/lu.serialisation.serialiseArrayImpl.html new file mode 100644 index 00000000..d4d11d8e --- /dev/null +++ b/lu.serialisation.serialiseArrayImpl.html @@ -0,0 +1,38 @@ + + + + serialiseArrayImpl (lu.serialisation.serialiseArrayImpl) + + + + + + + + + + +
+
+

serialiseArrayImpl

Serialises a non-string array into a single row. To be used when serialising + an aggregate with serialise.

Since UDAs do not persist across function calls, they must be summarised + in a SerialisationUDAs struct separately so we can pass them at runtime.

private
string
serialiseArrayImpl
(
T
)
(
const auto ref T array
,)

Parameters

array T

Array to serialise.

udas SerialisationUDAs

Aggregate of UDAs the original array was annotated with, passed as + a runtime value.

Return Value

Type: string

A string, to be saved as a serialised row in an .ini file-like format.

+ +
+ + + \ No newline at end of file diff --git a/lu.serialisation.splitEntryValue.html b/lu.serialisation.splitEntryValue.html new file mode 100644 index 00000000..ce0ad4f0 --- /dev/null +++ b/lu.serialisation.splitEntryValue.html @@ -0,0 +1,64 @@ + + + + splitEntryValue (lu.serialisation.splitEntryValue) + + + + + + + + + + +
+
+

splitEntryValue

Splits a line into an entry and a value component.

This drop-in-replaces the regex: ^(?P<entry>[^ \t]+)[ \t]+(?P<value>.+).

@safe pure nothrow @nogc
splitEntryValue
(
const string line
)

Parameters

line string

String to split up.

Return Value

Type: auto

A Voldemort struct with an entry and a value member.

Examples

{
+    immutable line = "monochrome            true";
+    immutable result = splitEntryValue(line);
+    assert((result.entry == "monochrome"), result.entry);
+    assert((result.value == "true"), result.value);
+}
+{
+    immutable line = "monochrome\tfalse";
+    immutable result = splitEntryValue(line);
+    assert((result.entry == "monochrome"), result.entry);
+    assert((result.value == "false"), result.value);
+}
+{
+    immutable line = "harbl                  ";
+    immutable result = splitEntryValue(line);
+    assert((result.entry == "harbl"), result.entry);
+    assert(!result.value.length, result.value);
+}
+{
+    immutable line = "ha\t \t \t\t  \t  \t      \tha";
+    immutable result = splitEntryValue(line);
+    assert((result.entry == "ha"), result.entry);
+    assert((result.value == "ha"), result.value);
+}
+{
+    immutable line = "#sendAfterConnect";
+    immutable result = splitEntryValue(line);
+    assert((result.entry == "#sendAfterConnect"), result.entry);
+    assert(!result.value.length, result.value);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceException.haystack.html b/lu.string.AdvanceException.haystack.html new file mode 100644 index 00000000..ce1ce7b3 --- /dev/null +++ b/lu.string.AdvanceException.haystack.html @@ -0,0 +1,35 @@ + + + + AdvanceException.haystack (lu.string.AdvanceException.haystack) + + + + + + + + + + +
+
+

AdvanceException.haystack

Returns a string of the original haystack the call to advancePast was operating on.

class AdvanceException
pure @safe
string
haystack
()
+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceException.html b/lu.string.AdvanceException.html new file mode 100644 index 00000000..8ca8115c --- /dev/null +++ b/lu.string.AdvanceException.html @@ -0,0 +1,35 @@ + + + + AdvanceException (lu.string.AdvanceException) + + + + + + + + + + +
+
+

AdvanceException

Exception, to be thrown when a call to advancePast went wrong.

It is a normal Exception but with an attached needle and haystack.

Constructors

this
this(string message, string file, size_t line, Throwable nextInChain)

Create a new AdvanceExceptionImpl, without attaching anything.

Members

Functions

haystack
string haystack()

Returns a string of the original haystack the call to advancePast was operating on.

needle
string needle()

Returns a string of the original needle the call to advancePast was operating on.

+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceException.needle.html b/lu.string.AdvanceException.needle.html new file mode 100644 index 00000000..0c36af89 --- /dev/null +++ b/lu.string.AdvanceException.needle.html @@ -0,0 +1,35 @@ + + + + AdvanceException.needle (lu.string.AdvanceException.needle) + + + + + + + + + + +
+
+

AdvanceException.needle

Returns a string of the original needle the call to advancePast was operating on.

class AdvanceException
pure @safe
string
needle
()
+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceException.this.html b/lu.string.AdvanceException.this.html new file mode 100644 index 00000000..147f860e --- /dev/null +++ b/lu.string.AdvanceException.this.html @@ -0,0 +1,35 @@ + + + + AdvanceException.this (lu.string.AdvanceException.this) + + + + + + + + + + +
+
+

AdvanceException.this

Create a new AdvanceExceptionImpl, without attaching anything.

class AdvanceException
pure nothrow @nogc @safe
this
(
const string message
,
const string file = __FILE__
,
const size_t line = __LINE__
,
Throwable nextInChain = null
)
+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceExceptionImpl._haystack.html b/lu.string.AdvanceExceptionImpl._haystack.html new file mode 100644 index 00000000..cde9b08d --- /dev/null +++ b/lu.string.AdvanceExceptionImpl._haystack.html @@ -0,0 +1,35 @@ + + + + AdvanceExceptionImpl._haystack (lu.string.AdvanceExceptionImpl._haystack) + + + + + + + + + + +
+
+

AdvanceExceptionImpl._haystack

Raw haystack that haystack converts to string and returns.

class AdvanceExceptionImpl(Haystack, Needle)
private
string _haystack;
+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceExceptionImpl._needle.html b/lu.string.AdvanceExceptionImpl._needle.html new file mode 100644 index 00000000..ea56cca6 --- /dev/null +++ b/lu.string.AdvanceExceptionImpl._needle.html @@ -0,0 +1,35 @@ + + + + AdvanceExceptionImpl._needle (lu.string.AdvanceExceptionImpl._needle) + + + + + + + + + + +
+
+

AdvanceExceptionImpl._needle

Raw needle that needle converts to string and returns.

class AdvanceExceptionImpl(Haystack, Needle)
private
string _needle;
+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceExceptionImpl.haystack.html b/lu.string.AdvanceExceptionImpl.haystack.html new file mode 100644 index 00000000..2c18620e --- /dev/null +++ b/lu.string.AdvanceExceptionImpl.haystack.html @@ -0,0 +1,35 @@ + + + + AdvanceExceptionImpl.haystack (lu.string.AdvanceExceptionImpl.haystack) + + + + + + + + + + +
+
+

AdvanceExceptionImpl.haystack

Returns a string of the original needle the call to advancePast was operating on.

class AdvanceExceptionImpl(Haystack, Needle)
override pure @safe
string
haystack
()

Return Value

Type: string

The raw haystack (be it any kind of string), converted to a string.

+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceExceptionImpl.html b/lu.string.AdvanceExceptionImpl.html new file mode 100644 index 00000000..27c58881 --- /dev/null +++ b/lu.string.AdvanceExceptionImpl.html @@ -0,0 +1,36 @@ + + + + AdvanceExceptionImpl (lu.string.AdvanceExceptionImpl) + + + + + + + + + + +
+
+

AdvanceExceptionImpl

Exception, to be thrown when a call to advancePast went wrong.

This is the templated implementation, so that we can support more than one + kind of needle and haystack combination.

It is a normal Exception but with an attached needle and haystack.

Constructors

this
this(string message, string file, size_t line, Throwable nextInChain)

Create a new AdvanceExceptionImpl, without attaching anything.

this
this(string message, Haystack haystack, Needle needle, string file, size_t line, Throwable nextInChain)

Create a new AdvanceExceptionImpl, attaching a command.

Members

Functions

haystack
string haystack()

Returns a string of the original needle the call to advancePast was operating on.

needle
string needle()

Returns a string of the original needle the call to advancePast was operating on.

Variables

_haystack
string _haystack;

Raw haystack that haystack converts to string and returns.

_needle
string _needle;

Raw needle that needle converts to string and returns.

Inherited Members

From AdvanceException

haystack
string haystack()

Returns a string of the original haystack the call to advancePast was operating on.

needle
string needle()

Returns a string of the original needle the call to advancePast was operating on.

Parameters

Haystack

Haystack array type.

Needle

Needle array or char-like type.

+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceExceptionImpl.needle.html b/lu.string.AdvanceExceptionImpl.needle.html new file mode 100644 index 00000000..329d467b --- /dev/null +++ b/lu.string.AdvanceExceptionImpl.needle.html @@ -0,0 +1,35 @@ + + + + AdvanceExceptionImpl.needle (lu.string.AdvanceExceptionImpl.needle) + + + + + + + + + + +
+
+

AdvanceExceptionImpl.needle

Returns a string of the original needle the call to advancePast was operating on.

class AdvanceExceptionImpl(Haystack, Needle)
override pure @safe
string
needle
()

Return Value

Type: string

The raw needle (be it any kind of string or character), converted to a string.

+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceExceptionImpl.this.1.html b/lu.string.AdvanceExceptionImpl.this.1.html new file mode 100644 index 00000000..763d855a --- /dev/null +++ b/lu.string.AdvanceExceptionImpl.this.1.html @@ -0,0 +1,35 @@ + + + + AdvanceExceptionImpl.this (lu.string.AdvanceExceptionImpl.this) + + + + + + + + + + +
+
+

AdvanceExceptionImpl.this

Create a new AdvanceExceptionImpl, without attaching anything.

  1. this(string message, string file, size_t line, Throwable nextInChain)
    class AdvanceExceptionImpl(Haystack, Needle)
    pure @safe nothrow @nogc
    this
    (
    const string message
    ,
    const string file = __FILE__
    ,
    const size_t line = __LINE__
    ,
    Throwable nextInChain = null
    )
  2. this(string message, Haystack haystack, Needle needle, string file, size_t line, Throwable nextInChain)
+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceExceptionImpl.this.2.html b/lu.string.AdvanceExceptionImpl.this.2.html new file mode 100644 index 00000000..52896f87 --- /dev/null +++ b/lu.string.AdvanceExceptionImpl.this.2.html @@ -0,0 +1,35 @@ + + + + AdvanceExceptionImpl.this (lu.string.AdvanceExceptionImpl.this) + + + + + + + + + + +
+
+

AdvanceExceptionImpl.this

Create a new AdvanceExceptionImpl, attaching a command.

  1. this(string message, string file, size_t line, Throwable nextInChain)
  2. this(string message, Haystack haystack, Needle needle, string file, size_t line, Throwable nextInChain)
    class AdvanceExceptionImpl(Haystack, Needle)
    pure @safe
    this
    (
    const string message
    ,
    const Haystack haystack
    ,
    const Needle needle
    ,
    const string file = __FILE__
    ,
    const size_t line = __LINE__
    ,
    Throwable nextInChain = null
    )
+ +
+ + + \ No newline at end of file diff --git a/lu.string.AdvanceExceptionImpl.this.html b/lu.string.AdvanceExceptionImpl.this.html new file mode 100644 index 00000000..47a13130 --- /dev/null +++ b/lu.string.AdvanceExceptionImpl.this.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.string.NomException.html b/lu.string.NomException.html new file mode 100644 index 00000000..ca1f7332 --- /dev/null +++ b/lu.string.NomException.html @@ -0,0 +1,35 @@ + + + + NomException (lu.string.NomException) + + + + + + + + + + +
+
+

NomException

Compatibility alias to AdvanceException.

@safe
alias NomException = AdvanceException
+ +
+ + + \ No newline at end of file diff --git a/lu.string.NomExceptionImpl.html b/lu.string.NomExceptionImpl.html new file mode 100644 index 00000000..40641cbe --- /dev/null +++ b/lu.string.NomExceptionImpl.html @@ -0,0 +1,35 @@ + + + + NomExceptionImpl (lu.string.NomExceptionImpl) + + + + + + + + + + +
+
+

NomExceptionImpl

Compatibility alias to AdvanceExceptionImpl.

@safe
alias NomExceptionImpl = AdvanceExceptionImpl
+ +
+ + + \ No newline at end of file diff --git a/lu.string.SplitResults.html b/lu.string.SplitResults.html new file mode 100644 index 00000000..b923b5a0 --- /dev/null +++ b/lu.string.SplitResults.html @@ -0,0 +1,35 @@ + + + + SplitResults (lu.string.SplitResults) + + + + + + + + + + +
+
+

SplitResults

The result of a call to splitInto.

Values

ValueMeaning
match

The number of arguments passed the number of separated words in the input string.

underrun

The input string did not have enough words to match the passed arguments.

overrun

The input string had too many words and could not fit into the passed arguments.

+ +
+ + + \ No newline at end of file diff --git a/lu.string.advancePast.1.html b/lu.string.advancePast.1.html new file mode 100644 index 00000000..e7466a79 --- /dev/null +++ b/lu.string.advancePast.1.html @@ -0,0 +1,238 @@ + + + + advancePast (lu.string.advancePast) + + + + + + + + + + +
+
+

advancePast

Given some string, finds the supplied needle token in it, returns the + string up to that point, and advances the passed string by ref to after the token.

The closest equivalent in Phobos is std.algorithm.searching.findSplit, + which largely serves the same function but doesn't advance the input string.

Additionally takes an optional Flag!"inherit" argument, to toggle + whether the return value inherits the passed line (and clearing it) upon no + needle match.

  1. auto advancePast(Haystack haystack, Needle needle, Flag!"inherit" inherit, string callingFile, size_t callingLine)
    @safe @safe
    advancePast
    (
    Haystack
    Needle
    )
    (
    auto ref return scope Haystack haystack
    ,
    const scope Needle needle
    ,
    const Flag!"inherit" inherit = No.inherit
    ,
    const string callingFile = __FILE__
    ,
    const size_t callingLine = __LINE__
    )
  2. auto advancePast(Haystack haystack, Needle needle, string callingFile, size_t callingLine)

Parameters

haystack Haystack

Array to walk and advance.

needle Needle

Token that delimits what should be returned and to where to advance. + May be another array or some individual character.

inherit Flag!"inherit"

Optional flag of whether or not the whole string should be + returned and the haystack variable cleared on no needle match.

callingFile string

Optional file name to attach to an exception.

callingLine size_t

Optional line number to attach to an exception.

Return Value

Type: auto

The string haystack from the start up to the needle token. The original + variable is advanced to after the token.

Throws

AdvanceException if the needle could not be found in the string.

Examples

string foobar = "foo bar!";
+string foo = foobar.advancePast(" ");
+string bar = foobar.advancePast("!");
+
+assert((foo == "foo"), foo);
+assert((bar == "bar"), bar);
+assert(!foobar.length);
+
+enum line = "abc def ghi";
+string def = line[4..$].advancePast(" ");  // now with auto ref
+
+string foobar2 = "foo bar!";
+string foo2 = foobar2.advancePast(" ");
+string bar2 = foobar2.advancePast("?", Yes.inherit);
+
+assert((foo2 == "foo"), foo2);
+assert((bar2 == "bar!"), bar2);
+assert(!foobar2.length);
+
+string slice2 = "snarfl";
+string verb2 = slice2.advancePast(" ", Yes.inherit);
+
+assert((verb2 == "snarfl"), verb2);
+assert(!slice2.length, slice2);
1 import std.conv : to;
+2 import std.string : indexOf;
+3 
+4 {
+5     string line = "Lorem ipsum :sit amet";
+6     immutable lorem = line.advancePast(" :");
+7     assert(lorem == "Lorem ipsum", lorem);
+8     assert(line == "sit amet", line);
+9 }
+10 {
+11     string line = "Lorem ipsum :sit amet";
+12     //immutable lorem = line.advancePast(" :");
+13     immutable lorem = line.advancePast(" :");
+14     assert(lorem == "Lorem ipsum", lorem);
+15     assert(line == "sit amet", line);
+16 }
+17 {
+18     string line = "Lorem ipsum :sit amet";
+19     immutable lorem = line.advancePast(':');
+20     assert(lorem == "Lorem ipsum ", lorem);
+21     assert(line == "sit amet", line);
+22 }
+23 {
+24     string line = "Lorem ipsum :sit amet";
+25     immutable lorem = line.advancePast(':');
+26     assert(lorem == "Lorem ipsum ", lorem);
+27     assert(line == "sit amet", line);
+28 }
+29 {
+30     string line = "Lorem ipsum :sit amet";
+31     immutable lorem = line.advancePast(' ');
+32     assert(lorem == "Lorem", lorem);
+33     assert(line == "ipsum :sit amet", line);
+34 }
+35 {
+36     string line = "Lorem ipsum :sit amet";
+37     immutable lorem = line.advancePast(' ');
+38     assert(lorem == "Lorem", lorem);
+39     assert(line == "ipsum :sit amet", line);
+40 }
+41 /*{
+42     string line = "Lorem ipsum :sit amet";
+43     immutable lorem = line.advancePast("");
+44     assert(!lorem.length, lorem);
+45     assert(line == "Lorem ipsum :sit amet", line);
+46 }*/
+47 /*{
+48     string line = "Lorem ipsum :sit amet";
+49     immutable lorem = line.advancePast("");
+50     assert(!lorem.length, lorem);
+51     assert(line == "Lorem ipsum :sit amet", line);
+52 }*/
+53 {
+54     string line = "Lorem ipsum :sit amet";
+55     immutable lorem = line.advancePast("Lorem ipsum");
+56     assert(!lorem.length, lorem);
+57     assert(line == " :sit amet", line);
+58 }
+59 {
+60     string line = "Lorem ipsum :sit amet";
+61     immutable lorem = line.advancePast("Lorem ipsum");
+62     assert(!lorem.length, lorem);
+63     assert(line == " :sit amet", line);
+64 }
+65 {
+66     string line = "Lorem ipsum :sit amet";
+67     immutable dchar dspace = ' ';
+68     immutable lorem = line.advancePast(dspace);
+69     assert(lorem == "Lorem", lorem);
+70     assert(line == "ipsum :sit amet", line);
+71 }
+72 {
+73     dstring dline = "Lorem ipsum :sit amet"d;
+74     immutable dspace = " "d;
+75     immutable lorem = dline.advancePast(dspace);
+76     assert((lorem == "Lorem"d), lorem.to!string);
+77     assert((dline == "ipsum :sit amet"d), dline.to!string);
+78 }
+79 {
+80     dstring dline = "Lorem ipsum :sit amet"d;
+81     immutable wchar wspace = ' ';
+82     immutable lorem = dline.advancePast(wspace);
+83     assert((lorem == "Lorem"d), lorem.to!string);
+84     assert((dline == "ipsum :sit amet"d), dline.to!string);
+85 }
+86 {
+87     wstring wline = "Lorem ipsum :sit amet"w;
+88     immutable wchar wspace = ' ';
+89     immutable lorem = wline.advancePast(wspace);
+90     assert((lorem == "Lorem"w), lorem.to!string);
+91     assert((wline == "ipsum :sit amet"w), wline.to!string);
+92 }
+93 {
+94     wstring wline = "Lorem ipsum :sit amet"w;
+95     immutable wspace = " "w;
+96     immutable lorem = wline.advancePast(wspace);
+97     assert((lorem == "Lorem"w), lorem.to!string);
+98     assert((wline == "ipsum :sit amet"w), wline.to!string);
+99 }
+100 {
+101     string user = "foo!bar@asdf.adsf.com";
+102     user = user.advancePast('!');
+103     assert((user == "foo"), user);
+104 }
+105 {
+106     immutable def = "abc def ghi"[4..$].advancePast(" ");
+107     assert((def == "def"), def);
+108 }
+109 {
+110     import std.exception : assertThrown;
+111     assertThrown!AdvanceException("abc def ghi"[4..$].advancePast(""));
+112 }
+113 {
+114     string line = "Lorem ipsum";
+115     immutable head = line.advancePast(" ");
+116     assert((head == "Lorem"), head);
+117     assert((line == "ipsum"), line);
+118 }
+119 {
+120     string line = "Lorem";
+121     immutable head = line.advancePast(" ", Yes.inherit);
+122     assert((head == "Lorem"), head);
+123     assert(!line.length, line);
+124 }
+125 {
+126     string slice = "verb";
+127     string verb;
+128 
+129     if (slice.indexOf(' ') != -1)
+130     {
+131         verb = slice.advancePast(' ');
+132     }
+133     else
+134     {
+135         verb = slice;
+136         slice = string.init;
+137     }
+138 
+139     assert((verb == "verb"), verb);
+140     assert(!slice.length, slice);
+141 }
+142 {
+143     string slice = "verb";
+144     immutable verb = slice.advancePast(' ', Yes.inherit);
+145     assert((verb == "verb"), verb);
+146     assert(!slice.length, slice);
+147 }
+148 {
+149     string url = "https://google.com/index.html#fragment-identifier";
+150     url = url.advancePast('#', Yes.inherit);
+151     assert((url == "https://google.com/index.html"), url);
+152 }
+153 {
+154     string url = "https://google.com/index.html";
+155     url = url.advancePast('#', Yes.inherit);
+156     assert((url == "https://google.com/index.html"), url);
+157 }
+158 {
+159     string line = "Lorem ipsum sit amet";
+160     string[] words;
+161 
+162     while (line.length > 0)
+163     {
+164         immutable word = line.advancePast(" ", Yes.inherit);
+165         words ~= word;
+166     }
+167 
+168     assert(words == [ "Lorem", "ipsum", "sit", "amet" ]);
+169 }
+170 {
+171     import std.exception : assertThrown;
+172     string url = "https://google.com/index.html#fragment-identifier";
+173     assertThrown!AdvanceException(url.advancePast("", Yes.inherit));
+174 }
+ +
+ + + \ No newline at end of file diff --git a/lu.string.advancePast.2.html b/lu.string.advancePast.2.html new file mode 100644 index 00000000..278bd63c --- /dev/null +++ b/lu.string.advancePast.2.html @@ -0,0 +1,38 @@ + + + + advancePast (lu.string.advancePast) + + + + + + + + + + +
+
+

advancePast

  1. auto advancePast(Haystack haystack, Needle needle, Flag!"inherit" inherit, string callingFile, size_t callingLine)
  2. auto advancePast(Haystack haystack, Needle needle, string callingFile, size_t callingLine)
    @safe deprecated pragma(inline, true) @safe
    advancePast
    (
    Flag!"inherit" inherit
    Haystack
    Needle
    )
    (
    auto ref return scope Haystack haystack
    ,
    const scope Needle needle
    ,
    const string callingFile = __FILE__
    ,
    const size_t callingLine = __LINE__
    )

Parameters

inherit

Optional flag of whether or not the whole string should be + returned and the haystack variable cleared on no needle match.

haystack Haystack

Array to walk and advance.

needle Needle

Token that delimits what should be returned and to where to advance. + May be another array or some individual character.

callingFile string

Optional file name to attach to an exception.

callingLine size_t

Optional line number to attach to an exception.

Return Value

Type: auto

The string haystack from the start up to the needle token. The original + variable is advanced to after the token.

+ +
+ + + \ No newline at end of file diff --git a/lu.string.advancePast.html b/lu.string.advancePast.html new file mode 100644 index 00000000..21f5be82 --- /dev/null +++ b/lu.string.advancePast.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.string.beginsWithOneOf.html b/lu.string.beginsWithOneOf.html new file mode 100644 index 00000000..c5a49304 --- /dev/null +++ b/lu.string.beginsWithOneOf.html @@ -0,0 +1,52 @@ + + + + beginsWithOneOf (lu.string.beginsWithOneOf) + + + + + + + + + + +
+
+

beginsWithOneOf

Checks whether or not the first letter of a string begins with any of the + passed string of characters, or single character.

Merely slices; does not decode the string and may thus give weird results on + weird inputs.

@safe deprecated
bool
beginsWithOneOf
(
Haystack
Needle
)
(
const scope Haystack haystack
,
const scope Needle needles
)

Parameters

haystack Haystack

String to examine the start of, or single character.

needles Needle

String of characters to look for in the start of haystack, + or a single character.

Return Value

Type: bool

true if the first character of haystack is also in needles, + false if not.

Examples

assert("#channel".beginsWithOneOf("#%+"));
+assert(!"#channel".beginsWithOneOf("~%+"));
+assert("".beginsWithOneOf(""));
+assert("abc".beginsWithOneOf(string.init));
+assert(!"".beginsWithOneOf("abc"));
+
+assert("abc".beginsWithOneOf('a'));
+assert(!"abc".beginsWithOneOf('b'));
+assert(!"abc".beginsWithOneOf(char.init));
+
+assert('#'.beginsWithOneOf("#%+"));
+assert(!'#'.beginsWithOneOf("~%+"));
+assert('a'.beginsWithOneOf(string.init));
+assert(!'d'.beginsWithOneOf("abc"));
+ +
+ + + \ No newline at end of file diff --git a/lu.string.decode64.html b/lu.string.decode64.html new file mode 100644 index 00000000..2dfac400 --- /dev/null +++ b/lu.string.decode64.html @@ -0,0 +1,45 @@ + + + + decode64 (lu.string.decode64) + + + + + + + + + + +
+
+

decode64

Base64-decodes a string.

Merely wraps Base64.decode and + std.string.representation into one function that will work with strings.

@safe pure
string
decode64
(
const string encoded
)

Parameters

encoded string

Encoded string to decode.

Return Value

Type: string

A decoded normal string.

Examples

{
+    immutable password = "base64:aGFyYmwgc25hcmJsIDEyMzQ1";
+    immutable decoded = decode64(password[7..$]);
+    assert((decoded == "harbl snarbl 12345"), decoded);
+}
+{
+    immutable password = "base64:";
+    immutable decoded = decode64(password[7..$]);
+    assert(!decoded.length, decoded);
+}

See Also

+ +
+ + + \ No newline at end of file diff --git a/lu.string.encode64.html b/lu.string.encode64.html new file mode 100644 index 00000000..dcbf0ebc --- /dev/null +++ b/lu.string.encode64.html @@ -0,0 +1,45 @@ + + + + encode64 (lu.string.encode64) + + + + + + + + + + +
+
+

encode64

Base64-encodes a string.

Merely wraps Base64.encode and + std.string.representation into one function that will work with strings.

@safe pure nothrow
string
encode64
(
const string line
)

Parameters

line string

String line to encode.

Return Value

Type: string

An encoded Base64 string.

Examples

{
+    immutable password = "harbl snarbl 12345";
+    immutable encoded = encode64(password);
+    assert((encoded == "aGFyYmwgc25hcmJsIDEyMzQ1"), encoded);
+}
+{
+    immutable string password;
+    immutable encoded = encode64(password);
+    assert(!encoded.length, encoded);
+}

See Also

+ +
+ + + \ No newline at end of file diff --git a/lu.string.escapeControlCharacters.html b/lu.string.escapeControlCharacters.html new file mode 100644 index 00000000..685dc006 --- /dev/null +++ b/lu.string.escapeControlCharacters.html @@ -0,0 +1,62 @@ + + + + escapeControlCharacters (lu.string.escapeControlCharacters) + + + + + + + + + + +
+
+

escapeControlCharacters

Replaces the control characters '\n', '\t', '\r' and '\0' with the escaped + "\\n", "\\t", "\\r" and "\\0". Does not allocate a new string if there + was nothing to escape.

@safe pure nothrow
escapeControlCharacters
(
return scope string line
)

Parameters

line string

String line to escape characters in.

Return Value

Type: auto

A new string with control characters escaped, or the original one unchanged.

Examples

{
+    immutable line = "abc\ndef";
+    immutable expected = "abc\\ndef";
+    immutable actual = escapeControlCharacters(line);
+    assert((actual == expected), actual);
+}
+{
+    immutable line = "\n\t\r\0";
+    immutable expected = "\\n\\t\\r\\0";
+    immutable actual = escapeControlCharacters(line);
+    assert((actual == expected), actual);
+}
+{
+    immutable line = "";
+    immutable expected = "";
+    immutable actual = escapeControlCharacters(line);
+    assert((actual == expected), actual);
+    assert(actual is line);  // No string allocated
+}
+{
+    immutable line = "nothing to escape";
+    immutable expected = "nothing to escape";
+    immutable actual = escapeControlCharacters(line);
+    assert((actual == expected), actual);
+    assert(actual is line);  // No string allocated
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.string.html b/lu.string.html new file mode 100644 index 00000000..0bd812ca --- /dev/null +++ b/lu.string.html @@ -0,0 +1,83 @@ + + + + lu.string (lu.string) + + + + + + + + + + +
+
+

lu.string

String manipulation functions complementing the standard library.

Public Imports

std.algorithm.searching
public static +import std.algorithm.searching;

Deprecated alias to Phobos' startsWith.

std.algorithm.searching
public static +import std.algorithm.searching;

Deprecated alias to Phobos' canFind.

Members

Aliases

NomException
alias NomException = AdvanceException

Compatibility alias to AdvanceException.

NomExceptionImpl
alias NomExceptionImpl = AdvanceExceptionImpl

Compatibility alias to AdvanceExceptionImpl.

nom
alias nom = advancePast

Compatibility alias to advancePast.

Classes

AdvanceException
class AdvanceException

Exception, to be thrown when a call to advancePast went wrong.

AdvanceExceptionImpl
class AdvanceExceptionImpl(Haystack, Needle)

Exception, to be thrown when a call to advancePast went wrong.

Enums

SplitResults
enum SplitResults

The result of a call to splitInto.

Functions

advancePast
auto advancePast(Haystack haystack, Needle needle, Flag!"inherit" inherit, string callingFile, size_t callingLine)

Given some string, finds the supplied needle token in it, returns the + string up to that point, and advances the passed string by ref to after the token.

advancePast
deprecated auto advancePast(Haystack haystack, Needle needle, string callingFile, size_t callingLine)
beginsWithOneOf
deprecated bool beginsWithOneOf(Haystack haystack, Needle needles)

Checks whether or not the first letter of a string begins with any of the + passed string of characters, or single character.

decode64
string decode64(string encoded)

Base64-decodes a string.

encode64
string encode64(string line)

Base64-encodes a string.

escapeControlCharacters
auto escapeControlCharacters(string line)

Replaces the control characters '\n', '\t', '\r' and '\0' with the escaped + "\\n", "\\t", "\\r" and "\\0". Does not allocate a new string if there + was nothing to escape.

indent
string indent(string wallOfText, uint numTabs, uint skip)

Indents lines in a string with the supplied number of tabs. Returns a newly + allocated string.

indentInto
void indentInto(string wallOfText, Sink sink, uint numTabs, uint skip)

Indents lines in a string into an output range sink with the supplied number of tabs.

plurality
T plurality(Num num, T singular, T plural)

Selects the correct singular or plural form of a word depending on the + numerical count of it.

removeControlCharacters
auto removeControlCharacters(string line)

Removes the control characters '\n', '\t', '\r' and '\0' from a string. + Does not allocate a new string if there was nothing to remove.

splitInto
auto splitInto(string slice, Strings strings)

Splits a string by a passed separator and assign the delimited words to the + passed strings by ref.

splitInto
auto splitInto(string slice, Strings strings, string[] overflow)

Splits a string by a passed separator and assign the delimited words to the + passed strings by ref. Overload that stores overflow strings into a passed array.

splitLineAtPosition
auto splitLineAtPosition(Line line, Separator separator, size_t maxLength)

Splits a string with on boundary as delimited by a supplied separator, into + one or more more lines not longer than the passed maximum length.

splitWithQuotes
auto splitWithQuotes(string line)

Splits a string into an array of strings by whitespace, but honours quotes.

stripSuffix
auto stripSuffix(string line, string suffix)

Strips the supplied string from the end of a string.

stripped
auto stripped(string line)

Returns a slice of the passed string with any preceding or trailing + whitespace or linebreaks sliced off both ends. Overload that implicitly + strips " \n\r\t".

stripped
auto stripped(Line line, Chaff chaff)

Returns a slice of the passed string with any preceding or trailing + passed characters sliced off. Implementation template capable of handling both + individual characters and strings of tokens to strip.

strippedLeft
auto strippedLeft(string line)

Returns a slice of the passed string with any preceding whitespace and/or + linebreaks sliced off. Overload that implicitly strips " \n\r\t".

strippedLeft
auto strippedLeft(Line line, Chaff chaff)

Returns a slice of the passed string with any preceding passed characters + sliced off. Implementation capable of handling both individual characters + and strings of tokens to strip.

strippedRight
auto strippedRight(string line)

Returns a slice of the passed string with any trailing whitespace and/or + linebreaks sliced off. Overload that implicitly strips " \n\r\t".

strippedRight
auto strippedRight(Line line, Chaff chaff)

Returns a slice of the passed string with any trailing passed characters. + Implementation template capable of handling both individual characters and + string of tokens to strip.

tabs
auto tabs(int num)

Returns a range of *spaces* equal to that of num tabs (\t).

unenclosed
auto unenclosed(string line)

Removes paired preceding and trailing tokens around a string line. + Assumes ASCII.

unquoted
auto unquoted(string line)

Removes paired preceding and trailing double quotes, unquoting a word. + Assumes ASCII.

unsinglequoted
auto unsinglequoted(string line)

Removes paired preceding and trailing single quotes around a line. + Assumes ASCII.

Examples

{
+    string line = "Lorem ipsum :sit amet";
+    immutable lorem = line.advancePast(" :");
+    assert(lorem == "Lorem ipsum", lorem);
+    assert(line == "sit amet", line);
+}
+{
+    string line = "Lorem ipsum :sit amet";
+    immutable lorem = line.advancePast(':');
+    assert(lorem == "Lorem ipsum ", lorem);
+    assert(line == "sit amet", line);
+}
+{
+    string line = "Lorem ipsum sit amet";  // mutable, will be modified by ref
+    string[] words;
+
+    while (line.length > 0)
+    {
+        immutable word = line.advancePast(" ", Yes.inherit);
+        words ~= word;
+    }
+
+    assert(words == [ "Lorem", "ipsum", "sit", "amet" ]);
+}

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.string.indent.html b/lu.string.indent.html new file mode 100644 index 00000000..351bd978 --- /dev/null +++ b/lu.string.indent.html @@ -0,0 +1,73 @@ + + + + indent (lu.string.indent) + + + + + + + + + + +
+
+

indent

Indents lines in a string with the supplied number of tabs. Returns a newly + allocated string.

@safe pure
string
indent
(
uint spaces = 4
)
(
const string wallOfText
,
const uint numTabs = 1
,
const uint skip = 0
)

Parameters

spaces

How many spaces make up a tab.

wallOfText string

String to indent the lines of.

numTabs uint

Amount of tabs to indent with, default 1.

skip uint

How many lines to skip indenting.

Return Value

Type: string

A string with all the lines of the original string indented.

Examples

    immutable string_ =
+"Lorem ipsum
+sit amet
+I don't remember
+any more offhand
+so shrug";
+
+    immutable indentedOne = string_.indent;
+    assert((indentedOne ==
+"    Lorem ipsum
+    sit amet
+    I don't remember
+    any more offhand
+    so shrug"), '\n' ~ indentedOne);
+
+    immutable indentedTwo = string_.indent(2);
+    assert((indentedTwo ==
+"        Lorem ipsum
+        sit amet
+        I don't remember
+        any more offhand
+        so shrug"), '\n' ~ indentedTwo);
+
+    immutable indentedZero = string_.indent(0);
+    assert((indentedZero ==
+"Lorem ipsum
+sit amet
+I don't remember
+any more offhand
+so shrug"), '\n' ~ indentedZero);
+
+    immutable indentedSkipTwo = string_.indent(1, 2);
+    assert((indentedSkipTwo ==
+"Lorem ipsum
+sit amet
+    I don't remember
+    any more offhand
+    so shrug"), '\n' ~ indentedSkipTwo);
+ +
+ + + \ No newline at end of file diff --git a/lu.string.indentInto.html b/lu.string.indentInto.html new file mode 100644 index 00000000..1d9ded37 --- /dev/null +++ b/lu.string.indentInto.html @@ -0,0 +1,70 @@ + + + + indentInto (lu.string.indentInto) + + + + + + + + + + +
+
+

indentInto

Indents lines in a string into an output range sink with the supplied number of tabs.

@safe
void
indentInto
(
uint spaces = 4
Sink
)
(
const string wallOfText
,
auto ref Sink sink
,
const uint numTabs = 1
,
const uint skip = 0
)

Parameters

spaces

How many spaces in an indenting tab.

wallOfText string

String to indent the individual lines of.

sink Sink

Output range to fill with the indented lines.

numTabs uint

Optional amount of tabs to indent with, default 1.

skip uint

How many lines to skip indenting.

Examples

    import std.array : Appender;
+
+    Appender!(char[]) sink;
+
+    immutable string_ =
+"Lorem ipsum
+sit amet
+I don't remember
+any more offhand
+so shrug";
+
+    string_.indentInto(sink);
+    assert((sink.data ==
+"    Lorem ipsum
+    sit amet
+    I don't remember
+    any more offhand
+    so shrug"), '\n' ~ sink.data);
+
+    sink.clear();
+    string_.indentInto!3(sink, 2);
+    assert((sink.data ==
+"      Lorem ipsum
+      sit amet
+      I don't remember
+      any more offhand
+      so shrug"), '\n' ~ sink.data);
+
+    sink.clear();
+    string_.indentInto(sink, 0);
+    assert((sink.data ==
+"Lorem ipsum
+sit amet
+I don't remember
+any more offhand
+so shrug"), '\n' ~ sink.data);
+ +
+ + + \ No newline at end of file diff --git a/lu.string.nom.html b/lu.string.nom.html new file mode 100644 index 00000000..e198c646 --- /dev/null +++ b/lu.string.nom.html @@ -0,0 +1,35 @@ + + + + nom (lu.string.nom) + + + + + + + + + + +
+
+

nom

Compatibility alias to advancePast.

@safe
alias nom = advancePast
+ +
+ + + \ No newline at end of file diff --git a/lu.string.plurality.html b/lu.string.plurality.html new file mode 100644 index 00000000..6c91dd6e --- /dev/null +++ b/lu.string.plurality.html @@ -0,0 +1,47 @@ + + + + plurality (lu.string.plurality) + + + + + + + + + + +
+
+

plurality

Selects the correct singular or plural form of a word depending on the + numerical count of it.

Technically works with any type provided the number is some comparable integral.

@safe pragma(inline, true) pure nothrow @nogc
T
plurality
(
Num
T
)
(
const Num num
,
const return scope T singular
,
const return scope T plural
)

Parameters

num Num

Numerical count.

singular T

The singular form.

plural T

The plural form.

Return Value

Type: T

The singular if num is 1 or -1, otherwise the plural.

Examples

string one = 1.plurality("one", "two");
+string two = 2.plurality("one", "two");
+string many = (-2).plurality("one", "many");
+string many0 = 0.plurality("one", "many");
+
+assert((one == "one"), one);
+assert((two == "two"), two);
+assert((many == "many"), many);
+assert((many0 == "many"), many0);
static assert(10.plurality("one","many") == "many");
+static assert(1.plurality("one", "many") == "one");
+static assert((-1).plurality("one", "many") == "one");
+static assert(0.plurality("one", "many") == "many");
+ +
+ + + \ No newline at end of file diff --git a/lu.string.removeControlCharacters.html b/lu.string.removeControlCharacters.html new file mode 100644 index 00000000..7de23d0c --- /dev/null +++ b/lu.string.removeControlCharacters.html @@ -0,0 +1,60 @@ + + + + removeControlCharacters (lu.string.removeControlCharacters) + + + + + + + + + + +
+
+

removeControlCharacters

Removes the control characters '\n', '\t', '\r' and '\0' from a string. + Does not allocate a new string if there was nothing to remove.

@safe pure nothrow
removeControlCharacters
(
return scope string line
)

Parameters

line string

String line to "remove" characters from.

Return Value

Type: auto

A new string with control characters removed, or the original one unchanged.

Examples

{
+    immutable line = "abc\ndef";
+    immutable expected = "abcdef";
+    immutable actual = removeControlCharacters(line);
+    assert((actual == expected), actual);
+}
+{
+    immutable line = "\n\t\r\0";
+    immutable expected = "";
+    immutable actual = removeControlCharacters(line);
+    assert((actual == expected), actual);
+}
+{
+    immutable line = "";
+    immutable expected = "";
+    immutable actual = removeControlCharacters(line);
+    assert((actual == expected), actual);
+}
+{
+    immutable line = "nothing to escape";
+    immutable expected = "nothing to escape";
+    immutable actual = removeControlCharacters(line);
+    assert((actual == expected), actual);
+    assert(line is actual);  // No new string was allocated
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.string.splitInto.1.html b/lu.string.splitInto.1.html new file mode 100644 index 00000000..23a18370 --- /dev/null +++ b/lu.string.splitInto.1.html @@ -0,0 +1,107 @@ + + + + splitInto (lu.string.splitInto) + + + + + + + + + + +
+
+

splitInto

Splits a string by a passed separator and assign the delimited words to the + passed strings by ref.

Note: Does *not* take quoted substrings into consideration.

  1. auto splitInto(string slice, Strings strings)
    @safe
    splitInto
    (
    string separator = " "
    Strings...
    )
    (
    auto ref string slice
    ,
    scope ref Strings strings
    )
    if (
    Strings.length &&
    is(Strings[0] == string)
    &&
    allSameType!Strings
    )
  2. auto splitInto(string slice, Strings strings, string[] overflow)

Parameters

separator

What token to separate the input string into words with.

slice string

Input string of words separated by separator.

strings Strings

Variadic list of strings to assign the split words in slice.

Return Value

Type: auto

A SplitResults with the results of the split attempt.

Examples

1 import lu.conv : Enum;
+2 
+3 {
+4     string line = "abc def ghi";
+5     string abc, def, ghi;
+6     immutable results = line.splitInto(abc, def, ghi);
+7 
+8     assert((abc == "abc"), abc);
+9     assert((def == "def"), def);
+10     assert((ghi == "ghi"), ghi);
+11     assert(!line.length, line);
+12     assert((results == SplitResults.match), Enum!SplitResults.toString(results));
+13 }
+14 {
+15     string line = "abc            def                                 ghi";
+16     string abc, def, ghi;
+17     immutable results = line.splitInto(abc, def, ghi);
+18 
+19     assert((abc == "abc"), abc);
+20     assert((def == "def"), def);
+21     assert((ghi == "ghi"), ghi);
+22     assert(!line.length, line);
+23     assert((results == SplitResults.match), Enum!SplitResults.toString(results));
+24 }
+25 {
+26     string line = "abc_def ghi";
+27     string abc, def, ghi;
+28     immutable results = line.splitInto!"_"(abc, def, ghi);
+29 
+30     assert((abc == "abc"), abc);
+31     assert((def == "def ghi"), def);
+32     assert(!ghi.length, ghi);
+33     assert(!line.length, line);
+34     assert((results == SplitResults.underrun), Enum!SplitResults.toString(results));
+35 }
+36 {
+37     string line = "abc def ghi";
+38     string abc, def;
+39     immutable results = line.splitInto(abc, def);
+40 
+41     assert((abc == "abc"), abc);
+42     assert((def == "def"), def);
+43     assert((line == "ghi"), line);
+44     assert((results == SplitResults.overrun), Enum!SplitResults.toString(results));
+45 }
+46 {
+47     string line = "abc///def";
+48     string abc, def;
+49     immutable results = line.splitInto!"//"(abc, def);
+50 
+51     assert((abc == "abc"), abc);
+52     assert((def == "/def"), def);
+53     assert(!line.length, line);
+54     assert((results == SplitResults.match), Enum!SplitResults.toString(results));
+55 }
+56 {
+57     string line = "abc 123 def I am a fish";
+58     string abc, a123, def;
+59     immutable results = line.splitInto(abc, a123, def);
+60 
+61     assert((abc == "abc"), abc);
+62     assert((a123 == "123"), a123);
+63     assert((def == "def"), def);
+64     assert((line == "I am a fish"), line);
+65     assert((results == SplitResults.overrun), Enum!SplitResults.toString(results));
+66 }
+67 {
+68     string line;
+69     string abc, def;
+70     immutable results = line.splitInto(abc, def);
+71     assert((results == SplitResults.underrun), Enum!SplitResults.toString(results));
+72 }
+ +
+ + + \ No newline at end of file diff --git a/lu.string.splitInto.2.html b/lu.string.splitInto.2.html new file mode 100644 index 00000000..47ea2e31 --- /dev/null +++ b/lu.string.splitInto.2.html @@ -0,0 +1,181 @@ + + + + splitInto (lu.string.splitInto) + + + + + + + + + + +
+
+

splitInto

Splits a string by a passed separator and assign the delimited words to the + passed strings by ref. Overload that stores overflow strings into a passed array.

Note: *Does* take quoted substrings into consideration.

  1. auto splitInto(string slice, Strings strings)
  2. auto splitInto(string slice, Strings strings, string[] overflow)
    @safe
    splitInto
    (
    string separator = " "
    Strings...
    )
    (
    const string slice
    ,
    ref Strings strings
    ,
    out string[] overflow
    )
    if (
    !Strings.length ||
    (
    is(Strings[0] == string) &&
    allSameType!Strings
    )
    )

Parameters

separator

What token to separate the input string into words with.

slice string

Input string of words separated by separator.

strings Strings

Variadic list of strings to assign the split words in slice.

overflow string[]

Overflow array.

Return Value

Type: auto

A SplitResults with the results of the split attempt.

Examples

1 import lu.conv : Enum;
+2 import std.conv : text;
+3 
+4 {
+5     string line = "abc def ghi";
+6     string abc, def, ghi;
+7     string[] overflow;
+8     immutable results = line.splitInto(abc, def, ghi, overflow);
+9 
+10     assert((abc == "abc"), abc);
+11     assert((def == "def"), def);
+12     assert((ghi == "ghi"), ghi);
+13     assert(!overflow.length, overflow.text);
+14     assert((results == SplitResults.match), Enum!SplitResults.toString(results));
+15 }
+16 {
+17     string line = "abc##def##ghi";
+18     string abc, def, ghi;
+19     string[] overflow;
+20     immutable results = line.splitInto!"##"(abc, def, ghi, overflow);
+21 
+22     assert((abc == "abc"), abc);
+23     assert((def == "def"), def);
+24     assert((ghi == "ghi"), ghi);
+25     assert(!overflow.length, overflow.text);
+26     assert((results == SplitResults.match), Enum!SplitResults.toString(results));
+27 }
+28 {
+29     string line = "abc  def  ghi";
+30     string abc, def, ghi;
+31     string[] overflow;
+32     immutable results = line.splitInto(abc, def, ghi, overflow);
+33 
+34     assert((abc == "abc"), abc);
+35     assert((def == "def"), def);
+36     assert((ghi == "ghi"), ghi);
+37     assert(!overflow.length, overflow.text);
+38     assert((results == SplitResults.match), Enum!SplitResults.toString(results));
+39 }
+40 {
+41     string line = "abc_def ghi";
+42     string abc, def, ghi;
+43     string[] overflow;
+44     immutable results = line.splitInto!"_"(abc, def, ghi, overflow);
+45 
+46     assert((abc == "abc"), abc);
+47     assert((def == "def ghi"), def);
+48     assert(!ghi.length, ghi);
+49     assert(!overflow.length, overflow.text);
+50     assert((results == SplitResults.underrun), Enum!SplitResults.toString(results));
+51 }
+52 {
+53     string line = "abc def ghi";
+54     string abc, def;
+55     string[] overflow;
+56     immutable results = line.splitInto(abc, def, overflow);
+57 
+58     assert((abc == "abc"), abc);
+59     assert((def == "def"), def);
+60     assert((overflow == [ "ghi" ]), overflow.text);
+61     assert((results == SplitResults.overrun), Enum!SplitResults.toString(results));
+62 }
+63 {
+64     string line = "abc///def";
+65     string abc, def;
+66     string[] overflow;
+67     immutable results = line.splitInto!"//"(abc, def, overflow);
+68 
+69     assert((abc == "abc"), abc);
+70     assert((def == "/def"), def);
+71     assert(!overflow.length, overflow.text);
+72     assert((results == SplitResults.match), Enum!SplitResults.toString(results));
+73 }
+74 {
+75     string line = "abc 123 def I am a fish";
+76     string abc, a123, def;
+77     string[] overflow;
+78     immutable results = line.splitInto(abc, a123, def, overflow);
+79 
+80     assert((abc == "abc"), abc);
+81     assert((a123 == "123"), a123);
+82     assert((def == "def"), def);
+83     assert((overflow == [ "I", "am", "a", "fish" ]), overflow.text);
+84     assert((results == SplitResults.overrun), Enum!SplitResults.toString(results));
+85 }
+86 {
+87     string line = `abc 123 def "I am a fish"`;
+88     string abc, a123, def;
+89     string[] overflow;
+90     immutable results = line.splitInto(abc, a123, def, overflow);
+91 
+92     assert((abc == "abc"), abc);
+93     assert((a123 == "123"), a123);
+94     assert((def == "def"), def);
+95     assert((overflow == [ "I am a fish" ]), overflow.text);
+96     assert((results == SplitResults.overrun), Enum!SplitResults.toString(results));
+97 }
+98 {
+99     string line;
+100     string abc, def;
+101     string[] overflow;
+102     immutable results = line.splitInto(abc, def, overflow);
+103     assert((results == SplitResults.underrun), Enum!SplitResults.toString(results));
+104 }
+105 {
+106     string line = "abchonkelonkhonkelodef";
+107     string abc, def;
+108     string[] overflow;
+109     immutable results = line.splitInto!"honkelonk"(abc, def, overflow);
+110 
+111     assert((abc == "abc"), abc);
+112     assert((def == "honkelodef"), def);
+113     assert(!overflow.length, overflow.text);
+114     assert((results == SplitResults.match), Enum!SplitResults.toString(results));
+115 }
+116 {
+117     string line = "honkelonkhonkelodef";
+118     string abc, def;
+119     string[] overflow;
+120     immutable results = line.splitInto!"honkelonk"(abc, def, overflow);
+121 
+122     assert((abc == "honkelodef"), abc);
+123     assert((def == string.init), def);
+124     assert(!overflow.length, overflow.text);
+125     assert((results == SplitResults.underrun), Enum!SplitResults.toString(results));
+126 }
+127 {
+128     string line = "###########hirrsteff#snabel";
+129     string abc, def;
+130     string[] overflow;
+131     immutable results = line.splitInto!"#"(abc, def, overflow);
+132 
+133     assert((abc == "hirrsteff"), abc);
+134     assert((def == "snabel"), def);
+135     assert(!overflow.length, overflow.text);
+136     assert((results == SplitResults.match), Enum!SplitResults.toString(results));
+137 }
+138 {
+139     string line = "abc def ghi";
+140     string[] overflow;
+141     immutable results = line.splitInto(overflow);
+142     immutable expectedOverflow = [ "abc", "def", "ghi" ];
+143 
+144     assert((overflow == expectedOverflow), overflow.text);
+145     assert((results == SplitResults.overrun), Enum!SplitResults.toString(results));
+146 }
+ +
+ + + \ No newline at end of file diff --git a/lu.string.splitInto.html b/lu.string.splitInto.html new file mode 100644 index 00000000..5e27c2e9 --- /dev/null +++ b/lu.string.splitInto.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.string.splitLineAtPosition.html b/lu.string.splitLineAtPosition.html new file mode 100644 index 00000000..c17abf90 --- /dev/null +++ b/lu.string.splitLineAtPosition.html @@ -0,0 +1,87 @@ + + + + splitLineAtPosition (lu.string.splitLineAtPosition) + + + + + + + + + + +
+
+

splitLineAtPosition

Splits a string with on boundary as delimited by a supplied separator, into + one or more more lines not longer than the passed maximum length.

If a line cannot be split due to the line being too short or the separator + not occurring in the text, it is added to the returned array as-is and no + more splitting is done.

@safe pure
splitLineAtPosition
(
Line
Separator
)
(
const Line line
,
const Separator separator
,
const size_t maxLength
)

Parameters

line Line

String line to split.

separator Separator

Separator character with which to split the line.

maxLength size_t

Maximum length of the separated lines.

Return Value

Type: auto

A T[] array with lines split out of the passed line.

Examples

string line = "I am a fish in a sort of long sentence~";
+enum maxLineLength = 20;
+auto splitLines = line.splitLineAtPosition(' ', maxLineLength);
+
+assert(splitLines[0] == "I am a fish in a");
+assert(splitLines[1] == "sort of a long");
+assert(splitLines[2] == "sentence~");
import std.conv : text;
+
+{
+    immutable prelude = "PRIVMSG #garderoben :";
+    immutable maxLength = 250 - prelude.length;
+
+    immutable rawLine = "Lorem ipsum dolor sit amet, ea has velit noluisse, " ~
+        "eos eius appetere constituto no, ad quas natum eos. Perpetua " ~
+        "electram mnesarchum usu ne, mei vero dolorem no. Ea quando scripta " ~
+        "quo, minim legendos ut vel. Ut usu graece equidem posidonium. Ius " ~
+        "denique ponderum verterem no, quo te mentitum officiis referrentur. " ~
+        "Sed an dolor iriure vocibus. " ~
+        "Lorem ipsum dolor sit amet, ea has velit noluisse, " ~
+        "eos eius appetere constituto no, ad quas natum eos. Perpetua " ~
+        "electram mnesarchum usu ne, mei vero dolorem no. Ea quando scripta " ~
+        "quo, minim legendos ut vel. Ut usu graece equidem posidonium. Ius " ~
+        "denique ponderum verterem no, quo te mentitum officiis referrentur. " ~
+        "Sed an dolor iriure vocibus. ssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "ssssssssssssssssssssssssssssssssssssssssssssssssssssssss";
+    const splitLines = rawLine.splitLineAtPosition(' ', maxLength);
+    assert((splitLines.length == 4), splitLines.length.text);
+}
+{
+    immutable prelude = "PRIVMSG #garderoben :";
+    immutable maxLength = 250 - prelude.length;
+
+    immutable rawLine = "ssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" ~
+        "ssssssssssssssssssssssssssssssssssssssssssssssssssssssss";
+    const splitLines = rawLine.splitLineAtPosition(' ', maxLength);
+    assert((splitLines.length == 1), splitLines.length.text);
+    assert(splitLines[0] == rawLine);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.string.splitWithQuotes.html b/lu.string.splitWithQuotes.html new file mode 100644 index 00000000..53126607 --- /dev/null +++ b/lu.string.splitWithQuotes.html @@ -0,0 +1,123 @@ + + + + splitWithQuotes (lu.string.splitWithQuotes) + + + + + + + + + + +
+
+

splitWithQuotes

Splits a string into an array of strings by whitespace, but honours quotes.

Intended to be used with ASCII strings; may or may not work with more + elaborate UTF-8 strings.

@safe
splitWithQuotes
(
string separator = " "
)
(
const string line
)
if (
separator.length
)

Parameters

separator

Separator string. May be more than one character.

line string

Input string.

Return Value

Type: auto

A string[] composed of the input string split up into substrings, + delimited by whitespace. Quoted sections are treated as one substring.

Examples

string s = `title "this is my title" author "john doe"`;
+immutable splitUp = splitWithQuotes(s);
+assert(splitUp == [ "title", "this is my title", "author", "john doe" ]);
1 import std.conv : text;
+2 
+3 {
+4     enum input = `title "this is my title" author "john doe"`;
+5     immutable splitUp = splitWithQuotes(input);
+6     immutable expected =
+7     [
+8         "title",
+9         "this is my title",
+10         "author",
+11         "john doe"
+12     ];
+13     assert(splitUp == expected, splitUp.text);
+14 }
+15 {
+16     enum input = `string without quotes`;
+17     immutable splitUp = splitWithQuotes(input);
+18     immutable expected =
+19     [
+20         "string",
+21         "without",
+22         "quotes",
+23     ];
+24     assert(splitUp == expected, splitUp.text);
+25 }
+26 {
+27     enum input = string.init;
+28     immutable splitUp = splitWithQuotes(input);
+29     immutable expected = (string[]).init;
+30     assert(splitUp == expected, splitUp.text);
+31 }
+32 {
+33     enum input = `title "this is \"my\" title" author "john\\" doe`;
+34     immutable splitUp = splitWithQuotes(input);
+35     immutable expected =
+36     [
+37         "title",
+38         `this is "my" title`,
+39         "author",
+40         `john\`,
+41         "doe"
+42     ];
+43     assert(splitUp == expected, splitUp.text);
+44 }
+45 {
+46     enum input = `title "this is \"my\" title" author "john\\\" doe`;
+47     immutable splitUp = splitWithQuotes(input);
+48     immutable expected =
+49     [
+50         "title",
+51         `this is "my" title`,
+52         "author",
+53         `john\" doe`
+54     ];
+55     assert(splitUp == expected, splitUp.text);
+56 }
+57 {
+58     enum input = `this has "unbalanced quotes`;
+59     immutable splitUp = splitWithQuotes(input);
+60     immutable expected =
+61     [
+62         "this",
+63         "has",
+64         "unbalanced quotes"
+65     ];
+66     assert(splitUp == expected, splitUp.text);
+67 }
+68 {
+69     enum input = `""`;
+70     immutable splitUp = splitWithQuotes(input);
+71     immutable expected = (string[]).init;
+72     assert(splitUp == expected, splitUp.text);
+73 }
+74 {
+75     enum input = `"`;
+76     immutable splitUp = splitWithQuotes(input);
+77     immutable expected = (string[]).init;
+78     assert(splitUp == expected, splitUp.text);
+79 }
+80 {
+81     enum input = `"""""""""""`;
+82     immutable splitUp = splitWithQuotes(input);
+83     immutable expected = (string[]).init;
+84     assert(splitUp == expected, splitUp.text);
+85 }
+ +
+ + + \ No newline at end of file diff --git a/lu.string.stripSuffix.html b/lu.string.stripSuffix.html new file mode 100644 index 00000000..43f97f3c --- /dev/null +++ b/lu.string.stripSuffix.html @@ -0,0 +1,41 @@ + + + + stripSuffix (lu.string.stripSuffix) + + + + + + + + + + +
+
+

stripSuffix

Strips the supplied string from the end of a string.

@safe pure nothrow @nogc
stripSuffix
(
return scope string line
,
const scope string suffix
)

Parameters

line string

Original line to strip the suffix from.

suffix string

Suffix string to strip.

Return Value

Type: auto

line with suffix sliced off the end.

Examples

string suffixed = "Kameloso";
+string stripped = suffixed.stripSuffix("oso");
+assert((stripped == "Kamel"), stripped);
immutable line = "harblsnarbl";
+assert(line.stripSuffix("snarbl") == "harbl");
+assert(line.stripSuffix("") == "harblsnarbl");
+assert(line.stripSuffix("INVALID") == "harblsnarbl");
+assert(!line.stripSuffix("harblsnarbl").length);
+ +
+ + + \ No newline at end of file diff --git a/lu.string.stripped.1.html b/lu.string.stripped.1.html new file mode 100644 index 00000000..f2cff2d1 --- /dev/null +++ b/lu.string.stripped.1.html @@ -0,0 +1,69 @@ + + + + stripped (lu.string.stripped) + + + + + + + + + + +
+
+

stripped

Returns a slice of the passed string with any preceding or trailing + whitespace or linebreaks sliced off both ends. Overload that implicitly + strips " \n\r\t".

It merely calls both strippedLeft and strippedRight. As such it + duplicates std.string.strip, which we can no longer trust not to assert + on unexpected input.

  1. auto stripped(string line)
    @safe pure nothrow @nogc
    stripped
    (
    return scope string line
    )
  2. auto stripped(Line line, Chaff chaff)

Parameters

line string

Line to strip both the right and left side of.

Return Value

Type: auto

The passed line, stripped of surrounding whitespace.

Examples

static if (!is(typeof("blah".stripped) == string))
+{
+    enum message = "`lu.string.stripped` should return a mutable string";
+    static assert(0, message);
+}
+
+{
+    immutable line = "   abc   ";
+    immutable stripped_ = line.stripped;
+    assert((stripped_ == "abc"), stripped_);
+}
+{
+    immutable line = "   ";
+    immutable stripped_ = line.stripped;
+    assert((stripped_ == ""), stripped_);
+}
+{
+    immutable line = "";
+    immutable stripped_ = line.stripped;
+    assert((stripped_ == ""), stripped_);
+}
+{
+    immutable line = "abc";
+    immutable stripped_ = line.stripped;
+    assert((stripped_ == "abc"), stripped_);
+}
+{
+    immutable line = " \r\n  abc\r\n\r\n";
+    immutable stripped_ = line.stripped;
+    assert((stripped_ == "abc"), stripped_);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.string.stripped.2.html b/lu.string.stripped.2.html new file mode 100644 index 00000000..392f2de6 --- /dev/null +++ b/lu.string.stripped.2.html @@ -0,0 +1,88 @@ + + + + stripped (lu.string.stripped) + + + + + + + + + + +
+
+

stripped

Returns a slice of the passed string with any preceding or trailing + passed characters sliced off. Implementation template capable of handling both + individual characters and strings of tokens to strip.

It merely calls both strippedLeft and strippedRight. As such it + duplicates std.string.strip, which we can no longer trust not to assert + on unexpected input.

  1. auto stripped(string line)
  2. auto stripped(Line line, Chaff chaff)
    @safe pure nothrow @nogc
    stripped
    (
    Line
    Chaff
    )
    (
    return scope Line line
    ,
    const scope Chaff chaff
    )

Parameters

line Line

Line to strip both the right and left side of.

chaff Chaff

Character or string of characters to strip away.

Return Value

Type: auto

The passed line, stripped of surrounding passed characters.

Examples

{
+    immutable line = "   abc   ";
+    immutable stripped_ = line.stripped(' ');
+    assert((stripped_ == "abc"), stripped_);
+}
+{
+    immutable line = "!!!";
+    immutable stripped_ = line.stripped('!');
+    assert((stripped_ == ""), stripped_);
+}
+{
+    immutable line = "";
+    immutable stripped_ = line.stripped('_');
+    assert((stripped_ == ""), stripped_);
+}
+{
+    immutable line = "abc";
+    immutable stripped_ = line.stripped('\t');
+    assert((stripped_ == "abc"), stripped_);
+}
+{
+    immutable line = " \r\n  abc\r\n\r\n  ";
+    immutable stripped_ = line.stripped(' ');
+    assert((stripped_ == "\r\n  abc\r\n\r\n"), stripped_);
+}
+{
+    immutable line = "   abc   ";
+    immutable stripped_ = line.stripped(" \t");
+    assert((stripped_ == "abc"), stripped_);
+}
+{
+    immutable line = "!,!!";
+    immutable stripped_ = line.stripped("!,");
+    assert((stripped_ == ""), stripped_);
+}
+{
+    immutable line = "";
+    immutable stripped_ = line.stripped("_");
+    assert((stripped_ == ""), stripped_);
+}
+{
+    immutable line = "abc";
+    immutable stripped_ = line.stripped("\t\r\n");
+    assert((stripped_ == "abc"), stripped_);
+}
+{
+    immutable line = " \r\n  abc\r\n\r\n  ";
+    immutable stripped_ = line.stripped(" _");
+    assert((stripped_ == "\r\n  abc\r\n\r\n"), stripped_);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.string.stripped.html b/lu.string.stripped.html new file mode 100644 index 00000000..4c0fff4a --- /dev/null +++ b/lu.string.stripped.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.string.strippedLeft.1.html b/lu.string.strippedLeft.1.html new file mode 100644 index 00000000..6a362579 --- /dev/null +++ b/lu.string.strippedLeft.1.html @@ -0,0 +1,67 @@ + + + + strippedLeft (lu.string.strippedLeft) + + + + + + + + + + +
+
+

strippedLeft

Returns a slice of the passed string with any preceding whitespace and/or + linebreaks sliced off. Overload that implicitly strips " \n\r\t".

Duplicates std.string.stripLeft, which we can no longer trust not to + assert on unexpected input.

  1. auto strippedLeft(string line)
    @safe pure nothrow @nogc
    strippedLeft
    (
    return scope string line
    )
  2. auto strippedLeft(Line line, Chaff chaff)

Parameters

line string

Line to strip the left side of.

Return Value

Type: auto

The passed line without any preceding whitespace or linebreaks.

Examples

static if (!is(typeof("blah".strippedLeft) == string))
+{
+    enum message = "`lu.string.strippedLeft` should return a mutable string";
+    static assert(0, message);
+}
+
+{
+    immutable preceded = "   abc";
+    immutable stripped = preceded.strippedLeft;
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable preceded = "   ";
+    immutable stripped = preceded.strippedLeft;
+    assert((stripped == ""), stripped);
+}
+{
+    immutable empty = "";
+    immutable stripped = empty.strippedLeft;
+    assert((stripped == ""), stripped);
+}
+{
+    immutable noPreceded = "abc";
+    immutable stripped = noPreceded.strippedLeft;
+    assert((stripped == noPreceded), stripped);
+}
+{
+    immutable linebreak  = "\r\n\r\n  abc";
+    immutable stripped = linebreak.strippedLeft;
+    assert((stripped == "abc"), stripped);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.string.strippedLeft.2.html b/lu.string.strippedLeft.2.html new file mode 100644 index 00000000..9b668c72 --- /dev/null +++ b/lu.string.strippedLeft.2.html @@ -0,0 +1,77 @@ + + + + strippedLeft (lu.string.strippedLeft) + + + + + + + + + + +
+
+

strippedLeft

Returns a slice of the passed string with any preceding passed characters + sliced off. Implementation capable of handling both individual characters + and strings of tokens to strip.

Duplicates std.string.stripLeft, which we can no longer trust not to + assert on unexpected input.

  1. auto strippedLeft(string line)
  2. auto strippedLeft(Line line, Chaff chaff)
    @safe pure nothrow @nogc
    strippedLeft
    (
    Line
    Chaff
    )
    (
    return scope Line line
    ,
    const scope Chaff chaff
    )

Parameters

line Line

Line to strip the left side of.

chaff Chaff

Character or string of characters to strip away.

Return Value

Type: auto

The passed line without any preceding passed characters.

Examples

{
+    immutable trailing = ",abc";
+    immutable stripped = trailing.strippedLeft(',');
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "!!!abc";
+    immutable stripped = trailing.strippedLeft('!');
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "abc";
+    immutable stripped = trailing.strippedLeft(' ');
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "";
+    immutable stripped = trailing.strippedLeft(' ');
+    assert(!stripped.length, stripped);
+}
+{
+    immutable trailing = ",abc";
+    immutable stripped = trailing.strippedLeft(",");
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "!!!abc";
+    immutable stripped = trailing.strippedLeft(",1!");
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "abc";
+    immutable stripped = trailing.strippedLeft(" ");
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "";
+    immutable stripped = trailing.strippedLeft(" ");
+    assert(!stripped.length, stripped);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.string.strippedLeft.html b/lu.string.strippedLeft.html new file mode 100644 index 00000000..a3fca37d --- /dev/null +++ b/lu.string.strippedLeft.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.string.strippedRight.1.html b/lu.string.strippedRight.1.html new file mode 100644 index 00000000..9492f8fc --- /dev/null +++ b/lu.string.strippedRight.1.html @@ -0,0 +1,67 @@ + + + + strippedRight (lu.string.strippedRight) + + + + + + + + + + +
+
+

strippedRight

Returns a slice of the passed string with any trailing whitespace and/or + linebreaks sliced off. Overload that implicitly strips " \n\r\t".

Duplicates std.string.stripRight, which we can no longer trust not to + assert on unexpected input.

  1. auto strippedRight(string line)
    @safe pure nothrow @nogc
    strippedRight
    (
    return scope string line
    )
  2. auto strippedRight(Line line, Chaff chaff)

Parameters

line string

Line to strip the right side of.

Return Value

Type: auto

The passed line without any trailing whitespace or linebreaks.

Examples

static if (!is(typeof("blah".strippedRight) == string))
+{
+    enum message = "`lu.string.strippedRight` should return a mutable string";
+    static assert(0, message);
+}
+
+{
+    immutable trailing = "abc  ";
+    immutable stripped = trailing.strippedRight;
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "  ";
+    immutable stripped = trailing.strippedRight;
+    assert((stripped == ""), stripped);
+}
+{
+    immutable empty = "";
+    immutable stripped = empty.strippedRight;
+    assert((stripped == ""), stripped);
+}
+{
+    immutable noTrailing = "abc";
+    immutable stripped = noTrailing.strippedRight;
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable linebreak = "abc\r\n  \r\n";
+    immutable stripped = linebreak.strippedRight;
+    assert((stripped == "abc"), stripped);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.string.strippedRight.2.html b/lu.string.strippedRight.2.html new file mode 100644 index 00000000..469c2984 --- /dev/null +++ b/lu.string.strippedRight.2.html @@ -0,0 +1,77 @@ + + + + strippedRight (lu.string.strippedRight) + + + + + + + + + + +
+
+

strippedRight

Returns a slice of the passed string with any trailing passed characters. + Implementation template capable of handling both individual characters and + string of tokens to strip.

Duplicates std.string.stripRight, which we can no longer trust not to + assert on unexpected input.

  1. auto strippedRight(string line)
  2. auto strippedRight(Line line, Chaff chaff)
    @safe pure nothrow @nogc
    strippedRight
    (
    Line
    Chaff
    )
    (
    return scope Line line
    ,
    const scope Chaff chaff
    )

Parameters

line Line

Line to strip the right side of.

chaff Chaff

Character or string of characters to strip away.

Return Value

Type: auto

The passed line without any trailing passed characters.

Examples

{
+    immutable trailing = "abc,";
+    immutable stripped = trailing.strippedRight(',');
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "abc!!!";
+    immutable stripped = trailing.strippedRight('!');
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "abc";
+    immutable stripped = trailing.strippedRight(' ');
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "";
+    immutable stripped = trailing.strippedRight(' ');
+    assert(!stripped.length, stripped);
+}
+{
+    immutable trailing = "abc,!.-";
+    immutable stripped = trailing.strippedRight("-.!,");
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "abc!!!";
+    immutable stripped = trailing.strippedRight("!");
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "abc";
+    immutable stripped = trailing.strippedRight(" ABC");
+    assert((stripped == "abc"), stripped);
+}
+{
+    immutable trailing = "";
+    immutable stripped = trailing.strippedRight(" ");
+    assert(!stripped.length, stripped);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.string.strippedRight.html b/lu.string.strippedRight.html new file mode 100644 index 00000000..169cebb6 --- /dev/null +++ b/lu.string.strippedRight.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.string.tabs.html b/lu.string.tabs.html new file mode 100644 index 00000000..bc9d66f2 --- /dev/null +++ b/lu.string.tabs.html @@ -0,0 +1,59 @@ + + + + tabs (lu.string.tabs) + + + + + + + + + + +
+
+

tabs

Returns a range of *spaces* equal to that of num tabs (\t).

Use std.conv.to or std.conv.text or similar to flatten to a string.

@safe pure nothrow @nogc
tabs
(
uint spaces = 4
)
(
const int num
)

Parameters

spaces

How many spaces make up a tab.

num int

How many tabs we want.

Return Value

Type: auto

A range of whitespace equalling (num * spaces) spaces.

Examples

string indentation = 2.tabs.text;
+assert((indentation == "        "), `"` ~  indentation ~ `"`);
+string smallIndent = 1.tabs!2.text;
+assert((smallIndent == "  "), `"` ~  smallIndent ~ `"`);
import std.array : Appender;
+import std.conv : to;
+import std.exception : assertThrown;
+import std.format : formattedWrite;
+import std.algorithm.comparison : equal;
+import core.exception : AssertError;
+
+auto one = 1.tabs!4;
+auto two = 2.tabs!3;
+auto three = 3.tabs!2;
+auto zero = 0.tabs;
+
+assert(one.equal("    "), one.to!string);
+assert(two.equal("      "), two.to!string);
+assert(three.equal("      "), three.to!string);
+assert(zero.equal(string.init), zero.to!string);
+
+assertThrown!AssertError((-1).tabs);
+
+Appender!(char[]) sink;
+sink.formattedWrite("%sHello world", 2.tabs!2);
+assert((sink.data == "    Hello world"), sink.data);
+ +
+ + + \ No newline at end of file diff --git a/lu.string.unenclosed.html b/lu.string.unenclosed.html new file mode 100644 index 00000000..3477c2d9 --- /dev/null +++ b/lu.string.unenclosed.html @@ -0,0 +1,37 @@ + + + + unenclosed (lu.string.unenclosed) + + + + + + + + + + +
+
+

unenclosed

Removes paired preceding and trailing tokens around a string line. + Assumes ASCII.

You should not need to use this directly; rather see unquoted and + unsinglequoted.

private @safe pure nothrow @nogc
unenclosed
(
char token = '"'
)
(
return scope string line
)

Parameters

token

Token character to strip away.

line string

String line to remove any enclosing tokens from.

Return Value

Type: auto

A slice of the passed string line without enclosing tokens.

+ +
+ + + \ No newline at end of file diff --git a/lu.string.unquoted.html b/lu.string.unquoted.html new file mode 100644 index 00000000..ae637875 --- /dev/null +++ b/lu.string.unquoted.html @@ -0,0 +1,44 @@ + + + + unquoted (lu.string.unquoted) + + + + + + + + + + +
+
+

unquoted

Removes paired preceding and trailing double quotes, unquoting a word. + Assumes ASCII.

Does not decode the string and may thus give weird results on weird inputs.

@safe pragma(inline, true) pure nothrow @nogc
unquoted
(
return scope string line
)

Parameters

line string

The (potentially) quoted string.

Return Value

Type: auto

A slice of the line argument that excludes the quotes.

Examples

string quoted = `"This is a quote"`;
+string unquotedLine = quoted.unquoted;
+assert((unquotedLine == "This is a quote"), unquotedLine);
assert(`"Lorem ipsum sit amet"`.unquoted == "Lorem ipsum sit amet");
+assert(`"""""Lorem ipsum sit amet"""""`.unquoted == "Lorem ipsum sit amet");
+// Unbalanced quotes are left untouched
+assert(`"Lorem ipsum sit amet`.unquoted == `"Lorem ipsum sit amet`);
+assert(`"Lorem \"`.unquoted == `"Lorem \"`);
+assert("\"Lorem \\\"".unquoted == "\"Lorem \\\"");
+assert(`"\"`.unquoted == `"\"`);
+ +
+ + + \ No newline at end of file diff --git a/lu.string.unsinglequoted.html b/lu.string.unsinglequoted.html new file mode 100644 index 00000000..c56b019f --- /dev/null +++ b/lu.string.unsinglequoted.html @@ -0,0 +1,44 @@ + + + + unsinglequoted (lu.string.unsinglequoted) + + + + + + + + + + +
+
+

unsinglequoted

Removes paired preceding and trailing single quotes around a line. + Assumes ASCII.

Does not decode the string and may thus give weird results on weird inputs.

@safe pragma(inline, true) pure nothrow @nogc
unsinglequoted
(
return scope string line
)

Parameters

line string

The (potentially) single-quoted string.

Return Value

Type: auto

A slice of the line argument that excludes the single-quotes.

Examples

string quoted = `'This is single-quoted'`;
+string unquotedLine = quoted.unsinglequoted;
+assert((unquotedLine == "This is single-quoted"), unquotedLine);
assert(`'Lorem ipsum sit amet'`.unsinglequoted == "Lorem ipsum sit amet");
+assert(`''''Lorem ipsum sit amet''''`.unsinglequoted == "Lorem ipsum sit amet");
+// Unbalanced quotes are left untouched
+assert(`'Lorem ipsum sit amet`.unsinglequoted == `'Lorem ipsum sit amet`);
+assert(`'Lorem \'`.unsinglequoted == `'Lorem \'`);
+assert("'Lorem \\'".unsinglequoted == "'Lorem \\'");
+assert(`'`.unsinglequoted == `'`);
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.CategoryName.fqn.html b/lu.traits.CategoryName.fqn.html new file mode 100644 index 00000000..2b6d560b --- /dev/null +++ b/lu.traits.CategoryName.fqn.html @@ -0,0 +1,35 @@ + + + + CategoryName.fqn (lu.traits.CategoryName.fqn) + + + + + + + + + + +
+
+

CategoryName.fqn

The fully qualified name for the symbol sym is an alias of.

template CategoryName(alias sym)
enum fqn = fullyQualifiedName!sym;
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.CategoryName.html b/lu.traits.CategoryName.html new file mode 100644 index 00000000..8790e602 --- /dev/null +++ b/lu.traits.CategoryName.html @@ -0,0 +1,101 @@ + + + + CategoryName (lu.traits.CategoryName) + + + + + + + + + + +
+
+

CategoryName

Provides string representations of the category of a symbol, where such is not + a fundamental primitive variable but a module, a function, a delegate, + a class or a struct.

Accurate module detection only works on compilers 2.087 and later, due to + missing support for __traits(isModule).

template CategoryName (
alias sym
) {
static if(isFunction!sym)
enum type;
static if(!(isFunction!sym))
static if(isDelegate!sym)
enum type;
static if(!(isFunction!sym))
static if(!(isDelegate!sym))
static if(is(sym == class) || is(typeof(sym) == class))
enum type;
static if(!(isFunction!sym))
static if(!(isDelegate!sym))
static if(!(is(sym == class) || is(typeof(sym) == class)))
static if(is(sym == struct) || is(typeof(sym) == struct))
enum type;
static if(!(isFunction!sym))
static if(!(isDelegate!sym))
static if(!(is(sym == class) || is(typeof(sym) == class)))
static if(!(is(sym == struct) || is(typeof(sym) == struct)))
static if(is(sym == interface) || is(typeof(sym) == interface))
enum type;
static if(!(isFunction!sym))
static if(!(isDelegate!sym))
static if(!(is(sym == class) || is(typeof(sym) == class)))
static if(!(is(sym == struct) || is(typeof(sym) == struct)))
static if(!(is(sym == interface) || is(typeof(sym) == interface)))
static if(is(sym == union) || is(typeof(sym) == union))
enum type;
static if(!(isFunction!sym))
static if(!(isDelegate!sym))
static if(!(is(sym == class) || is(typeof(sym) == class)))
static if(!(is(sym == struct) || is(typeof(sym) == struct)))
static if(!(is(sym == interface) || is(typeof(sym) == interface)))
static if(!(is(sym == union) || is(typeof(sym) == union)))
static if(((__VERSION__ >= 2087L) && __traits(isModule, sym)) || ((__VERSION__ < 2087L) && __traits(compiles, )))
enum type;
static if(!(isFunction!sym))
static if(!(isDelegate!sym))
static if(!(is(sym == class) || is(typeof(sym) == class)))
static if(!(is(sym == struct) || is(typeof(sym) == struct)))
static if(!(is(sym == interface) || is(typeof(sym) == interface)))
static if(!(is(sym == union) || is(typeof(sym) == union)))
static if(!(((__VERSION__ >= 2087L) && __traits(isModule, sym)) || ((__VERSION__ < 2087L) && __traits(compiles, ))))
enum type;
}

Members

Imports

fullyQualifiedName (from std.traits)
public +import std.traits : isDelegate, isFunction, fullyQualifiedName;
Undocumented in source.
isDelegate (from std.traits)
public +import std.traits : isDelegate, isFunction, fullyQualifiedName;
Undocumented in source.
isFunction (from std.traits)
public +import std.traits : isDelegate, isFunction, fullyQualifiedName;
Undocumented in source.

Manifest constants

fqn
enum fqn;

The fully qualified name for the symbol sym is an alias of.

name
enum name;

A short name for the symbol sym is an alias of.

Parameters

sym

Symbol to provide the strings for.

Examples

module foo;
+
+void bar() {}
+
+alias categoryName = CategoryName!bar;
+
+assert(categoryName.type == "function");
+assert(categoryName.name == "bar");
+assert(categoryName.fqn == "foo.bar");
bool localSymbol;
+
+void fn() {}
+
+auto dg = () => localSymbol;
+
+class C {}
+C c;
+
+struct S {}
+S s;
+
+interface I {}
+
+union U
+{
+    int i;
+    bool b;
+}
+
+U u;
+
+alias Ffn = CategoryName!fn;
+static assert(Ffn.type == "function");
+static assert(Ffn.name == "fn");
+// Can't test fqn from inside a unittest
+
+alias Fdg = CategoryName!dg;
+static assert(Fdg.type == "delegate");
+static assert(Fdg.name == "dg");
+// Ditto
+
+alias Fc = CategoryName!c;
+static assert(Fc.type == "class");
+static assert(Fc.name == "c");
+// Ditto
+
+alias Fs = CategoryName!s;
+static assert(Fs.type == "struct");
+static assert(Fs.name == "s");
+
+alias Fm = CategoryName!(lu.traits);
+static assert(Fm.type == "module");
+static assert(Fm.name == "traits");
+static assert(Fm.fqn == "lu.traits");
+
+alias Fi = CategoryName!I;
+static assert(Fi.type == "interface");
+static assert(Fi.name == "I");
+
+alias Fu = CategoryName!u;
+static assert(Fu.type == "union");
+static assert(Fu.name == "u");
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.CategoryName.name.html b/lu.traits.CategoryName.name.html new file mode 100644 index 00000000..9dfe0064 --- /dev/null +++ b/lu.traits.CategoryName.name.html @@ -0,0 +1,35 @@ + + + + CategoryName.name (lu.traits.CategoryName.name) + + + + + + + + + + +
+
+

CategoryName.name

A short name for the symbol sym is an alias of.

template CategoryName(alias sym)
enum name = __traits(identifier, sym);
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.MixinConstraints.html b/lu.traits.MixinConstraints.html new file mode 100644 index 00000000..39e4a052 --- /dev/null +++ b/lu.traits.MixinConstraints.html @@ -0,0 +1,89 @@ + + + + MixinConstraints (lu.traits.MixinConstraints) + + + + + + + + + + +
+
+

MixinConstraints

Mixes in constraints into another mixin template, to provide static + guarantees that it is not mixed into a type of scope other than the one specified.

Using this you can ensure that a mixin template meant to be mixed into a + class isn't mixed into a module-level scope, or into a function, etc.

More than one scope type can be supplied with bitwise OR.

Parameters

mixinScope

The scope into which to only allow the mixin to be mixed in. + All other kinds of scopes will be statically rejected.

mixinName

Optional string name of the mixing-in mixin. + Can be anything; it's just used for the error messages.

Examples

module foo;
+
+mixin template Foo()
+{
+    mixin MixinConstraints!(MixinScope.module_, "Foo");  // Constrained to module-level scope
+}
+
+mixin Foo;  // no problem, scope is MixinScope.module_
+
+void bar()
+{
+    mixin Foo;  // static assert(0): scope is MixinScope.function_, not MixinScope.module_
+}
+
+class C
+{
+    mixin Foo;  // static assert(0): ditto but MixinScope.class_
+}
+
+struct C
+{
+    mixin Foo;  // static assert(0): ditto but MixinScope.struct_
+}
+
+mixin template FooStructOrClass()
+{
+    mixin MixinConstraints(MixinScope.struct_ | MixinScope.class_);
+}
void fun()
+{
+    // MixinConstraints!(MixinScope.function_, "TestMixinConstrainedToFunctions");
+    mixin TestMixinConstrainedToFunctions;
+}
+
+class TestClassC
+{
+    // MixinConstraints!(MixinScope.class_, "TestMixinConstrainedToClass");
+    mixin TestMixinConstrainedToClass;
+}
+
+struct TestStructS
+{
+    // mixin MixinConstraints!(MixinScope.struct_, "TestMixinConstrainedToStruct");
+    mixin TestMixinConstrainedToStruct;
+}
+
+struct TestStructS2
+{
+    mixin TestMixinConstrainedToClassOrStruct;
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.MixinScope.html b/lu.traits.MixinScope.html new file mode 100644 index 00000000..2d8f7134 --- /dev/null +++ b/lu.traits.MixinScope.html @@ -0,0 +1,35 @@ + + + + MixinScope (lu.traits.MixinScope) + + + + + + + + + + +
+
+

MixinScope

The types of scope into which a mixin template may be mixed in.

Values

ValueMeaning
function_1 << 0

Mixed in inside a function.

class_1 << 1

Mixed in inside a class.

struct_1 << 2

Mixed in inside a struct.

interface_1 << 3

Mixed in inside an interface.

union_1 << 4

Mixed in inside a union.

module_1 << 5

Mixed in inside a module.

+ +
+ + + \ No newline at end of file diff --git a/lu.traits.TakesParams.1.html b/lu.traits.TakesParams.1.html new file mode 100644 index 00000000..0a4c2adc --- /dev/null +++ b/lu.traits.TakesParams.1.html @@ -0,0 +1,61 @@ + + + + TakesParams (lu.traits.TakesParams) + + + + + + + + + + +
+
+

TakesParams

Given a function and a tuple of types, evaluates whether that function could + be called with that tuple as parameters. Alias version (works on functions, + not function types.)

Qualifiers like const andimmutable are skipped, which may make it a poor + choice if dealing with functions that require such arguments.

It is merely syntactic sugar, using std.meta and std.traits behind the scenes.

  1. template TakesParams(alias fun, P...)
    template TakesParams (
    alias fun
    P...
    ) if (
    isSomeFunction!fun
    ) {
    static if(is(FunParams : PassedParams))
    enum TakesParams;
    static if(!(is(FunParams : PassedParams)))
    enum TakesParams;
    }
  2. template TakesParams(Fun, P...)

Members

Imports

Parameters (from std.traits)
public +import std.traits : Parameters, Unqual, staticMap;
Undocumented in source.
Unqual (from std.traits)
public +import std.traits : Parameters, Unqual, staticMap;
Undocumented in source.
staticMap (from std.traits)
public +import std.traits : Parameters, Unqual, staticMap;
Undocumented in source.

Parameters

fun

Function to evaluate the parameters of.

P

Variadic list of types to compare fun's function parameters with.

Examples

void noParams();
+bool boolParam(bool);
+string stringParam(string);
+float floatParam(float);
+
+static assert(TakesParams!(noParams));
+static assert(TakesParams!(boolParam, bool));
+static assert(TakesParams!(stringParam, string));
+static assert(TakesParams!(floatParam, float));
void foo();
+void foo1(string);
+void foo2(string, int);
+void foo3(bool, bool, bool);
+
+static assert(TakesParams!(foo));//, AliasSeq!()));
+static assert(TakesParams!(foo1, string));
+static assert(TakesParams!(foo2, string, int));
+static assert(TakesParams!(foo3, bool, bool, bool));
+
+static assert(!TakesParams!(foo, string));
+static assert(!TakesParams!(foo1, string, int));
+static assert(!TakesParams!(foo2, bool, bool, bool));
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.TakesParams.2.html b/lu.traits.TakesParams.2.html new file mode 100644 index 00000000..d6ef3370 --- /dev/null +++ b/lu.traits.TakesParams.2.html @@ -0,0 +1,70 @@ + + + + TakesParams (lu.traits.TakesParams) + + + + + + + + + + +
+
+

TakesParams

Given a function and a tuple of types, evaluates whether that function could + be called with that tuple as parameters. Non-alias version (works on types).

Qualifiers like const and immutable are skipped, which may make it a + poor choice if dealing with functions that require such arguments.

It is merely syntactic sugar, using std.meta and std.traits behind the scenes.

  1. template TakesParams(alias fun, P...)
  2. template TakesParams(Fun, P...)
    template TakesParams (
    Fun
    P...
    ) if (
    isSomeFunction!Fun
    ) {
    static if(is(FunParams : PassedParams))
    enum TakesParams;
    static if(!(is(FunParams : PassedParams)))
    enum TakesParams;
    }

Members

Imports

Parameters (from std.traits)
public +import std.traits : Parameters, Unqual, staticMap;
Undocumented in source.
Unqual (from std.traits)
public +import std.traits : Parameters, Unqual, staticMap;
Undocumented in source.
staticMap (from std.traits)
public +import std.traits : Parameters, Unqual, staticMap;
Undocumented in source.

Parameters

Fun

Type of function to evaluate the parameters of.

P

Variadic list of types to compare Fun function parameters with.

Examples

void noParams();
+bool boolParam(bool);
+string stringParam(string);
+float floatParam(float);
+
+alias N = typeof(noParams);
+alias B = typeof(boolParam);
+alias S = typeof(stringParam);
+alias F = typeof(floatParam);
+
+static assert(TakesParams!N);
+static assert(TakesParams!(B, bool));
+static assert(TakesParams!(S, string));
+static assert(TakesParams!(F, float));
void foo();
+void foo1(string);
+void foo2(string, int);
+void foo3(bool, bool, bool);
+
+alias F = typeof(foo);
+alias F1 = typeof(foo1);
+alias F2 = typeof(foo2);
+alias F3 = typeof(foo3);
+
+static assert(TakesParams!F);//, AliasSeq!()));
+static assert(TakesParams!(F1, string));
+static assert(TakesParams!(F2, string, int));
+static assert(TakesParams!(F3, bool, bool, bool));
+
+static assert(!TakesParams!(F, string));
+static assert(!TakesParams!(F1, string, int));
+static assert(!TakesParams!(F2, bool, bool, bool));
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.TakesParams.html b/lu.traits.TakesParams.html new file mode 100644 index 00000000..0fdb22e0 --- /dev/null +++ b/lu.traits.TakesParams.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.traits.UnqualArray.1.html b/lu.traits.UnqualArray.1.html new file mode 100644 index 00000000..2993b734 --- /dev/null +++ b/lu.traits.UnqualArray.1.html @@ -0,0 +1,51 @@ + + + + UnqualArray (lu.traits.UnqualArray) + + + + + + + + + + +
+
+

UnqualArray

Given an array of qualified elements, aliases itself to one such of + unqualified elements.

  1. template UnqualArray(QualArray : QualType[], QualType)
    template UnqualArray (
    QualArray : QualType[]
    QualType
    ) if (
    !isAssociativeArray!QualType
    ) {}
  2. template UnqualArray(QualArray : QualElem[QualKey], QualElem, QualKey)
  3. template UnqualArray(QualArray : QualElem[QualKey], QualElem, QualKey)

Members

Imports

Unqual (from std.traits)
public +import std.traits : Unqual;
Undocumented in source.

Parameters

QualArray

Qualified array type.

QualType

Qualified type, element of QualArray.

Examples

alias ConstStrings = const(string)[];
+alias UnqualStrings = UnqualArray!ConstStrings;
+static assert(is(UnqualStrings == string[]));
+
+alias ImmChars = string;
+alias UnqualChars = UnqualArray!ImmChars;
+static assert(is(UnqualChars == char[]));
+
+alias InoutBools = inout(bool)[];
+alias UnqualBools = UnqualArray!InoutBools;
+static assert(is(UnqualBools == bool[]));
+
+alias ConstChars = const(char)[];
+alias UnqualChars2 = UnqualArray!ConstChars;
+static assert(is(UnqualChars2 == char[]));
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.UnqualArray.2.html b/lu.traits.UnqualArray.2.html new file mode 100644 index 00000000..c103aef4 --- /dev/null +++ b/lu.traits.UnqualArray.2.html @@ -0,0 +1,51 @@ + + + + UnqualArray (lu.traits.UnqualArray) + + + + + + + + + + +
+
+

UnqualArray

Given an associative array with elements that have a storage class, aliases + itself to an associative array with elements without the storage classes.

  1. template UnqualArray(QualArray : QualType[], QualType)
  2. template UnqualArray(QualArray : QualElem[QualKey], QualElem, QualKey)
    template UnqualArray (
    QualArray : QualElem[QualKey]
    QualElem
    QualKey
    ) if (
    !isArray!QualElem
    ) {}
  3. template UnqualArray(QualArray : QualElem[QualKey], QualElem, QualKey)

Members

Imports

Unqual (from std.traits)
public +import std.traits : Unqual;
Undocumented in source.

Parameters

QualArray

Qualified associative array type.

QualElem

Qualified type, element of QualArray.

QualKey

Qualified type, key of QualArray.

Examples

alias ConstStringAA = const(string)[int];
+alias UnqualStringAA = UnqualArray!ConstStringAA;
+static assert (is(UnqualStringAA == string[int]));
+
+alias ImmIntAA = immutable(int)[char];
+alias UnqualIntAA = UnqualArray!ImmIntAA;
+static assert(is(UnqualIntAA == int[char]));
+
+alias InoutBoolAA = inout(bool)[long];
+alias UnqualBoolAA = UnqualArray!InoutBoolAA;
+static assert(is(UnqualBoolAA == bool[long]));
+
+alias ConstCharAA = const(char)[string];
+alias UnqualCharAA = UnqualArray!ConstCharAA;
+static assert(is(UnqualCharAA == char[string]));
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.UnqualArray.3.html b/lu.traits.UnqualArray.3.html new file mode 100644 index 00000000..c30f73c0 --- /dev/null +++ b/lu.traits.UnqualArray.3.html @@ -0,0 +1,51 @@ + + + + UnqualArray (lu.traits.UnqualArray) + + + + + + + + + + +
+
+

UnqualArray

Given an associative array of arrays with a storage class, aliases itself to + an associative array with array elements without the storage classes.

  1. template UnqualArray(QualArray : QualType[], QualType)
  2. template UnqualArray(QualArray : QualElem[QualKey], QualElem, QualKey)
  3. template UnqualArray(QualArray : QualElem[QualKey], QualElem, QualKey)
    template UnqualArray (
    QualArray : QualElem[QualKey]
    QualElem
    QualKey
    ) if (
    isArray!QualElem
    ) {}

Members

Imports

Unqual (from std.traits)
public +import std.traits : Unqual;
Undocumented in source.

Parameters

QualArray

Qualified associative array type.

QualElem

Qualified type, element of QualArray.

QualKey

Qualified type, key of QualArray.

Examples

alias ConstStringArrays = const(string[])[int];
+alias UnqualStringArrays = UnqualArray!ConstStringArrays;
+static assert (is(UnqualStringArrays == string[][int]));
+
+alias ImmIntArrays = immutable(int[])[char];
+alias UnqualIntArrays = UnqualArray!ImmIntArrays;
+static assert(is(UnqualIntArrays == int[][char]));
+
+alias InoutBoolArrays = inout(bool)[][long];
+alias UnqualBoolArrays = UnqualArray!InoutBoolArrays;
+static assert(is(UnqualBoolArrays == bool[][long]));
+
+alias ConstCharArrays = const(char)[][string];
+alias UnqualCharArrays = UnqualArray!ConstCharArrays;
+static assert(is(UnqualCharArrays == char[][string]));
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.UnqualArray.html b/lu.traits.UnqualArray.html new file mode 100644 index 00000000..15e7ae41 --- /dev/null +++ b/lu.traits.UnqualArray.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.traits.getSymbolsByUDA.html b/lu.traits.getSymbolsByUDA.html new file mode 100644 index 00000000..3c121a42 --- /dev/null +++ b/lu.traits.getSymbolsByUDA.html @@ -0,0 +1,38 @@ + + + + getSymbolsByUDA (lu.traits.getSymbolsByUDA) + + + + + + + + + + +
+
+

getSymbolsByUDA

Provide a non-2.088, non-2.089 getSymbolsByUDA.

The getSymbolsByUDA in 2.088/2.089 is + completely broken by having inserted a constraint to force it to only + work on aggregates, which a module apparently isn't.

static if((__VERSION__ == 2088L) || (__VERSION__ == 2089L))
template getSymbolsByUDA (
alias symbol
alias attribute
) {}

Members

Imports

hasUDA (from std.traits)
public +import std.traits : hasUDA;
Undocumented in source.
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.getSymbolsByUDAImpl.html b/lu.traits.getSymbolsByUDAImpl.html new file mode 100644 index 00000000..0908872f --- /dev/null +++ b/lu.traits.getSymbolsByUDAImpl.html @@ -0,0 +1,35 @@ + + + + getSymbolsByUDAImpl (lu.traits.getSymbolsByUDAImpl) + + + + + + + + + + +
+
+

getSymbolsByUDAImpl

Implementation of getSymbolsByUDA, copy/pasted.

private
static if((__VERSION__ == 2088L) || (__VERSION__ == 2089L))
template getSymbolsByUDAImpl (
alias symbol
alias attribute
names...
) {}
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.html b/lu.traits.html new file mode 100644 index 00000000..0d401358 --- /dev/null +++ b/lu.traits.html @@ -0,0 +1,47 @@ + + + + lu.traits (lu.traits) + + + + + + + + + + +
+
+

lu.traits

Various compile-time traits and cleverness.

Members

Enums

MixinScope
enum MixinScope

The types of scope into which a mixin template may be mixed in.

isMerelyArray
eponymoustemplate isMerelyArray(S)

True if a type is a non-string array; otherwise false.

isMutableArrayOfImmutables
eponymoustemplate isMutableArrayOfImmutables(Array : Element[], Element)

Evaluates whether or not a passed array type is a mutable array of immutable + elements, such as a string.

isStruct
eponymoustemplate isStruct(T)

Eponymous template that is true if the passed type is a struct.

isTrulyString
eponymoustemplate isTrulyString(S)

True if a type is string, dstring or wstring; otherwise false.

Imports

getSymbolsByUDA (from std.traits)
public +import std.traits : getSymbolsByUDA;
Undocumented in source.

Mixin templates

MixinConstraints
mixintemplate MixinConstraints(MixinScope mixinScope, string mixinName = "a constrained mixin")

Mixes in constraints into another mixin template, to provide static + guarantees that it is not mixed into a type of scope other than the one specified.

Templates

CategoryName
template CategoryName(alias sym)

Provides string representations of the category of a symbol, where such is not + a fundamental primitive variable but a module, a function, a delegate, + a class or a struct.

TakesParams
template TakesParams(alias fun, P...)

Given a function and a tuple of types, evaluates whether that function could + be called with that tuple as parameters. Alias version (works on functions, + not function types.)

TakesParams
template TakesParams(Fun, P...)

Given a function and a tuple of types, evaluates whether that function could + be called with that tuple as parameters. Non-alias version (works on types).

UnqualArray
template UnqualArray(QualArray : QualType[], QualType)

Given an array of qualified elements, aliases itself to one such of + unqualified elements.

UnqualArray
template UnqualArray(QualArray : QualElem[QualKey], QualElem, QualKey)

Given an associative array with elements that have a storage class, aliases + itself to an associative array with elements without the storage classes.

UnqualArray
template UnqualArray(QualArray : QualElem[QualKey], QualElem, QualKey)

Given an associative array of arrays with a storage class, aliases itself to + an associative array with array elements without the storage classes.

getSymbolsByUDA
template getSymbolsByUDA(alias symbol, alias attribute)

Provide a non-2.088, non-2.089 getSymbolsByUDA.

getSymbolsByUDAImpl
template getSymbolsByUDAImpl(alias symbol, alias attribute, names...)

Implementation of getSymbolsByUDA, copy/pasted.

isSerialisable
template isSerialisable(alias sym)

Eponymous template bool of whether a variable can be treated as a mutable + variable, like a fundamental integral, and thus be serialised.

stringofParams
template stringofParams(alias fun)

Produces a string of the unqualified parameters of the passed function alias.

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.traits.isMerelyArray.html b/lu.traits.isMerelyArray.html new file mode 100644 index 00000000..4d305c16 --- /dev/null +++ b/lu.traits.isMerelyArray.html @@ -0,0 +1,41 @@ + + + + isMerelyArray (lu.traits.isMerelyArray) + + + + + + + + + + +
+
+

isMerelyArray

True if a type is a non-string array; otherwise false.

For now also evaluates to true for static arrays.

enum isMerelyArray (
S
)

Parameters

S

Array type to introspect.

Examples

static assert(!isMerelyArray!string);
+static assert(!isMerelyArray!dstring);
+static assert(!isMerelyArray!wstring);
+static assert(isMerelyArray!(char[]));
+static assert(isMerelyArray!(dchar[]));
+static assert(isMerelyArray!(wchar[]));
+static assert(isMerelyArray!(int[5]));
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.isMutableArrayOfImmutables.html b/lu.traits.isMutableArrayOfImmutables.html new file mode 100644 index 00000000..9d73dd2a --- /dev/null +++ b/lu.traits.isMutableArrayOfImmutables.html @@ -0,0 +1,42 @@ + + + + isMutableArrayOfImmutables (lu.traits.isMutableArrayOfImmutables) + + + + + + + + + + +
+
+

isMutableArrayOfImmutables

Evaluates whether or not a passed array type is a mutable array of immutable + elements, such as a string.

enum isMutableArrayOfImmutables (
Array : Element[]
Element
)

Parameters

Array

Array to inspect.

Examples

static assert(isMutableArrayOfImmutables!string);
+static assert(isMutableArrayOfImmutables!wstring);
+static assert(isMutableArrayOfImmutables!dstring);
+static assert(!isMutableArrayOfImmutables!(immutable(string)));
+
+static assert(isMutableArrayOfImmutables!(immutable(int)[]));
+static assert(!isMutableArrayOfImmutables!(immutable(int[])));
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.isSerialisable.html b/lu.traits.isSerialisable.html new file mode 100644 index 00000000..16d43553 --- /dev/null +++ b/lu.traits.isSerialisable.html @@ -0,0 +1,52 @@ + + + + isSerialisable (lu.traits.isSerialisable) + + + + + + + + + + +
+
+

isSerialisable

Eponymous template bool of whether a variable can be treated as a mutable + variable, like a fundamental integral, and thus be serialised.

Currently it does not support static arrays.

template isSerialisable (
alias sym
) {
static if(!isType!sym)
enum isSerialisable;
static if(!(!isType!sym))
enum isSerialisable;
}

Members

Imports

isSomeFunction (from std.traits)
public +import std.traits : isSomeFunction;
Undocumented in source.
isType (from std.traits)
public +import std.traits : isType;
Undocumented in source.

Parameters

sym

Alias of symbol to introspect.

Examples

int i;
+char[] c;
+char[8] c2;
+struct S {}
+class C {}
+enum E { foo }
+E e;
+
+static assert(isSerialisable!i);
+static assert(isSerialisable!c);
+static assert(!isSerialisable!c2); // should static arrays pass?
+static assert(!isSerialisable!S);
+static assert(!isSerialisable!C);
+static assert(!isSerialisable!E);
+static assert(isSerialisable!e);
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.isStruct.html b/lu.traits.isStruct.html new file mode 100644 index 00000000..e4fb9321 --- /dev/null +++ b/lu.traits.isStruct.html @@ -0,0 +1,35 @@ + + + + isStruct (lu.traits.isStruct) + + + + + + + + + + +
+
+

isStruct

Eponymous template that is true if the passed type is a struct.

Used with std.meta.Filter, which cannot take is() expressions.

enum isStruct (
T
)

Parameters

T

Type to introspect.

+ +
+ + + \ No newline at end of file diff --git a/lu.traits.isTrulyString.html b/lu.traits.isTrulyString.html new file mode 100644 index 00000000..6bb62cc0 --- /dev/null +++ b/lu.traits.isTrulyString.html @@ -0,0 +1,41 @@ + + + + isTrulyString (lu.traits.isTrulyString) + + + + + + + + + + +
+
+

isTrulyString

True if a type is string, dstring or wstring; otherwise false.

Does not consider e.g. char[] a string, as + isSomeString does.

enum isTrulyString (
S
)

Parameters

S

String type to introspect.

Examples

static assert(isTrulyString!string);
+static assert(isTrulyString!dstring);
+static assert(isTrulyString!wstring);
+static assert(!isTrulyString!(char[]));
+static assert(!isTrulyString!(dchar[]));
+static assert(!isTrulyString!(wchar[]));
+ +
+ + + \ No newline at end of file diff --git a/lu.traits.stringofParams.html b/lu.traits.stringofParams.html new file mode 100644 index 00000000..4ca49207 --- /dev/null +++ b/lu.traits.stringofParams.html @@ -0,0 +1,52 @@ + + + + stringofParams (lu.traits.stringofParams) + + + + + + + + + + +
+
+

stringofParams

Produces a string of the unqualified parameters of the passed function alias.

template stringofParams (
alias fun
) {
enum stringofParams;
}

Members

Imports

Parameters (from std.traits)
public +import std.traits : Parameters, Unqual, staticMap;
Undocumented in source.
Unqual (from std.traits)
public +import std.traits : Parameters, Unqual, staticMap;
Undocumented in source.
staticMap (from std.traits)
public +import std.traits : Parameters, Unqual, staticMap;
Undocumented in source.

Parameters

fun

A function alias to get the parameter string of.

Examples

void foo(bool b, int i, string s) {}
+static assert(stringofParams!foo == "bool, int, string");
void foo();
+void foo1(string);
+void foo2(string, int);
+void foo3(bool, bool, bool);
+
+enum ofFoo = stringofParams!foo;
+enum ofFoo1 = stringofParams!foo1;
+enum ofFoo2 = stringofParams!foo2;
+enum ofFoo3 = stringofParams!foo3;
+
+static assert(!ofFoo.length, ofFoo);
+static assert((ofFoo1 == "string"), ofFoo1);
+static assert((ofFoo2 == "string, int"), ofFoo2);
+static assert((ofFoo3 == "bool, bool, bool"), ofFoo3);
+ +
+ + + \ No newline at end of file diff --git a/lu.typecons.UnderscoreOpDispatcher.html b/lu.typecons.UnderscoreOpDispatcher.html new file mode 100644 index 00000000..1a32e449 --- /dev/null +++ b/lu.typecons.UnderscoreOpDispatcher.html @@ -0,0 +1,89 @@ + + + + UnderscoreOpDispatcher (lu.typecons.UnderscoreOpDispatcher) + + + + + + + + + + +
+
+

UnderscoreOpDispatcher

Mixin template generating an opDispatch redirecting calls to members whose + names match the passed variable string but with an underscore prepended.

Members

Functions

opDispatch
auto ref opDispatch(T value)

Mutator.

opDispatch
auto opDispatch()

Accessor.

Examples

{
+    struct Foo
+    {
+        int _i;
+        string _s;
+        bool _b;
+        string[] _add;
+        alias wordList = _add;
+
+        mixin UnderscoreOpDispatcher;
+    }
+
+    Foo f;
+    f.i = 42;         // f.opDispatch!"i"(42);
+    f.s = "hello";    // f.opDispatch!"s"("hello");
+    f.b = true;       // f.opDispatch!"b"(true);
+    f.add("hello");   // f.opDispatch!"add"("hello");
+    f.add("world");   // f.opDispatch!"add"("world");
+
+    assert(f.i == 42);
+    assert(f.s == "hello");
+    assert(f.b);
+    assert(f.wordList == [ "hello", "world" ]);
+
+    /+
+        Returns `this` by reference, so we can chain calls.
+    +/
+    auto f2 = Foo()
+        .i(9001)
+        .s("world")
+        .b(false)
+        .add("hello")
+        .add("world");
+
+    assert(f2.i == 9001);
+    assert(f2.s == "world");
+    assert(!f2.b);
+    assert(f2.wordList == [ "hello", "world" ]);
+}
+{
+    struct Bar
+    {
+        string[string] _aa;
+
+        mixin UnderscoreOpDispatcher;
+    }
+
+    Bar bar;
+    bar.aa = [ "hello" : "world" ];
+    bar.aa = [ "foo" : "bar" ];
+    assert(bar.aa == [ "hello" : "world", "foo" : "bar"]);
+}
+ +
+ + + \ No newline at end of file diff --git a/lu.typecons.UnderscoreOpDispatcher.opDispatch.1.html b/lu.typecons.UnderscoreOpDispatcher.opDispatch.1.html new file mode 100644 index 00000000..249e33f7 --- /dev/null +++ b/lu.typecons.UnderscoreOpDispatcher.opDispatch.1.html @@ -0,0 +1,35 @@ + + + + UnderscoreOpDispatcher.opDispatch (lu.typecons.UnderscoreOpDispatcher.opDispatch) + + + + + + + + + + +
+
+

UnderscoreOpDispatcher.opDispatch

Mutator.

  1. auto ref opDispatch(T value)
    mixintemplate UnderscoreOpDispatcher()
    ref
    opDispatch
    (
    string var
    T
    )
    ()
  2. auto opDispatch()

Parameters

var

The variable name to set.

value T

The value to set the variable to.

Return Value

Type: auto ref

A reference to the object which this is mixed into.

+ +
+ + + \ No newline at end of file diff --git a/lu.typecons.UnderscoreOpDispatcher.opDispatch.2.html b/lu.typecons.UnderscoreOpDispatcher.opDispatch.2.html new file mode 100644 index 00000000..a44011d4 --- /dev/null +++ b/lu.typecons.UnderscoreOpDispatcher.opDispatch.2.html @@ -0,0 +1,35 @@ + + + + UnderscoreOpDispatcher.opDispatch (lu.typecons.UnderscoreOpDispatcher.opDispatch) + + + + + + + + + + +
+
+

UnderscoreOpDispatcher.opDispatch

Accessor.

  1. auto ref opDispatch(T value)
  2. auto opDispatch()
    mixintemplate UnderscoreOpDispatcher()
    inout
    opDispatch
    (
    string var
    )
    ()

Parameters

var

The variable name to get.

Return Value

Type: auto

The value of the variable.

+ +
+ + + \ No newline at end of file diff --git a/lu.typecons.UnderscoreOpDispatcher.opDispatch.html b/lu.typecons.UnderscoreOpDispatcher.opDispatch.html new file mode 100644 index 00000000..1ed9607e --- /dev/null +++ b/lu.typecons.UnderscoreOpDispatcher.opDispatch.html @@ -0,0 +1 @@ + Continue to overload \ No newline at end of file diff --git a/lu.typecons.html b/lu.typecons.html new file mode 100644 index 00000000..c5722726 --- /dev/null +++ b/lu.typecons.html @@ -0,0 +1,36 @@ + + + + lu.typecons (lu.typecons) + + + + + + + + + + +
+
+

lu.typecons

Type constructors.

Members

Mixin templates

UnderscoreOpDispatcher
mixintemplate UnderscoreOpDispatcher()

Mixin template generating an opDispatch redirecting calls to members whose + names match the passed variable string but with an underscore prepended.

Meta

+ +
+ + + \ No newline at end of file diff --git a/lu.uda.CannotContainComments.html b/lu.uda.CannotContainComments.html new file mode 100644 index 00000000..2fbfc068 --- /dev/null +++ b/lu.uda.CannotContainComments.html @@ -0,0 +1,36 @@ + + + + CannotContainComments (lu.uda.CannotContainComments) + + + + + + + + + + +
+
+

CannotContainComments

UDA conveying that this member may contain characters that would otherwise + indicate a comment, but isn't.

+ +
+ + + \ No newline at end of file diff --git a/lu.uda.Hidden.html b/lu.uda.Hidden.html new file mode 100644 index 00000000..19e0eccc --- /dev/null +++ b/lu.uda.Hidden.html @@ -0,0 +1,36 @@ + + + + Hidden (lu.uda.Hidden) + + + + + + + + + + +
+
+

Hidden

UDA conveying that this member contains sensitive information and should not + be printed in clear text; e.g. passwords.

+ +
+ + + \ No newline at end of file diff --git a/lu.uda.Quoted.html b/lu.uda.Quoted.html new file mode 100644 index 00000000..98b1d4f3 --- /dev/null +++ b/lu.uda.Quoted.html @@ -0,0 +1,35 @@ + + + + Quoted (lu.uda.Quoted) + + + + + + + + + + +
+
+

Quoted

UDA conveying that this member's value must be quoted when serialised.

+ +
+ + + \ No newline at end of file diff --git a/lu.uda.Separator.html b/lu.uda.Separator.html new file mode 100644 index 00000000..b6877af0 --- /dev/null +++ b/lu.uda.Separator.html @@ -0,0 +1,36 @@ + + + + Separator (lu.uda.Separator) + + + + + + + + + + +
+
+

Separator

UDA conveying that the annotated array should have this token as separator + when formatted to a string.

struct Separator {}

Members

Variables

token
string token;

Separator, can be more than one character.

+ +
+ + + \ No newline at end of file diff --git a/lu.uda.Separator.token.html b/lu.uda.Separator.token.html new file mode 100644 index 00000000..31d9eb99 --- /dev/null +++ b/lu.uda.Separator.token.html @@ -0,0 +1,35 @@ + + + + Separator.token (lu.uda.Separator.token) + + + + + + + + + + +
+
+

Separator.token

Separator, can be more than one character.

struct Separator
string token;
+ +
+ + + \ No newline at end of file diff --git a/lu.uda.Unserialisable.html b/lu.uda.Unserialisable.html new file mode 100644 index 00000000..79df3a76 --- /dev/null +++ b/lu.uda.Unserialisable.html @@ -0,0 +1,35 @@ + + + + Unserialisable (lu.uda.Unserialisable) + + + + + + + + + + +
+
+

Unserialisable

UDA conveying that a field cannot (or should not) be serialised.

+ +
+ + + \ No newline at end of file diff --git a/lu.uda.html b/lu.uda.html new file mode 100644 index 00000000..278f09b0 --- /dev/null +++ b/lu.uda.html @@ -0,0 +1,38 @@ + + + + lu.uda (lu.uda) + + + + + + + + + + +
+
+

lu.uda

Common user-defined attributes (UDAs).

Members

Enums

CannotContainComments
enum CannotContainComments

UDA conveying that this member may contain characters that would otherwise + indicate a comment, but isn't.

Hidden
enum Hidden

UDA conveying that this member contains sensitive information and should not + be printed in clear text; e.g. passwords.

Quoted
enum Quoted

UDA conveying that this member's value must be quoted when serialised.

Unserialisable
enum Unserialisable

UDA conveying that a field cannot (or should not) be serialised.

Structs

Separator
struct Separator

UDA conveying that the annotated array should have this token as separator + when formatted to a string.

Meta

+ +
+ + + \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 00000000..b47257ef --- /dev/null +++ b/script.js @@ -0,0 +1,180 @@ +window.addEventListener("load", function() { + + var lineWrappers = document.querySelectorAll(".with-line-wrappers"); + for(var i = 0; i < lineWrappers.length; i++) { + var l = lineWrappers[i]; + + var codeblock = document.createElement("div"); + codeblock.className = "codeblock"; + l.parentNode.insertBefore(codeblock, l); + + var header = document.createElement("header"); + codeblock.appendChild(header); + codeblock.appendChild(l); + + var btn = document.createElement("button"); + btn.setAttribute("type", "button"); + var canCopyToClipboard = document.queryCommandSupported("copy"); + btn.addEventListener("click", (function(l) { return function() { + document.body.classList.add("hide-line-numbers"); + window.getSelection().selectAllChildren(l); + if(canCopyToClipboard) + if(!document.execCommand("copy")) { + alert("copy failed, try ctrl+c manually"); + } + };})(l)); + btn.textContent = canCopyToClipboard ? "Copy to Clipboard" : "Select All"; + header.appendChild(btn); + + var btn = document.createElement("button"); + btn.setAttribute("type", "button"); + btn.addEventListener("click", function() { + document.body.classList.toggle("hide-line-numbers"); + }); + btn.textContent = "Toggle Line Numbers"; + header.appendChild(btn); + } + + /* // still sucks in firefox! + document.addEventListener("copy", function(event) { + document.body.classList.add("hide-line-numbers"); + }); + */ + + document.body.addEventListener("mouseover", function(event) { + if(event.target.hasAttribute("data-ident")) { + var all = document.querySelectorAll("[data-ident=\""+event.target.getAttribute("data-ident")+"\"]"); + for(var i = 0; i < all.length; i++) + all[i].className += " active"; + } + }); + document.body.addEventListener("mouseout", function(event) { + if(event.target.hasAttribute("data-ident")) { + var all = document.querySelectorAll("[data-ident=\""+event.target.getAttribute("data-ident")+"\"]"); + for(var i = 0; i < all.length; i++) + all[i].className = all[i].className.replace(" active", ""); + } + }); + /* + document.body.addEventListener("dblclick", function(event) { + if(event.target.hasAttribute("data-ident")) { + location.href = "/" + event.target.getAttribute("data-ident"); + } + }); + */ + + var sn = document.getElementById("source-navigation"); + if(sn) { + sn.addEventListener("click", function(event) { + if(event.target.tagName != "A" || event.target.className == "docs") + return true; + if(event.target.nextSibling) { + var s = event.target.nextSibling; + if(s.style.display == "" || s.style.display == "none" || s.className.indexOf("search-hit") != -1) { + s.style.display = "block"; + var items = s.getElementsByTagName("ul"); + var i; + for(i = 0; i < items.length; i++) + items[i].style.display = ""; + items = s.getElementsByTagName("li"); + for(i = 0; i < items.length; i++) + items[i].style.display = ""; + } else + s.style.display = ""; + } + + //var id = event.target.href.substring(event.target.href.indexOf("#") + 1); + //sn.style.marginTop = (document.getElementById(id).offsetTop - event.target.offsetTop + 16) + "px"; + }); + + var search = document.createElement("input"); + search.setAttribute("type", "search"); + function searchHelper() { + var regex = new RegExp(search.value, "i"); + var items = document.querySelectorAll("#source-navigation a[href^=\"#\"]"); + var stxt = search.value; + for(var i = 0; i < items.length; i++) { + var a = items[i]; + if(stxt.length && regex.test(a.textContent)) { + var p = a.parentNode; + while(p.tagName != "DIV") { + if(p.tagName == "LI") + p.style.display = "list-item"; + else + p.style.display = "block"; + p.className += " search-hit"; + p = p.parentNode; + } + } else { + var p = a.parentNode; + if(stxt.length == 0) { + p.style.display = ""; + while(p.tagName != "DIV") { + p.style.display = ""; + p = p.parentNode; + } + } else + p.style.display = "none"; + p.className = p.className.replace(" search-hit", ""); + } + } + } + search.addEventListener("keyup", searchHelper); + sn.insertBefore(search, sn.firstChild); + } + + /* + function updateDynamicStyle() { + var thing = document.getElementById("page-content"); + var newStyle = document.getElementById("dynamic-style"); + if(!newStyle) { + newStyle = document.createElement("style"); + newStyle.setAttribute("id", "dynamic-style"); + newStyle.type = "text/css"; + document.head.appendChild(newStyle); + } + + var maxContentWidth = window.innerWidth; + // 800 is the threshold for putting nav vertically + if(maxContentWidth < 800) + maxContentWidth = 800; + else + maxContentWidth = + document.body.offsetWidth - + document.getElementById("page-nav").offsetWidth - + document.getElementById("page-nav").offsetLeft - + 64; + + // sanity check lol + if(maxContentWidth < 800) + maxContentWidth = 800; + + newStyle.innerHTML = ".member-list:not(.constructors) dt .simplified-prototype:hover { width: " + (thing.offsetWidth - 32) + "px; } #page-content pre.d_code, #page-content .overload-option, #page-content .member-list dt { max-width: " + (maxContentWidth) + "px; }"; + } + + updateDynamicStyle(); + + window.onresize = updateDynamicStyle; + */ + + // Disable line numbers in IE because the copy/paste with them sucks - it includes all line numbers + // in the middle making it too hard to use. Copy/paste is more important than line displays. + if (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0) { + var items = document.querySelectorAll(".with-line-wrappers"); + for(var a = 0; a < items.length; a++) + items[a].className = items[a].className.replace("with-line-wrappers", ""); + } + + // Keybind to focus search bar on '?' keydown. + document.addEventListener("keydown", (event) => { + if (event.key == "?") { + var searchBox = document.getElementsByName("searchTerm")[0]; + // Hack so the '?' doesn't auto-populate in the search bar. + this.setTimeout(() => { + searchBox.focus(); + }, 100); + } + }); + + +}); diff --git a/search-docs.html b/search-docs.html new file mode 100644 index 00000000..522aab4a --- /dev/null +++ b/search-docs.html @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/search-docs.js b/search-docs.js new file mode 100644 index 00000000..11b29398 --- /dev/null +++ b/search-docs.js @@ -0,0 +1,421 @@ +/* + This is the source for offline web search; it will be embedded + in a generated search page along with the search index xml. + + You will almost certainly want to gzip this when delivering it! + Also be sure it has the proper cache headers to give a remotely + acceptable performance result. Configure the web server to do + both these. When storing it for offline usage, you might just + leave it unzipped though for convenience of use without a web server. + + Tip to the end user: you might want to open this page and keep it + open in a reused tab. + + The file generated should be the skeleton.html with the search + index in a + + + + + + +
+
+
+ +
+ + + + + diff --git a/style.css b/style.css new file mode 100644 index 00000000..d57e9480 --- /dev/null +++ b/style.css @@ -0,0 +1,1593 @@ +/* a few things you can change to pick a basic color scheme */ + +/* + FIXME: have some automatic magic for choosing light vs dark and picking an accent color. + + Ideally, we'll get to the point where you can just say: + project name + project logo + project links + + light/dark scheme + project color + + and it will adapt the rest to a good-enough state automatically. +*/ + +#page-header, +#suggestion-box { + background-color: rgb(49, 57, 176); + background-color: rgb(49, 110, 47); + background-color: rgb(176, 57, 49); +} + +#page-header, +#suggestion-box, +#page-footer, +#page-nav { + border-color: rgb(41, 48, 148); + border-color: rgb(41, 110, 48); + border-color: rgb(148, 48, 41); + border-color: rgb(204, 204, 204); +} + +#page-nav { + background-color: rgb(245, 245, 255); + background-color: rgb(245, 250, 245); + background-color: rgb(245, 245, 245); + +} + +a:link { + color: #0000ff; + color: #bb0000; +} + +a:visited { + color: #004488; + color: #bb0044; +} + +/* for the dlang.org website font thing */ + +@font-face { + font-family: "Roboto Slab"; + font-weight: normal; + src: url("RobotoSlab-Regular.ttf"); +} +@font-face { + font-family: "Roboto Slab"; + font-weight: bold; + src: url("RobotoSlab-Bold.ttf"); +} + +body { + font-family: "Roboto Slab", sans-serif; + tab-size: 4; +} + +h1, #page-nav a, .quickindex a.xref, .breadcrumb, dt > a { + font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace; +} + + +/* done with basic colors */ + +html { + font-size: 100%; +} + +h1 { + font-size: 2.2rem; +} + +h2 { + font-size: 1.6rem; + margin-top: 1.5em; + font-family: "Roboto Slab", sans-serif; + font-weight: normal; +} + +h3 { + font-size: 1.26rem; +} + +body { + /*font-family: sans-serif;*/ + color: #111; + background-color: white; +} + +.big-o { + white-space: nowrap; +} + +.member-list .dt, +.overload-option, +pre { + box-sizing: border-box; + overflow: auto; + max-width: 800px; /* The script sets the real one */ + max-width: calc(80vw - 16em - 4em); +} + + +#page-header { + height: 32px; + line-height: 32px; + margin-bottom: 6px; + border-bottom-width: 1px; + border-bottom-style: solid; + color: white; + margin: -0.5em; + padding: 0em 0.5em; + margin-bottom: 0.0em; + overflow: hidden; +} + +#page-header span { + vertical-align: top; +} + +#page-header #logotype { + float: left; +} + +#page-header #search { + float: right; +} + +#page-header nav { + display: inline-block; + margin-left: 2em; + vertical-align: top; +} + +#page-header nav a { + display: inline-block; + color: white; + font-weight: bold; + margin-right: 2em; +} + +#page-body { + clear: both; + margin: 0px auto; + max-width: 1200px; + min-height: 800px; + min-height: calc(100vh - 3em - 32px); + display: flex; + box-sizing: border-box; +} + +#page-body #page-nav { + flex: 0 0 16em; + width: 16em; + min-width: 16em; + max-width: 16em; + order: 1; + padding-top: 0.25em; + padding-left: 1em; + padding-right: 0px; + min-height: 800px; + min-height: calc(100vh - 3em - 32px); + + border-right-style: solid; + border-right-width: 1px; + border-left-style: solid; + border-left-width: 1px; + box-sizing: border-box; +} + +#page-body #page-content { + flex: 1 1 auto; + order: 2; + padding: 0.25em; + padding-left: 1.75em; + box-sizing: border-box; + max-width: 960px; +} + +@media all and (max-width: 800px) { + #page-body { + display: block; + min-height: 0px; + } + + #page-body #page-nav { + display: block; + width: auto; + max-width: 800px; + border-top-style: solid; + border-top-width: 1px; + border-right: none; + min-height: 0px; + } + + #page-body #page-content { + padding-left: 0.25em; + } + + .member-list .dt, + .overload-option, + pre { + box-sizing: border-box; + overflow: auto; + max-width: 800px; /* The script sets the real one */ + max-width: calc(100vw - 2em); + } + + #page-header { + line-height: 20px; + height: auto; + min-height: 32px; + overflow: visible; + } + #page-header::after { + content: ' '; + display: block; + clear: both; + } +} + +#page-footer { + margin-top: 0em; + padding-top: 2em; + color: #999; + font-size: 0.9rem; + text-align: center; + border-top-style: solid; + border-top-width: 1px; +} + +a:link { + text-decoration: none; +} + +a:link:hover { + text-decoration: underline !important; /* important so it overrides even id level things on non-hover */ +} + +/* +pre.d_code { background-color: #fdf6e3; color: #002b36; padding: 0.25em; border: solid 1px #ccc; } +.d_code .kwrd { color: #b58900; font-weight: bold; } +.d_code .com { color: #666; font-style: italic; } +.d_code .num { color: #dc322f; font-weight: normal; } +.d_code .str { color: #2aa198; font-style: italic; } +.d_code .op { color: #586e75; font-weight: bold; } +.d_code .type { color: #268bd2; font-weight: bold; } +.d_code .cons { color: #859900; font-weight: bold; } + +.highlighted .kwrd { color: #b58900; font-weight: bold; } +.highlighted .com { color: #666; font-style: italic; } /* #93a1a1; * / +.highlighted .num { color: #dc322f; font-weight: normal; } +.highlighted .str { color: #2aa198; font-style: italic; } +.highlighted .op { color: #586e75; font-weight: bold; } +.highlighted .type { color: #268bd2; font-weight: bold; } +.highlighted .cons { color: #859900; font-weight: bold; } +*/ + +/* .member-list p, */ +#table-of-contents, +.enum-members, +.documentation-comment .tip, +.documentation-comment .note, +.documentation-comment .warning, +.documentation-comment .pitfall, +.documentation-comment li, +.documentation-comment p { + /* white-space: pre-line; */ + /* max-width: 74ch; */ + /*font-size: 1.1rem;*/ + font-size: 1.0rem; + line-height: 1.5; +} + +/* +.parameter-item::after { + content: ','; +} + +.parameter-item:last-child::after { + content: ''; +} +*/ + +.aggregate-declaration { + margin: 1em; +} + +.aggregate-member { + padding-left: 2em; +} + +/* +.aggregate-member::after { + content: ";"; +} +*/ + +.aggregate-member > a { + color: inherit; +} + +.template-constraint-expression, +.parameter-item { + padding-left: 2em; +} + + +/* +ol.overloads { + margin-bottom: -1px; + white-space: nowrap; +} + +ol.overloads::before { + content: "Overloads: "; +} + +ol.overloads li { + display: inline-block; + border: solid 1px #ccc; + list-style-position: inside; + text-align: center; + width: 5em; +} + +ol.overloads li.overload-option { + background-color: #eee; +} + +ol.overloads li a { + display: block; +} + +ol.overloads li.active-overload-option { + border-bottom: solid 1px white; +} + +ol.overloads + .aggregate-prototype, +ol.overloads + .function-prototype { + margin-top: 0px; +} +*/ + +.aggregate-prototype #help-link, +.function-prototype #help-link { + border-radius: 100%; + position: absolute; + top: -0.5em; + right: -0.5em; + display: block; + border: solid 1px #ccc; + background-color: white; + width: 1em; + height: 1em; + text-align: center; + font-size: 1.1rem; + padding-bottom: 3px; +} + +.aggregate-prototype #help-link:hover, +.function-prototype #help-link:hover { + text-decoration: none; + background-color: #ccc; +} + +.function-prototype .attributes { + color: #666; +} + +.declaration-prototype, +.aggregate-prototype, +.function-prototype { + border: solid 1px #ccc; + padding: 2em; + margin: 1em; + font-family: monospace; + position: relative; +} + +.declaration-prototype { + padding: 3em 2em; +} + +.parameters-list:empty { + display: none; +} + +/* +.parameters-list .parameters-list { + display: inline; +} +*/ + +.toplevel.parameters-list { + display: table; +} + +.toplevel.parameters-list > .parameter-item { + display: table-row; +} + +.toplevel.parameters-list > .parameter-item > *:first-child { + padding-left: 2em !important; +} + +.toplevel.parameters-list > .parameter-item + .comma { + display: none; +} + +.toplevel.parameters-list > .parameter-item > *:last-child::after { + content: ","; +} +.toplevel.parameters-list > .parameter-item:last-of-type > *:last-child::after { + content: ""; +} + +.parameter-attribute { + padding-left: 1em; +} + +.toplevel.parameters-list > .parameter-item .parameter-type-holder, +.toplevel.parameters-list > .parameter-item .parameter-name, +.toplevel.parameters-list > .parameter-item .parameter-default-value { + display: table-cell; + padding: 0px 0.25em; +} + +.toplevel.parameters-list > .parameter-item:hover { + background-color: #f8f8f8; +} + +.parameter-descriptions .parameter-name { + margin-right: 1.5rem; + font-weight: bold; + padding: 0.25ex 0.75ex; +} + +.parameter-descriptions dd { + margin-left: 1.5em; +} + +.parameter-descriptions dd p:first-child { + margin-top: 0.5em; +} + +.parameter-descriptions dt:not(:first-child) { + margin-top: 1.5em; +} + +.codeblock { + border: solid 1px #ccc; + padding: 0; + margin: 0; +} + +.codeblock header { + background-color: #e8e8e8; + padding: 0; + display: flex; + justify-content: flex-end; +} + +.codeblock header:before { + display: inline-block; + content: "Example"; + justify-content: flex-start; + flex-grow: 1; + padding: 0.25em 1em; + font-weight: bold; +} + +.codeblock header button { +/* TODO: add :before class with icons here (copy, line numbers) */ + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + margin: 0; + padding: 0 1em; + background-color: transparent; + border: none; + border-left: 1px solid #ccc; + cursor: pointer; +} + +.codeblock header button:hover { + background-color: rgba(255, 255, 255, 0.5); +} + +.codeblock header + pre { + border: none; + border-top: solid 1px #ccc; + margin: 0; + padding: 1em 0; + max-width: unset !important;; +} + +.hide-line-numbers .codeblock .with-line-wrappers, +.codeblock pre.d_code:not(.with-line-wrappers) { + padding: 1em; +} + +.codeblock .with-line-wrappers .br { + margin-right: 1em; +} + +.documentation-comment p { + hyphens: auto; +} + +.declaration-prototype, .aggregate-prototype, .function-prototype { + margin-left: 0; + margin-right: 0; +} + + + +tt.D, .inline-code { + color: black; + font-weight: 500; + background-color: #f2f2f2; + padding: 0px 0.5ex; + border-radius: 2px; +} + + +/* +.toplevel.parameters-list > .parameter-item > .parameter-type-holder { + text-align: right; +} + +.toplevel.parameters-list > .parameter-item > .parameter-type-holder > .parameter-type { + text-align: left; + display: inline-block; +} +*/ + +.function-prototype .return-type, .function-prototype .function-name { + display: inline; +} + +.function-name::before { + content: ' '; +} + +.function-name { + /*color: #008888;*/ +} + +.template-parameters[data-count="0"], +.template-parameters[data-count="0"] ~ .runtime-parameters[data-count="0"], +.template-parameters[data-count="0"] ~ .runtime-parameters[data-count="0"] > .parameters-list { + display: inline; +} + +.parameters-list:empty { + display: inline; +} + +.type-constructor, +.builtin-type { + text-decoration: none; + color: #004400 !important; + /*color: green !important; + font-weight: bold;*/ +} + +.kwrd, +.highlighted-keyword, +.lang-feature, +.storage-class { + text-decoration: none; + color: #026 !important; +} + +[data-ident].active { + outline: solid 1px red; +} + +table.enum-members { + border-collapse: collapse; + border: solid 1px #ccc; + min-width: 60%; +} + +.enum-members th, +.enum-members td { + border: solid 1px #ccc; + margin: 0px; + padding: 0.25em 0.5em; +} + +.enum-members th { + text-align: left; + color: #888; +} + +.enum-members td { + vertical-align: top; +} + +.enum-members td p:first-child { + margin-top: 0px; +} + +.enum-members .enum-member-name { + font-weight: bold; + color: inherit; +} + +.enum-members .enum-member-value { + display: block; + color: #666; +} + +.enum-members .enum-disabled { + font-style: italic; +} + +.enum-members .enum-deprecated { + margin-bottom: 1em; +} + +.enum-members .enum-deprecated > span.deprecated-label { + color: red; +} + +.enum-members .enum-attributes { + margin-top: 1em; +} + +.enum-member .enum-attributes:empty { + display: none; +} + +.enum-members tr.enum-member > td:nth-child(2) > div:only-child:empty:before { + display: inline; + content: "undocumented"; + color: rgba(0, 0, 0, 0.4); + font-style: italic; +} + +*:target { + background: #ffffbb; +} + +.breadcrumbs { + margin: 1em; +} + +.breadcrumbs a::before { + content: ' \00bb\a0'; +} + +.parameter-name { + font-weight: bold; +} + +.symbol-reference, +.return-type, +.parameter-type { + font-family: monospace; +} + +.phobos-booktable { + border-collapse: collapse; + margin-bottom: 1.5em; +} + +.phobos-booktable tt.D { + font-weight: bold; + background-color: transparent; +} + +.phobos-booktable caption { + text-align: left; +} + +.phobos-booktable tr { + border-bottom: solid 1px #ccc; +} + +.phobos-booktable tr:hover { + background-color: #fafafa; +} + +.phobos-booktable { + border-top: solid 2px black; + border-bottom: solid 2px black; +} + +.phobos-booktable tr:first-child:has(th) { + border-bottom: solid 1px black; +} + +.phobos-booktable th { + text-align: left; + padding-top: 0.3em; + padding-bottom: 0.3em; +} + +.phobos-booktable td:first-child { + padding-top: 0.3em; + padding-bottom: 0.3em; + padding-right: 1em; +} + +.phobos-booktable td:not(:last-child), +.phobos-booktable th:not(:last-child) { + padding-right: 1em; +} + +.quickindex .phobos-booktable td:last-child a { + padding-right: 1.2em; +} + +.current.breadcrumb { + color: inherit; + text-decoration: none; +} + +.andand-right { + display: inline; +} + +.oror-right { + display: inline; +} + +.parenthetical-expression > .parenthetical-expression-contents > .andand-left, +.parenthetical-expression > .parenthetical-expression-contents > .oror-left { + display: inline; +} + +/* +.parenthetical-expression > .parenthetical-expression-contents > .oror-left:first-child { + display: block; +} +*/ + + +.template-constraint-expression .parenthetical-expression { + display: block; + margin-left: 1em; +} + +.oror-left > .andand-left, +.oror-left > .andand-right { + display: inline; +} + +.aggregate-members:empty::after { + content: "This aggregate has no documented members available."; +} + +h1 .entity-name { + font-family: monospace; +} + +.other-section h3 { + font-size: 1rem; + margin-bottom: 0.25em; +} + +.other-section h3 + p { + margin-top: 0.25em; +} + +.function-prototype .in-contract, +.function-prototype .out-contract { + display: none; + white-space: pre; +} + +.note { + margin: 1em; + padding: 0.5em; + background-color: #f0f0ff; + border: solid 1px #ccc; + clear: both; +} + +/* +.note::before { + color: #000066; + font-weight: bold; + content: "Note: "; +} +*/ + +.warning { + margin: 1em; + padding: 0.5em; + background-color: #fffff0; + border: solid 1px #ccc; + clear: both; +} + +.pitfall { + margin: 1em; + padding: 0.5em; + background-color: #fff0f0; + border: solid 1px #ccc; + clear: both; +} + +.tip { + margin: 1em; + padding: 0.5em; + background-color: #f0fff0; + border: solid 1px #ccc; + clear: both; +} + +.sidebar { + float: right; + margin: 1em; + margin-top: 2px; + padding: 0.25em; + background: #f3f3f3; + border: solid 1px #ccc; + width: 20%; + min-width: 30ch; + clear: right; +} + +h2 { + clear: both; +} + +.sidebar > *:first-child { + margin-top: 0px; +} + +/* I want to clear floats. This leaves a gap about the size of a blank line + too, but that doesn't bother me (actually, I kinda like a small gap at the + bottom. */ +#page-content::after { + clear: both; + content: '\a0'; + display: block; +} + +tt.D, +.inline-code { + color: black; + font-weight: 500; + background-color: #f2f2f2; + padding: 0px 0.125em; +} + +#page-nav .type-separator { + text-transform: capitalize; + display: block; + border-bottom: solid 1px #ccc; + margin-top: 1em; + margin-bottom: 0.25em; +} + +#page-nav a { + display: block; + box-sizing: border-box; + padding: 1px 0.25em 1px 0.5em; + text-overflow: ellipsis; + overflow: hidden; + font-family: "Roboto Slab", sans-serif; +} + +#page-nav a:hover { + position: relative; + overflow: visible; + z-index: 10; + background-color: rgb(245, 245, 245); + width: max-content; +} + +#page-nav a.parent { + font-weight: bold; + font-size: 1.1rem; + line-height: 0.9; + overflow: visible; +} + +#page-nav a.parent:first-child { + margin-top: 0.75em; +} + +#page-nav a.parent + a.parent::before { + content: "."; +} + +#page-nav a.current { + font-weight: bold; + color: inherit; +} + +pre[data-language=console], +pre.console { + background-color: #222; + color: #eee; + padding: 0.5em; + border: solid 1px #ccc; +} + +#more-link { + display: block; + font-weight: bold; + font-size: 1.1rem; + color: blue; +} + +.member-list dd + dt { + border-top: solid 1px #ccc; + padding-top: 0.5em; + margin-top: 0.5em; +} + +/* +.member-list dd { + max-height: 4em; + overflow: hidden; + text-overflow: ellipsis; +} +*/ + +.member-list dt a { + overflow: hidden; + text-overflow: ellipsis; +} + +.member-list dt .simplified-prototype { + font-family: monospace; + font-size: 90%; + color: #333; + white-space: nowrap; + text-overflow: ellipsis; + text-overflow: '[...]'; /* only Firefox supports this but i like it */ + overflow: hidden; + border: solid 1px white; +} + +.member-list dt .simplified-prototype:hover { + background-color: white; + position: relative; + z-index: 5; + width: 800px; + width: calc(100vw - 16em); + border: solid 1px #eee; + box-shadow: 1px 1px 1px #ccc; +} + +@media screen and (min-width: 640px) { + .member-list dt { + float: left; + clear: left; + width: 20em; + box-sizing: border-box; + padding-right: 1em; + } + + .member-list dd, + .member-list dd + dt { + border-top: solid 1px #ccc; + padding-top: 0.5em; + margin-top: 0em; + } + + .member-list dd p:first-child { + margin-top: 0px; + } + + .member-list dd:first-of-type { + border-top: none; + padding-top: 0px; + } + + .member-list dd { + margin: 0px; + margin-left: 20em; + } + + .member-list dd::after { + content: '\a0'; + height: 0.5em; + clear: both; + display: block; + } +} + +.member-list.articles dt, +.member-list.constructors dt { + float: none; + clear: none; + margin: 0em; + width: auto; + border: none; +} + +.member-list.articles dd, +.member-list.constructors dd { + float: none; + clear: none; + margin: 1em 0em; + width: auto; + border: none; +} + +.member-list.articles dd, +.member-list.constructors dd { + padding-left: 2em; +} + +.member-list dt a { + display: block; +} + +#suggestion-box { + display: inline-block; + color: white; + font-weight: bold; + border: solid 2px black; + border-radius: 8px 8px 0px 0px; + position: fixed; + left: 1em; + bottom: 0em; + padding: 0.25em 0.5em; +} + +.synopsis { + margin: 2em 0px; +} + +/* If it was successfully looked up in an xref, no need to highlight anymore */ +a.xref:link span[data-ident].active { + border: none; +} + +#table-of-contents { + border: solid 1px #ccc; + margin: 1em; + padding: 1em; + padding-left: 0em; /* the list inside can handle this */ +} + +.parent-prototype { + font-size: 0.9rem; + padding-bottom: 1em; +} + +.parent-prototype::after { + content: " {"; +} + +.parent-prototype + div { + padding-left: 1em; +} + +.parent-prototype + div::after { + content: "}"; + display: block; + font-size: 0.9rem; + padding-top: 1em; + margin-left: -1.33em; /* 1/(3/4) */ +} + +.search-result::after { + content: '(Search Score: ' attr(data-score) ')'; + font-size: 0.9rem; +} + +table.std_math { + min-width: 25%; + border: solid 1px black; + border-collapse: collapse; + margin: 2em; +} + +table.std_math td, table.std_math th { + border: solid 1px #ccc; + text-align: left; + padding: 0.25em; +} + +table.std_math.special-values th { + border-bottom: solid 2px #000; +} + +table.std_math.special-values caption { + text-align: left; + font-weight: 700; +} + +.nan { + font-family: monospace; + color: red; +} + +.overload-option, +.overload-signature { + font-family: monospace; +} + +.block-code, +.d_code, +.annotated-prototype { + font-size: 1rem; +} + +.annotated-prototype .overloads { + display: block; + padding: 0px; +} + +.annotated-prototype .overloads li { + display: block; + width: auto; + padding: 0em 0.5em; + text-align: left; + overflow: hidden; + + margin: 0; +} + +.member-list .dt, .overload-option, pre { + max-width: unset; +} + +.annotated-prototype .overloads li.active-overload-option { + border: ridge 2px #ccc; +} + +.annotated-prototype .overloads li.active-overload-option .overload-signature { + white-space: nowrap; + border-bottom: dotted 1px #999; + display: block; +} + +.annotated-prototype .overloads li.overload-option { + border: solid 1px #ccc; + background-color: #eee; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.annotated-prototype .overloads li.ditto-option::before, +.annotated-prototype .overloads li.active-overload-option .overload-signature::before, +.annotated-prototype .overloads li.overload-option::before { + display: inline-block; + width: 6em; + width: 9ch; + font-size: 0.9rem; + vertical-align: baseline; +} + +.annotated-prototype .overloads li.overload-option::before { + content: "Overload: "; +} + +.annotated-prototype .overloads li.active-overload-option .overload-signature::before { + content: "Viewing: "; +} + +.annotated-prototype .overloads li.ditto-option::before { + content: "Related: "; +} + +.annotated-prototype li .declaration-prototype, +.annotated-prototype li .aggregate-prototype, +.annotated-prototype li .function-prototype { + border: none; + padding: 0px; +} + +.annotated-prototype li .declaration-prototype { + padding: 2em 0px; +} + +#page-nav ul { + margin: 0px; + padding: 0px; + list-style: none; +} + +.parameter-name > a[href^="#"], +a.parameter-name[href^="#"] { + color: inherit; +} + + + +/* adrdox special syntax styles */ + +.small-table { + border-collapse: collapse; + min-width: 10em; +} + +.small-table td, +.small-table th { + border: solid 1px #ccc; + padding: 0.25em; +} + +.small-table thead th { + border-bottom: solid 2px #999; +} + +.small-table tbody th, +.small-table.two-axes thead th:first-child { + border-right: solid 2px #999; +} + +.small-table.two-axes td, +.small-table.two-axes th { + text-align: center; + vertical-align: middle; +} + +.adrdox-sample { + display: table; + width: 100%; +} + +.adrdox-sample > div { + display: table-row; +} + +.adrdox-sample > div > * { + display: table-cell; + width: 50%; + vertical-align: top; + border-bottom: dashed 1px #ccc; + padding: 0.25em; + padding-bottom: 0.5em; +} + +.adrdox-sample > div > pre { + border-right: dashed 1px #ccc; +} + +.adrdox-sample > div > pre::before, +.adrdox-sample > div > div::before { + display: block; + font-style: italic; + border-bottom: dashed 1px #ccc; + margin-bottom: 0.5em; + font-family: sans-serif; + font-size: 1rem; + padding: 0px; +} + +.adrdox-sample > div > pre::before { + content: 'Doc source:'; +} +.adrdox-sample > div > div::before { + content: 'Rendered:'; +} + +blockquote { + margin: 1em; + padding: 1em; + border-left: 0.5em solid #ccc; + color: #333; +} + +pre.d_code, +.block-code:not([data-language=""]):not([data-language="pre"]) { + background-color: #fcfcfc; + padding: 0.25em; + border: solid 1px #ccc; + position: relative; +} + +.block-code:not([data-language=""]):not([data-language="pre"])::before { + content: attr(data-language); + display: block; + text-transform: capitalize; + font-size: 0.9rem; + padding: 0px 2px; + border: solid 1px #999; + border-top: none; + border-radius: 0px 0px 0.25em 0.25em; + background-color: #f0f0f0; + float: right; + margin: 0px; + margin-top: -0.25em; + margin-top: calc(-0.25em - 1px); +} +.type, +.highlighted-type { + color: green; + /* font-weight: bold; */ +} +.num, +.highlighted-number { + color: #dc322f; +} +.str, +.highlighted-string { + color: red; +} +.com, +.highlighted-comment { + color: blue; +} +.highlighted-preprocessor-directive { + color: #cd00cd; +} +.highlighted-identifier, +.highlighted-tag { + color: #008888; +} +.highlighted-tag-name { + color: #859900; +} +.highlighted-entity { + color: #cd00cd; + text-decoration: none; + cursor: help; +} +.highlighted-named-constant, +.highlighted-attribute-name { + color: green; +} +.highlighted-attribute-value { + color: red; +} +.highlighted-python-indent { + background: linear-gradient(to right, #eee, transparent 3px) no-repeat; +} +.highlighted-python-indent:hover { + background: linear-gradient(to right, #ccc, transparent 3px) no-repeat; +} + +/* +.with-line-wrappers { + counter-reset: line_numbers; +} + +.with-line-wrappers span.br { + counter-increment: line_numbers; +} + +.with-line-wrappers span.br::before { + content: counter(line_numbers); +*/ +.with-line-wrappers .br { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + width: 3em; + width: 4ch; + display: inline-block; + color: #999; + border-right: solid 2px #ccc; + padding: 0px; + margin: 0px; + margin-right: 3px; + padding-right: 3px; + font-style: normal; + font-weight: normal; + background-color: transparent; + text-align: right; + white-space: pre; +} + +.hide-line-numbers .with-line-wrappers .br { + display: none; +} +.with-line-wrappers .br:target { + background: #ffffbb; +} + +.thousand-lines.with-line-wrappers .br { + width: 4em; + width: 5ch; +} +.ten-thousand-lines.with-line-wrappers .br { + width: 5em; + width: 6ch; +} + +#source-navigation { + position: fixed; + width: 15.5em; +} + +#source-navigation .list-holder { + width: 100%; + overflow: auto; + max-height: 80vh; +} + +#source-navigation .list-holder ul { + padding-left: 1em; +} + +/* hide nested decls as it is too much... */ +#source-navigation .list-holder ul > li > ul { + display: none; +} + +/* ...but show top-level decls under the module cuz no reason not to */ +#source-navigation .list-holder > ul > li > ul { + display: block; +} + +#source-navigation li { + white-space: nowrap; +} + +#source-navigation a { + display: inline; +} + +.postcondition { + color: blue; + font-family: monospace; + font-size: 0.9rem; +} +.postcondition::before { + content: "Post: "; + font-style: italic; + color: black; +} + +.user-table { + border-top: solid 2px black; + border-collapse: collapse; +} + +.user-table tr:nth-of-type(1) th { + border-bottom: solid 1px black; + text-align: left; +} + +.user-table td { + border-bottom: solid 1px #ccc; + vertical-align: top; + padding: 4px; +} +.user-table th { + padding: 4px; +} + +.user-table.two-axes tr + tr th:first-child { + border-bottom: solid 1px #ccc; +} + +.user-table.two-axes th:first-child { + border-right: solid 1px black; + text-align: right; +} + +.allocator-table td:first-child tt { + background-color: transparent; + white-space: nowrap; + font-weight: bold; +} + +.header-anchor { + color: inherit !important; +} + +#members + h3, +.member-list + h3, +h3.member-list-header { + border-bottom: solid 1px #333; + text-transform: capitalize; +} + +#members + h4, +.member-list + h4, +h4.member-list-header { + font-weight: normal; + text-transform: capitalize; + text-decoration: underline; +} + + +tr.leading-row th { + border-bottom: solid 2px black; +} + +.lambda-expression * { + display: inline !important; + padding: 0px !important; + margin: 0px !important; +} + +.footnote-ref a {} +.footnote-ref abbr { + font-variant: none; + text-decoration: none; + cursor: help; +} + +.side-by-side { + table-layout: fixed; + border: none; + width: 100%; +} + +.side-by-side > tbody > tr > td { + vertical-align: top; +} + +/* +tt.D { + font-weight: bold; + background: transparent; + color: inherit; +} +*/ + +tt.D.highlighted *:not(a) { + font-weight: inherit; + color: inherit; +} +tt.D.highlighted a { + color: #500000; +} + +.date-posted { + font-size: 0.9rem; + font-style: italic; +} + +.token-string-literal { + font-style: italic; +} +.token-string-literal:hover { + background-color: rgba(255, 0, 0, 0.05); +} + +.specially-highlighted { + background-color: yellow; + background-color: rgba(255, 255, 0, 0.5); +} + +.console .specially-highlighted { + background-color: rgba(255, 255, 0, 1.0); + color: black; +} + +.quickindex { + background: #f5f5f5; + max-width: 760px; +} + +.quickindex .phobos-booktable { + width: 100%; +} + +.leading-row { + font-style: italic; + background-color: rgb(228, 233, 239); +} + +.leading-row th { + padding-left: 1.5em; +} + +.quickindex td, .quickindex th { + padding-left: 0.3em; +} + +.undocumented-note { + color: #999; +} + +.deprecated-decl { + color: #c00; + font-weight: bold; +} + +.conditional-compilation-attributes { + font-size: 90%; +}