#!/usr/bin/env dub
/+ dub.sdl:
name "gen-wired-inline"
+/
/**
Generates the `wired-inline` bench engine's single-translation-unit copy of
the native JSON reader.
The wired-native hot path is built from templates (`parseJsonDocument` →
`parseInto` → `scanNumber`), so it is code-generated in whichever package
*instantiates* it — here the benchmark package, which cannot enable
`-enable-cross-module-inlining` (it would propagate to mir-ion and cull a
template-nested symbol). The consequence is visible in the disassembly: even
`doubleToBits`, a single `movq`, is emitted as a `call` into `sparkles:base`.
This tool splices the six modules that make up that path into one module, so
every seam is intra-module and LDC's inliner sees the whole kernel at once.
That isolates the value of inlining from the build-system variables
(cross-module inlining, ThinLTO, PGO) that could not be evaluated cleanly.
Nothing under `libs/base` or `libs/wired` is modified — this is a copy, and
the copy is what the `wired-inline` engine measures. Re-run after changing any
source module so the two engines stay comparable:
dub run --single tools/gen-wired-inline.d
*/
module (module) gen_wired_inlineGenerates the wired-inline bench engine's single-translation-unit copy of
the native JSON reader.
The wired-native hot path is built from templates (parseJsonDocument →
parseInto → scanNumber), so it is code-generated in whichever package
instantiates* it — here the benchmark package, which cannot enable
-enable-cross-module-inlining (it would propagate to mir-ion and cull a
template-nested symbol). The consequence is visible in the disassembly: even
doubleToBits, a single movq, is emitted as a call into sparkles:base.
This tool splices the six modules that make up that path into one module, so
every seam is intra-module and LDC's inliner sees the whole kernel at once.
That isolates the value of inlining from the build-system variables
(cross-module inlining, ThinLTO, PGO) that could not be evaluated cleanly.
Nothing under libs/base or libs/wired is modified — this is a copy, and
the copy is what the wired-inline engine measures. Re-run after changing any
source module so the two engines stay comparable:
dub run --single tools/gen-wired-inline.d
gen_wired_inline;
import (package) stdstd.(package) std.algorithmalgorithm.(module) std.algorithm.searchingThis is a submodule of std.algorithm.
It contains generic searching algorithms.
Function Name Description all all!"a > 0"([1, 2, 3, 4]) returns true because all elements are positive any any!"a > 0"([1, 2, -3, -4]) returns true because at least one element is positive balancedParens balancedParens("((1 + 1) / 2)", '(', ')') returns true because the string has balanced parentheses. boyerMooreFinder find("hello world", boyerMooreFinder("or")) returns "orld" using the Boyer-Moore algorithm. canFind canFind("hello world", "or") returns true. count Counts all elements or elements matching a predicate, specific element or sub-range.
count([1, 2, 1]) returns 3,
count([1, 2, 1], 1) returns 2 and
count!"a < 0"([1, -3, 0]) returns 1. |
| countUntil | countUntil(a, b) returns the number of steps taken in a to reach b; for example, countUntil("hello!", "o") returns 4. |
| commonPrefix | commonPrefix("parakeet", "parachute") returns "para". |
| endsWith | endsWith("rocks", "ks") returns true. |
| extrema | extrema([2, 1, 3, 5, 4]) returns [1, 5]. |
| find | find("hello world", "or") returns "orld" using linear search. (For binary search refer to SortedRange.) |
| findAdjacent | findAdjacent([1, 2, 3, 3, 4]) returns the subrange starting with two equal adjacent elements, i.e. [3, 3, 4]. |
| findAmong | findAmong("abcd", "qcx") returns "cd" because 'c' is among "qcx". |
| findSkip | If a = "abcde", then findSkip(a, "x") returns false and leaves a unchanged, whereas findSkip(a, "c") advances a to "de" and returns true. |
| findSplit | findSplit("abcdefg", "de") returns a tuple of three ranges "abc", "de", and "fg". |
| findSplitAfter | findSplitAfter("abcdefg", "de") returns a tuple of two ranges "abcde" and "fg". |
| findSplitBefore | findSplitBefore("abcdefg", "de") returns a tuple of two ranges "abc" and "defg". |
| minCount | minCount([2, 1, 1, 4, 1]) returns tuple(1, 3). |
| maxCount | maxCount([2, 4, 1, 4, 1]) returns tuple(4, 2). |
| minElement | Selects the minimal element of a range. minElement([3, 4, 1, 2]) returns 1. |
| maxElement | Selects the maximal element of a range. maxElement([3, 4, 1, 2]) returns 4. |
| minIndex | Index of the minimal element of a range. minIndex([3, 4, 1, 2]) returns 2. |
| maxIndex | Index of the maximal element of a range. maxIndex([3, 4, 1, 2]) returns 1. |
| minPos | minPos([2, 3, 1, 3, 4, 1]) returns the subrange [1, 3, 4, 1], i.e., positions the range at the first occurrence of its minimal element. |
| maxPos | maxPos([2, 3, 1, 3, 4, 1]) returns the subrange [4, 1], i.e., positions the range at the first occurrence of its maximal element. |
| skipOver | Assume a = "blah". Then skipOver(a, "bi") leaves a unchanged and returns false, whereas skipOver(a, "bl") advances a to refer to "ah" and returns true. |
| startsWith | startsWith("hello, world", "hello") returns true. |
| until | Lazily iterates a range until a specific value is found. |
Source
std/algorithm/searching.d
searching : (alias template) gen_wired_inline.canFind = std.algorithm.searching.canFind(alias pred = "a == b")Convenience function. Like find, but only returns whether or not the search
was successful.
For more information about pred see find.
canFind, (alias template) gen_wired_inline.startsWith = std.algorithm.searching.startsWith(alias pred = (a, b) => a == b, Range, Needles...)(Range doesThisStart, Needles withOneOfThese) if (isInputRange!Range && (Needles.length > 1) && allSatisfy!(canTestStartsWith!(pred, Range), Needles))Checks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith;
import (package) stdstd.(module) std.arrayFunctions and types that manipulate built-in arrays and associative arrays.
This module provides all kinds of functions to create, manipulate or convert arrays:
Function Name Description
| array |
Returns a copy of the input in a newly allocated dynamic array.
|
| appender |
Returns a new Appender or RefAppender initialized with a given array.
|
| assocArray |
Returns a newly allocated associative array from a range/ranges of keys and values.
|
| byPair |
Construct a range iterating over an associative array by key/value tuples.
|
| insertInPlace |
Inserts into an existing array at a given position.
|
| join |
Concatenates a range of ranges into one array.
|
| minimallyInitializedArray |
Returns a new array of type T.
|
| replace |
Returns a new array with all occurrences of a certain subrange replaced.
|
| replaceFirst |
Returns a new array with the first occurrence of a certain subrange replaced.
|
| replaceInPlace |
Replaces all occurrences of a certain subrange and puts the result into a given array.
|
| replaceInto |
Replaces all occurrences of a certain subrange and puts the result into an output range.
|
| replaceLast |
Returns a new array with the last occurrence of a certain subrange replaced.
|
| replaceSlice |
Returns a new array with a given slice replaced.
|
| replicate |
Creates a new array out of several copies of an input array or range.
|
| sameHead |
Checks if the initial segments of two arrays refer to the same
place in memory.
|
| sameTail |
Checks if the final segments of two arrays refer to the same place
in memory.
|
| split |
Eagerly split a range or string into an array.
|
| staticArray |
Creates a new static array from given data.
|
| uninitializedArray |
Returns a new array of type T without initializing its elements.
|
Source
std/array.d
array : (alias template) gen_wired_inline.appender = std.array.appender(A)() if (isDynamicArray!A)Convenience function that returns an Appender instance,
optionally initialized with array.
appender, (alias template) gen_wired_inline.join = std.array.join(RoR, R)(RoR ror, R sep) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)) && isInputRange!R && (is(immutable(ElementType!(ElementType!RoR)) == immutable(ElementType!R)) || isSomeChar!(ElementType!(ElementType!RoR)) && isSomeChar!(ElementType!R)))Eagerly concatenates all of the ranges in ror together (with the GC)
into one array using sep as the separator if present.
join;
import (package) stdstd.(module) std.fileUtilities for manipulating files and scanning directories. Functions
in this module handle files as a unit, e.g., read or write one file
at a time. For opening files and manipulating them via handles refer
to module std.stdio.
Category Functions General exists isDir isFile isSymlink rename thisExePath Directories chdir dirEntries getcwd mkdir mkdirRecurse rmdir rmdirRecurse tempDir Files append copy read readText remove slurp write Symlinks symlink readLink Attributes attrIsDir attrIsFile attrIsSymlink getAttributes getLinkAttributes getSize setAttributes Timestamp getTimes getTimesWin setTimes timeLastModified timeLastAccessed timeStatusChanged Other DirEntry FileException PreserveAttributes SpanMode getAvailableDiskSpace
Source
std/file.d
file : (alias template) gen_wired_inline.readText = std.file.readText(S = string, R)(auto ref R name) if (isSomeString!S && (isSomeFiniteCharInputRange!R || is(StringTypeOf!R)))Reads and validates (using validate) a text file. S can be
an array of any character type. However, no width or endian conversions are
performed. So, if the width or endianness of the characters in the given
file differ from the width or endianness of the element type of S, then
validation will fail.
readText, (alias template) gen_wired_inline.write = std.file.write(R)(R name, const void[] buffer) if ((isSomeFiniteCharInputRange!R || isSomeString!R) && !isConvertibleToString!R)Write buffer to file name.
Creates the file if it does not already exist.
write;
import (package) stdstd.(module) std.pathThis module is used to manipulate path strings.
All functions, with the exception of expandTilde (and in some
cases absolutePath and relativePath), are pure
string manipulation functions; they don't depend on any state outside
the program, nor do they perform any actual file system actions.
This has the consequence that the module does not make any distinction
between a path that points to a directory and a path that points to a
file, and it does not know whether or not the object pointed to by the
path actually exists in the file system.
To differentiate between these cases, use isDir and
exists.
Note that on Windows, both the backslash (\) and the slash (/)
are in principle valid directory separators. This module treats them
both on equal footing, but in cases where a new separator is
added, a backslash will be used. Furthermore, the buildNormalizedPath
function will replace all slashes with backslashes on that platform.
In general, the functions in this module assume that the input paths
are well-formed. (That is, they should not contain invalid characters,
they should follow the file system's path format, etc.) The result
of calling a function on an ill-formed path is undefined. When there
is a chance that a path or a file name is invalid (for instance, when it
has been input by the user), it may sometimes be desirable to use the
isValidFilename and isValidPath functions to check
this.
Most functions do not perform any memory allocations, and if a string is
returned, it is usually a slice of an input string. If a function
allocates, this is explicitly mentioned in the documentation.
Category Functions Normalization absolutePath asAbsolutePath asNormalizedPath asRelativePath buildNormalizedPath buildPath chainPath expandTilde Partitioning baseName dirName dirSeparator driveName pathSeparator pathSplitter relativePath rootName stripDrive Validation isAbsolute isDirSeparator isRooted isValidFilename isValidPath Extension defaultExtension extension setExtension stripExtension withDefaultExtension withExtension Other filenameCharCmp filenameCmp globMatch CaseSensitive
Source
std/path.d
path : (alias template) gen_wired_inline.buildPath = std.path.buildPath(Range)(scope Range segments) if (isInputRange!Range && !isInfinite!Range && isSomeString!(ElementType!Range))Combines one or more path segments.
This function takes a set of path segments, given as an input
range of string elements or as a set of string arguments,
and concatenates them with each other. Directory separators
are inserted between segments if necessary. If any of the
path segments are absolute (as defined by isAbsolute), the
preceding segments will be dropped.
On Windows, if one of the path segments are rooted, but not absolute
(e.g. \foo), all preceding path segments down to the previous
root will be dropped. (See below for an example.)
This function always allocates memory to hold the resulting path.
The variadic overload is guaranteed to only perform a single
allocation, as is the range version if paths is a forward
range.
buildPath, (alias template) gen_wired_inline.dirName = std.path.dirName(R)(return scope R path) if (isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) && !isSomeString!R)Returns the parent directory of path. On Windows, this
includes the drive letter if present. If path is a relative path and
the parent directory is the current working directory, returns ".".
dirName;
import (package) stdstd.(module) std.stdioCategory Symbols File handles _popen File isFileHandle openNetwork stderr stdin stdout Reading chunks lines readf readfln readln Writing toFile write writef writefln writeln Misc KeepTerminator LockType StdioException
Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio
is publically imported when importing std.stdio.
There are three layers of I/O:
The lowest layer is the operating system layer. The two main schemes are Windows and Posix.
C's stdio.h which unifies the two operating system schemes.
std.stdio, this module, unifies the various stdio.h implementations into
a high level package for D programs.
Source
std/stdio.d
stdio : (alias template) gen_wired_inline.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))Equivalent to writef(fmt, args, '\n').
writefln;
import (package) stdstd.(module) std.stringString handling functions.
Category Functions Searching column indexOf indexOfAny indexOfNeither lastIndexOf lastIndexOfAny lastIndexOfNeither Comparison isNumeric Mutation capitalize Pruning and Filling center chomp chompPrefix chop detabber detab entab entabber leftJustify outdent rightJustify strip stripLeft stripRight wrap Substitution abbrev soundex soundexer succ tr translate Miscellaneous assumeUTF fromStringz lineSplitter representation splitLines toStringz Objects of types string, wstring, and dstring are value types and cannot be mutated element-by-element. For using mutation during building strings, use char[], wchar[], or dchar[]. The xxxstring types are preferable because they don't exhibit undesired aliasing, thus making code more robust.
The following functions are publicly imported:
Module Functions Publicly imported functions std.algorithm cmp, std,algorithm,comparison count, std,algorithm,searching endsWith, std,algorithm,searching startsWith, std,algorithm,searching std.array join, std,array replace, std,array replaceInPlace, std,array split, std,array empty, std,array std.format format, std,format sformat, std,format std.uni icmp, std,uni toLower, std,uni toLowerInPlace, std,uni toUpper, std,uni toUpperInPlace, std,uni There is a rich set of functions for string handling defined in other modules. Functions related to Unicode and ASCII are found in std.uni and std.ascii, respectively. Other functions that have a wider generality than just strings can be found in std.algorithm and std.range.
Source
std/string.d
string : (alias template) gen_wired_inline.strip = std.string.strip(Range)(Range str) if (isSomeString!Range || isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && !isConvertibleToString!Range && isSomeChar!(ElementEncodingType!Range))Strips both leading and trailing whitespace (as defined by
isWhite) or as specified in the second argument.
strip, (alias template) gen_wired_inline.stripRight = std.string.stripRight(Range)(Range str) if (isSomeString!Range || isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && !isConvertibleToString!Range && isSomeChar!(ElementEncodingType!Range))Strips trailing whitespace (as defined by isWhite) or
as specified in the second argument.
stripRight;
/// One source module folded into the generated unit. Order is cosmetic —
/// D module-scope declarations are order-independent — but it keeps the
/// generated file readable bottom-up: primitives first, grammar last.
private struct (struct) gen_wired_inline.SourceOne source module folded into the generated unit. Order is cosmetic —
D module-scope declarations are order-independent — but it keeps the
generated file readable bottom-up: primitives first, grammar last.
Source
{
(alias) object.string = stringstring (field) string gen_wired_inline.Source.pathrepo-relative
path; /// repo-relative
(alias) object.string = stringstring (field) string gen_wired_inline.Source.moduleNamethe module being absorbed (its imports drop out)
moduleName; /// the module being absorbed (its imports drop out)
}
private immutable (struct) gen_wired_inline.SourceOne source module folded into the generated unit. Order is cosmetic —
D module-scope declarations are order-independent — but it keeps the
generated file readable bottom-up: primitives first, grammar last.
Source[] (immutable global) immutable(gen_wired_inline.Source[]) gen_wired_inline.sourcessources = [
(struct) gen_wired_inline.SourceOne source module folded into the generated unit. Order is cosmetic —
D module-scope declarations are order-independent — but it keeps the
generated file readable bottom-up: primitives first, grammar last.
Source("libs/base/src/sparkles/base/text/errors.d", "sparkles.base.text.errors"),
(struct) gen_wired_inline.SourceOne source module folded into the generated unit. Order is cosmetic —
D module-scope declarations are order-independent — but it keeps the
generated file readable bottom-up: primitives first, grammar last.
Source("libs/base/src/sparkles/base/text/float_conv.d", "sparkles.base.text.float_conv"),
(struct) gen_wired_inline.SourceOne source module folded into the generated unit. Order is cosmetic —
D module-scope declarations are order-independent — but it keeps the
generated file readable bottom-up: primitives first, grammar last.
Source("libs/base/src/sparkles/base/text/utf8.d", "sparkles.base.text.utf8"),
(struct) gen_wired_inline.SourceOne source module folded into the generated unit. Order is cosmetic —
D module-scope declarations are order-independent — but it keeps the
generated file readable bottom-up: primitives first, grammar last.
Source("libs/wired/src/sparkles/wired/json/document.d", "sparkles.wired.json.document"),
(struct) gen_wired_inline.SourceOne source module folded into the generated unit. Order is cosmetic —
D module-scope declarations are order-independent — but it keeps the
generated file readable bottom-up: primitives first, grammar last.
Source("libs/wired/src/sparkles/wired/json/scan.d", "sparkles.wired.json.scan"),
(struct) gen_wired_inline.SourceOne source module folded into the generated unit. Order is cosmetic —
D module-scope declarations are order-independent — but it keeps the
generated file readable bottom-up: primitives first, grammar last.
Source("libs/wired/src/sparkles/wired/json/reader.d", "sparkles.wired.json.reader"),
];
private enum (constant) string gen_wired_inline.outRelative = "libs/wired/bench/runtime/src/sparkles/wired_bench/engines/wired_inline_impl.d"outRelative = "libs/wired/bench/runtime/src/sparkles/wired_bench/engines/"
~ "wired_inline_impl.d";
void void D main(string[] args)main((alias) object.string = stringstring[] (parameter) string[] argsargs)
{
// The tool lives at <repo>/libs/wired/bench/runtime/tools/.
const (local variable) const(string) reporepo = (parameter) string[] argsargs[0].string std.path.dirName!(immutable(char))(return scope string path) pure nothrow @nogc @safeReturns the parent directory of path. On Windows, this
includes the drive letter if present. If path is a relative path and
the parent directory is the current working directory, returns ".".
Examples
assert(dirName("") == ".");
assert(dirName("file"w) == ".");
assert(dirName("dir/"d) == ".");
assert(dirName("dir///") == ".");
assert(dirName("dir/file"w.dup) == "dir");
assert(dirName("dir///file"d.dup) == "dir");
assert(dirName("dir/subdir/") == "dir");
assert(dirName("/dir/file"w) == "/dir");
assert(dirName("/file"d) == "/");
assert(dirName("/") == "/");
assert(dirName("///") == "/");
version (Windows)
{
assert(dirName(`dir\`) == `.`);
assert(dirName(`dir\\\`) == `.`);
assert(dirName(`dir\file`) == `dir`);
assert(dirName(`dir\\\file`) == `dir`);
assert(dirName(`dir\subdir\`) == `dir`);
assert(dirName(`\dir\file`) == `\dir`);
assert(dirName(`\file`) == `\`);
assert(dirName(`\`) == `\`);
assert(dirName(`\\\`) == `\`);
assert(dirName(`d:`) == `d:`);
assert(dirName(`d:file`) == `d:`);
assert(dirName(`d:\`) == `d:\`);
assert(dirName(`d:\file`) == `d:\`);
assert(dirName(`d:\dir\file`) == `d:\dir`);
assert(dirName(`\\server\share\dir\file`) == `\\server\share\dir`);
assert(dirName(`\\server\share\file`) == `\\server\share`);
assert(dirName(`\\server\share\`) == `\\server\share`);
assert(dirName(`\\server\share`) == `\\server\share`);
}
dirName.string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safeCombines one or more path segments.
This function takes a set of path segments, given as an input
range of string elements or as a set of string arguments,
and concatenates them with each other. Directory separators
are inserted between segments if necessary. If any of the
path segments are absolute (as defined by isAbsolute), the
preceding segments will be dropped.
On Windows, if one of the path segments are rooted, but not absolute
(e.g. \foo), all preceding path segments down to the previous
root will be dropped. (See below for an example.)
This function always allocates memory to hold the resulting path.
The variadic overload is guaranteed to only perform a single
allocation, as is the range version if paths is a forward
range.
Examples
version (Posix)
{
assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
assert(buildPath("/foo/", "bar/baz") == "/foo/bar/baz");
assert(buildPath("/foo", "/bar") == "/bar");
}
version (Windows)
{
assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
assert(buildPath("foo", `d:\bar`) == `d:\bar`);
assert(buildPath("foo", `\bar`) == `\bar`);
assert(buildPath(`c:\foo`, `\bar`) == `c:\bar`);
}
buildPath("..", "..", "..", "..", "..");
auto (local variable) std.array.Appender!string body_body_ = std.array.Appender!string std.array.appender!string() pure nothrow @safeConvenience function that returns an Appender instance,
optionally initialized with array.
appender!(alias) object.string = stringstring;
(alias) object.string = stringstring[] (local variable) string[] carriedImportscarriedImports;
foreach ((parameter) immutable(gen_wired_inline.Source) srcsrc; (immutable global) immutable(gen_wired_inline.Source[]) gen_wired_inline.sourcessources)
{
auto (local variable) gen_wired_inline.Absorbed rr = gen_wired_inline.Absorbed gen_wired_inline.absorb(string text, string moduleName)Strips text down to the declarations worth copying: drops the module
header, the top-level imports of modules that are themselves being absorbed
(they would be self-imports), the test section, and any stray named
unittest block. Top-level imports of outside modules are lifted out and
returned so the generated file can carry them once.
absorb(string std.file.readText!(string, string)(string name) @safeReads and validates (using validate) a text file. S can be
an array of any character type. However, no width or endian conversions are
performed. So, if the width or endianness of the characters in the given
file differ from the width or endianness of the element type of S, then
validation will fail.
Examples
Read file with UTF-8 text.
write(deleteme, "abc"); // deleteme is the name of a temporary file
scope(exit) remove(deleteme);
string content = readText(deleteme);
assert(content == "abc");
readText((local variable) const(string) reporepo.string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safeCombines one or more path segments.
This function takes a set of path segments, given as an input
range of string elements or as a set of string arguments,
and concatenates them with each other. Directory separators
are inserted between segments if necessary. If any of the
path segments are absolute (as defined by isAbsolute), the
preceding segments will be dropped.
On Windows, if one of the path segments are rooted, but not absolute
(e.g. \foo), all preceding path segments down to the previous
root will be dropped. (See below for an example.)
This function always allocates memory to hold the resulting path.
The variadic overload is guaranteed to only perform a single
allocation, as is the range version if paths is a forward
range.
Examples
version (Posix)
{
assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
assert(buildPath("/foo/", "bar/baz") == "/foo/bar/baz");
assert(buildPath("/foo", "/bar") == "/bar");
}
version (Windows)
{
assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
assert(buildPath("foo", `d:\bar`) == `d:\bar`);
assert(buildPath("foo", `\bar`) == `\bar`);
assert(buildPath(`c:\foo`, `\bar`) == `c:\bar`);
}
buildPath((local variable) immutable(gen_wired_inline.Source) srcsrc.(field) string gen_wired_inline.Source.pathrepo-relative
path)), (local variable) immutable(gen_wired_inline.Source) srcsrc.(field) string gen_wired_inline.Source.moduleNamethe module being absorbed (its imports drop out)
moduleName);
foreach ((parameter) string impimp; (local variable) gen_wired_inline.Absorbed rr.(field) string[] gen_wired_inline.Absorbed.importstop-level imports of modules NOT being absorbed
imports)
if (!(local variable) string[] carriedImportscarriedImports.bool std.algorithm.searching.canFind!().canFind!(string[], string)(string[] haystack, scope string needle) pure nothrow @nogc @safeConvenience function. Like find, but only returns whether or not the search
was successful.
For more information about pred see find.
Examples
const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));
// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);
assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);
Example using a custom predicate.
Note that the needle appears as the second argument of the predicate.
auto words = [
"apple",
"beeswax",
"cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));
Search for multiple items in an array of items (search for needles in an array of haystacks)
string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
canFind((local variable) string impimp))
(local variable) string[] carriedImportscarriedImports ~= (local variable) string impimp;
(local variable) std.array.Appender!string body_body_ ~= "// ═══════════════════════════════════════════════════════"
~ "══════════════════\n";
(local variable) std.array.Appender!string body_body_ ~= "// From " ~ (local variable) immutable(gen_wired_inline.Source) srcsrc.(field) string gen_wired_inline.Source.pathrepo-relative
path ~ "\n";
(local variable) std.array.Appender!string body_body_ ~= "// ═══════════════════════════════════════════════════════"
~ "══════════════════\n\n";
(local variable) std.array.Appender!string body_body_ ~= (local variable) gen_wired_inline.Absorbed rr.(field) string gen_wired_inline.Absorbed.codecode;
(local variable) std.array.Appender!string body_body_ ~= "\n";
}
const (local variable) const(string) outPathoutPath = (local variable) const(string) reporepo.string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safeCombines one or more path segments.
This function takes a set of path segments, given as an input
range of string elements or as a set of string arguments,
and concatenates them with each other. Directory separators
are inserted between segments if necessary. If any of the
path segments are absolute (as defined by isAbsolute), the
preceding segments will be dropped.
On Windows, if one of the path segments are rooted, but not absolute
(e.g. \foo), all preceding path segments down to the previous
root will be dropped. (See below for an example.)
This function always allocates memory to hold the resulting path.
The variadic overload is guaranteed to only perform a single
allocation, as is the range version if paths is a forward
range.
Examples
version (Posix)
{
assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
assert(buildPath("/foo/", "bar/baz") == "/foo/bar/baz");
assert(buildPath("/foo", "/bar") == "/bar");
}
version (Windows)
{
assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
assert(buildPath("foo", `d:\bar`) == `d:\bar`);
assert(buildPath("foo", `\bar`) == `\bar`);
assert(buildPath(`c:\foo`, `\bar`) == `c:\bar`);
}
buildPath((constant) string gen_wired_inline.outRelative = "libs/wired/bench/runtime/src/sparkles/wired_bench/engines/wired_inline_impl.d"outRelative);
// Exactly one trailing newline — the end-of-file-fixer hook rewrites the
// file otherwise, and a hook-edited generated file no longer matches what
// the generator produces.
void std.file.write!string(string name, const(void[]) buffer) @safeWrite buffer to file name.
Creates the file if it does not already exist.
Examples
scope(exit)
{
assert(exists(deleteme));
remove(deleteme);
}
int[] a = [ 0, 1, 1, 2, 3, 5, 8 ];
write(deleteme, a); // deleteme is the name of a temporary file
const bytes = read(deleteme);
const fileInts = () @trusted { return cast(int[]) bytes; }();
assert(fileInts == a);
write((local variable) const(string) outPathoutPath, (string gen_wired_inline.header(string[] imports)header((local variable) string[] carriedImportscarriedImports) ~ (local variable) std.array.Appender!string body_body_[]).string std.string.stripRight!string(string str) pure nothrow @nogc @safeStrips trailing whitespace (as defined by isWhite) or
as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(stripRight(" hello world ") ==
" hello world");
assert(stripRight("\n\t\v\rhello world\n\t\v\r") ==
"\n\t\v\rhello world");
assert(stripRight("hello world") ==
"hello world");
assert(stripRight([lineSep] ~ "hello world" ~ lineSep) ==
[lineSep] ~ "hello world");
assert(stripRight([paraSep] ~ "hello world" ~ paraSep) ==
[paraSep] ~ "hello world");
stripRight ~ "\n");
void std.stdio.writefln!(char, string, ulong, ulong)(in char[] fmt, string __param_1, ulong __param_2, ulong __param_3) @safeEquivalent to writef(fmt, args, '\n').
writefln("wrote %s (%s lines, %s carried imports)", (constant) string gen_wired_inline.outRelative = "libs/wired/bench/runtime/src/sparkles/wired_bench/engines/wired_inline_impl.d"outRelative,
(local variable) std.array.Appender!string body_body_[].ulong gen_wired_inline.countLines(string s)countLines, (local variable) string[] carriedImportscarriedImports.(field) ulong string[].lengthlength);
}
private (alias) object.size_t = ulongsize_t ulong gen_wired_inline.countLines(string s)countLines((alias) object.string = stringstring (parameter) string ss)
{
(alias) object.size_t = ulongsize_t (local variable) ulong nn = 1;
foreach ((parameter) immutable(char) cc; (parameter) string ss)
if ((local variable) immutable(char) cc == '\n')
(local variable) ulong nn++;
return (local variable) ulong nn;
}
private (alias) object.string = stringstring string gen_wired_inline.header(string[] imports)header((alias) object.string = stringstring[] (parameter) string[] importsimports)
{
return "// GENERATED FILE — DO NOT EDIT.\n"
~ "// Regenerate with: dub run --single tools/gen-wired-inline.d\n"
~ "//\n"
~ "// A single-translation-unit copy of the `sparkles:wired` native JSON\n"
~ "// reader and the `sparkles:base` primitives it calls, spliced together\n"
~ "// so every seam is intra-module and LDC's inliner sees the whole kernel\n"
~ "// at once. Backs the `wired-inline` bench engine, whose only difference\n"
~ "// from `wired-native` is that this code is all in one module — the A/B\n"
~ "// that isolates inlining from cross-module-inlining, LTO and PGO.\n"
~ "//\n"
~ "// Sources are copied verbatim (module headers, imports of the absorbed\n"
~ "// modules, and unittest blocks removed). Edit the originals, not this.\n"
~ "module sparkles.wired_bench.engines.wired_inline_impl;\n\n"
~ (parameter) string[] importsimports.string std.array.join!(string[], string)(string[] ror, string sep) pure nothrow @safeEagerly concatenates all of the ranges in ror together (with the GC)
into one array using sep as the separator if present.
join("\n") ~ "\n\n";
}
private struct (struct) gen_wired_inline.AbsorbedAbsorbed
{
(alias) object.string = stringstring (field) string gen_wired_inline.Absorbed.codecode;
(alias) object.string = stringstring[] (field) string[] gen_wired_inline.Absorbed.importstop-level imports of modules NOT being absorbed
imports; /// top-level imports of modules NOT being absorbed
}
/**
Strips `text` down to the declarations worth copying: drops the module
header, the top-level imports of modules that are themselves being absorbed
(they would be self-imports), the test section, and any stray named
unittest block. Top-level imports of *outside* modules are lifted out and
returned so the generated file can carry them once.
*/
private (struct) gen_wired_inline.AbsorbedAbsorbed gen_wired_inline.Absorbed gen_wired_inline.absorb(string text, string moduleName)Strips text down to the declarations worth copying: drops the module
header, the top-level imports of modules that are themselves being absorbed
(they would be self-imports), the test section, and any stray named
unittest block. Top-level imports of outside modules are lifted out and
returned so the generated file can carry them once.
absorb((alias) object.string = stringstring (parameter) string texttext, (alias) object.string = stringstring (parameter) string moduleNamemoduleName)
{
import (package) stdstd.(module) std.stringString handling functions.
Category Functions Searching column indexOf indexOfAny indexOfNeither lastIndexOf lastIndexOfAny lastIndexOfNeither Comparison isNumeric Mutation capitalize Pruning and Filling center chomp chompPrefix chop detabber detab entab entabber leftJustify outdent rightJustify strip stripLeft stripRight wrap Substitution abbrev soundex soundexer succ tr translate Miscellaneous assumeUTF fromStringz lineSplitter representation splitLines toStringz Objects of types string, wstring, and dstring are value types and cannot be mutated element-by-element. For using mutation during building strings, use char[], wchar[], or dchar[]. The xxxstring types are preferable because they don't exhibit undesired aliasing, thus making code more robust.
The following functions are publicly imported:
Module Functions Publicly imported functions std.algorithm cmp, std,algorithm,comparison count, std,algorithm,searching endsWith, std,algorithm,searching startsWith, std,algorithm,searching std.array join, std,array replace, std,array replaceInPlace, std,array split, std,array empty, std,array std.format format, std,format sformat, std,format std.uni icmp, std,uni toLower, std,uni toLowerInPlace, std,uni toUpper, std,uni toUpperInPlace, std,uni There is a rich set of functions for string handling defined in other modules. Functions related to Unicode and ASCII are found in std.uni and std.ascii, respectively. Other functions that have a wider generality than just strings can be found in std.algorithm and std.range.
Source
std/string.d
string : (alias template) splitLines = std.string.splitLines(C)(C[] s, KeepTerminator keepTerm = No.keepTerminator) if (isSomeChar!C)Split s into an array of lines according to the unicode standard using
'\r', '\n', "\r\n", $(REF lineSep, std,uni),
$(REF paraSep, std,uni), U+0085 (NEL), '\v' and '\f'
as delimiters. If keepTerm is set to KeepTerminator.yes, then the
delimiter is included in the strings returned.
Does not throw on invalid UTF; such is simply passed unchanged
to the output.
Allocates memory; use $(LREF lineSplitter) for an alternative that
does not.
Adheres to $(HTTP www.unicode.org/versions/Unicode7.0.0/ch05.pdf, Unicode 7.0).
Params:
s = a string of chars, wchars, or dchars, or any custom
type that casts to a string type
keepTerm = whether delimiter is included or not in the results
Returns:
array of strings, each element is a line that is a slice of s
See_Also:
$(LREF lineSplitter)
$(REF splitter, std,algorithm)
$(REF splitter, std,regex)
splitLines;
auto (local variable) string[] lineslines = (parameter) string texttext.string[] std.string.splitLines!(immutable(char))(string s, std.typecons.Flag!"keepTerminator" keepTerm = Flag.no) pure nothrow @safeSplit s into an array of lines according to the unicode standard using
'\r', '\n', "\r\n", lineSep,
paraSep, U+0085 (NEL), '\v' and '\f'
as delimiters. If keepTerm is set to KeepTerminator.yes, then the
delimiter is included in the strings returned.
Does not throw on invalid UTF; such is simply passed unchanged
to the output.
Allocates memory; use lineSplitter for an alternative that
does not.
Adheres to Unicode 7.0.
Examples
string s = "Hello\nmy\rname\nis";
assert(splitLines(s) == ["Hello", "my", "name", "is"]);
splitLines;
auto (local variable) std.array.Appender!string codecode = std.array.Appender!string std.array.appender!string() pure nothrow @safeConvenience function that returns an Appender instance,
optionally initialized with array.
appender!(alias) object.string = stringstring;
(alias) object.string = stringstring[] (local variable) string[] importsimports;
(alias) object.size_t = ulongsize_t (local variable) ulong ii = 0;
// 1. Skip the module's DDoc banner and `module x.y.z;` line.
foreach ((parameter) ulong jj, (parameter) string lineline; (local variable) string[] lineslines)
if ((local variable) string lineline.string std.string.strip!string(string str) pure nothrow @nogc @safeStrips both leading and trailing whitespace (as defined by
isWhite) or as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(strip(" hello world ") ==
"hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
"hello world");
assert(strip("hello world") ==
"hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
"hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
"hello world");
strip.bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("module "))
{
(local variable) ulong ii = (local variable) ulong jj + 1;
break;
}
// The absorbed set — an import of any of these becomes a self-import.
static immutable (immutable global) immutable(string[]) gen_wired_inline.absorb.absorbedModulesabsorbedModules = [
"sparkles.base.text.errors", "sparkles.base.text.float_conv",
"sparkles.base.text.utf8", "sparkles.wired.json.document",
"sparkles.wired.json.scan", "sparkles.wired.json.reader",
];
for (; i < lines.length; i++)
{
const (local variable) const(string) lineline = (local variable) string[] lineslines[(local variable) ulong ii];
// 2. The test section — every module in this repo separates it with a
// box-drawing banner whose next line reads `// Tests…`.
if ((local variable) const(string) lineline.bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("// ─────") && (local variable) ulong ii + 1 < (local variable) string[] lineslines.(field) ulong string[].lengthlength
&& (local variable) string[] lineslines[(local variable) ulong ii + 1].string std.string.strip!string(string str) pure nothrow @nogc @safeStrips both leading and trailing whitespace (as defined by
isWhite) or as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(strip(" hello world ") ==
"hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
"hello world");
assert(strip("hello world") ==
"hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
"hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
"hello world");
strip.bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("// Tests"))
break;
// 3. A named unittest block (`@("name")` … through the closing brace
// in column 0). Covers modules whose tests sit between
// declarations rather than in a trailing section.
if ((local variable) const(string) lineline.bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("@(\""))
{
while ((local variable) ulong ii < (local variable) string[] lineslines.(field) ulong string[].lengthlength && (local variable) string[] lineslines[(local variable) ulong ii] != "}")
(local variable) ulong ii++;
continue;
}
// 4. A top-level import: drop it if self-referential, otherwise carry
// it up to the generated file's header. Selective imports wrap, so
// consume through the terminating semicolon.
if ((local variable) const(string) lineline.bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("import "))
{
(alias) object.string = stringstring (local variable) string stmtstmt = (local variable) const(string) lineline;
while (!(local variable) string stmtstmt.string std.string.stripRight!string(string str) pure nothrow @nogc @safeStrips trailing whitespace (as defined by isWhite) or
as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(stripRight(" hello world ") ==
" hello world");
assert(stripRight("\n\t\v\rhello world\n\t\v\r") ==
"\n\t\v\rhello world");
assert(stripRight("hello world") ==
"hello world");
assert(stripRight([lineSep] ~ "hello world" ~ lineSep) ==
[lineSep] ~ "hello world");
assert(stripRight([paraSep] ~ "hello world" ~ paraSep) ==
[paraSep] ~ "hello world");
stripRight.bool gen_wired_inline.endsWith(string s, string suffix)endsWith(";") && (local variable) ulong ii + 1 < (local variable) string[] lineslines.(field) ulong string[].lengthlength)
(local variable) string stmtstmt ~= "\n" ~ (local variable) string[] lineslines[++(local variable) ulong ii];
if (!(immutable global) immutable(string[]) gen_wired_inline.absorb.absorbedModulesabsorbedModules.bool std.algorithm.searching.canFind!().canFind!(immutable(string)[], string)(immutable(string)[] haystack, scope string needle) pure nothrow @nogc @safeConvenience function. Like find, but only returns whether or not the search
was successful.
For more information about pred see find.
Examples
const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));
// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);
assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);
Example using a custom predicate.
Note that the needle appears as the second argument of the predicate.
auto words = [
"apple",
"beeswax",
"cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));
Search for multiple items in an array of items (search for needles in an array of haystacks)
string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
canFind(string gen_wired_inline.importedModule(string stmt)import a.b.c : x, y; → a.b.c
importedModule((local variable) string stmtstmt)))
(local variable) string[] importsimports ~= (local variable) string stmtstmt;
continue;
}
// 5. A module-scope attribute *block* (`@safe … package:`) would leak
// its attributes across every later splice, so brace it instead.
if ((local variable) const(string) lineline.(field) ulong const(string).lengthlength && (local variable) const(string) lineline[0] == '@' && (local variable) const(string) lineline.string std.string.stripRight!string(string str) pure nothrow @nogc @safeStrips trailing whitespace (as defined by isWhite) or
as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(stripRight(" hello world ") ==
" hello world");
assert(stripRight("\n\t\v\rhello world\n\t\v\r") ==
"\n\t\v\rhello world");
assert(stripRight("hello world") ==
"hello world");
assert(stripRight([lineSep] ~ "hello world" ~ lineSep) ==
[lineSep] ~ "hello world");
assert(stripRight([paraSep] ~ "hello world" ~ paraSep) ==
[paraSep] ~ "hello world");
stripRight.bool gen_wired_inline.endsWith(string s, string suffix)endsWith(":"))
{
const (local variable) const(string) attrsattrs = (local variable) const(string) lineline.string std.string.stripRight!string(string str) pure nothrow @nogc @safeStrips trailing whitespace (as defined by isWhite) or
as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(stripRight(" hello world ") ==
" hello world");
assert(stripRight("\n\t\v\rhello world\n\t\v\r") ==
"\n\t\v\rhello world");
assert(stripRight("hello world") ==
"hello world");
assert(stripRight([lineSep] ~ "hello world" ~ lineSep) ==
[lineSep] ~ "hello world");
assert(stripRight([paraSep] ~ "hello world" ~ paraSep) ==
[paraSep] ~ "hello world");
stripRight[0 .. $ - 1];
(local variable) std.array.Appender!string codecode ~= (local variable) const(string) attrsattrs ~ "\n{\n";
for ((local variable) ulong ii++; i < lines.length; i++)
{
if ((local variable) string[] lineslines[(local variable) ulong ii].bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("// ─────") && (local variable) ulong ii + 1 < (local variable) string[] lineslines.(field) ulong string[].lengthlength
&& (local variable) string[] lineslines[(local variable) ulong ii + 1].string std.string.strip!string(string str) pure nothrow @nogc @safeStrips both leading and trailing whitespace (as defined by
isWhite) or as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(strip(" hello world ") ==
"hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
"hello world");
assert(strip("hello world") ==
"hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
"hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
"hello world");
strip.bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("// Tests"))
break;
if ((local variable) string[] lineslines[(local variable) ulong ii].bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("@(\""))
{
while ((local variable) ulong ii < (local variable) string[] lineslines.(field) ulong string[].lengthlength && (local variable) string[] lineslines[(local variable) ulong ii] != "}")
(local variable) ulong ii++;
continue;
}
(local variable) std.array.Appender!string codecode ~= (local variable) string[] lineslines[(local variable) ulong ii] ~ "\n";
}
(local variable) std.array.Appender!string codecode ~= "}\n";
break;
}
(local variable) std.array.Appender!string codecode ~= (local variable) const(string) lineline ~ "\n";
}
return (struct) gen_wired_inline.AbsorbedAbsorbed((local variable) std.array.Appender!string codecode[], (local variable) string[] importsimports);
}
private bool bool gen_wired_inline.endsWith(string s, string suffix)endsWith((alias) object.string = stringstring (parameter) string ss, (alias) object.string = stringstring (parameter) string suffixsuffix)
=> (parameter) string ss.(field) ulong string.lengthlength >= (parameter) string suffixsuffix.(field) ulong string.lengthlength && (parameter) string ss[$ - (parameter) string suffixsuffix.(field) ulong string.lengthlength .. $] == (parameter) string suffixsuffix;
/// `import a.b.c : x, y;` → `a.b.c`
private (alias) object.string = stringstring string gen_wired_inline.importedModule(string stmt)import a.b.c : x, y; → a.b.c
importedModule((alias) object.string = stringstring (parameter) string stmtstmt)
{
auto (local variable) string restrest = (parameter) string stmtstmt["import ".(constant) ulong "import ".length = 7LUlength .. $].string std.string.strip!string(string str) pure nothrow @nogc @safeStrips both leading and trailing whitespace (as defined by
isWhite) or as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(strip(" hello world ") ==
"hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
"hello world");
assert(strip("hello world") ==
"hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
"hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
"hello world");
strip;
foreach ((parameter) ulong kk, (parameter) immutable(char) cc; (local variable) string restrest)
if ((local variable) immutable(char) cc == ':' || (local variable) immutable(char) cc == ';' || (local variable) immutable(char) cc == ' ' || (local variable) immutable(char) cc == ',')
return (local variable) string restrest[0 .. (local variable) ulong kk].string std.string.strip!string(string str) pure nothrow @nogc @safeStrips both leading and trailing whitespace (as defined by
isWhite) or as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(strip(" hello world ") ==
"hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
"hello world");
assert(strip("hello world") ==
"hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
"hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
"hello world");
strip;
return (local variable) string restrest;
}