#!/usr/bin/env dub
/+ dub.sdl:
name "font_libraries_font_scan_timing"
targetPath "build"
buildType "checked" {
buildOptions "optimize" "inline" "debugInfo"
}
+/
/**
* How long does describing every font on a machine take? For each file
* (`.ttf`, `.otf`, and every face of a `.ttc`/`.otc` collection) this reads
* what a font catalog records per face — the table directory, the family name
* from `name`, the weight class from `OS/2`, and the code-point coverage of
* the best Unicode `cmap` subtable as a range count — through `mmap`, so only
* the pages those tables live on are touched.
*
* It times one serial pass, a second serial pass, and two passes over a
* `std.parallelism` pool. The first pass is cold only for files no process has
* read since boot: eviction needs root (and on ZFS the ARC ignores
* `posix_fadvise`), so the program does not try.
*
* Spike S1 of docs/specs/font/PLAN.md; decision FTX8 in
* docs/specs/font/decisions.md records the result.
*
* Run with: dub run --single font-scan-timing.d [-- list-of-paths.txt]
*
* Font resolution: the argument names a file with one font path per line;
* without it the program asks `fc-list : file`. If neither yields a font, it
* prints a `SKIP:` line and exits 0 so CI stays green.
*/
module (module) font_libraries_font_scan_timingHow long does describing every font on a machine take? For each file
(.ttf, .otf, and every face of a .ttc/.otc collection) this reads
what a font catalog records per face — the table directory, the family name
from name, the weight class from OS/2, and the code-point coverage of
the best Unicode cmap subtable as a range count — through mmap, so only
the pages those tables live on are touched.
It times one serial pass, a second serial pass, and two passes over a
std.parallelism pool. The first pass is cold only for files no process has
read since boot: eviction needs root (and on ZFS the ARC ignores
posix_fadvise), so the program does not try.
Spike S1 of docs/specs/font/PLAN.md; decision FTX8 in
docs/specs/font/decisions.md records the result.
Run with: dub run --single font-scan-timing.d [-- list-of-paths.txt]
Font resolution: the argument names a file with one font path per line;
without it the program asks fc-list : file. If neither yields a font, it
prints a SKIP: line and exits 0 so CI stays green.
font_libraries_font_scan_timing;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(module) core.sys.posix.fcntlD header file for POSIX.
fcntl : open, (alias constant) font_libraries_font_scan_timing.O_RDONLY = int core.sys.posix.fcntl.O_RDONLY = 0O_RDONLY;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(package) core.sys.posix.syssys.(module) core.sys.posix.sys.mmanD header file for POSIX.
mman : (alias constant) font_libraries_font_scan_timing.MAP_FAILED = void* core.sys.posix.sys.mman.MAP_FAILED = cast(void*)cast(size_t)18446744073709551615LUMAP_FAILED, (alias constant) font_libraries_font_scan_timing.MAP_PRIVATE = int core.sys.posix.sys.mman.MAP_PRIVATE = 2MAP_PRIVATE, mmap, (alias) font_libraries_font_scan_timing.munmap = int core.sys.posix.sys.mman.munmap(void*, ulong) nothrow @nogcmunmap, (alias constant) font_libraries_font_scan_timing.PROT_READ = int core.sys.posix.sys.mman.PROT_READ = 1PROT_READ;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(package) core.sys.posix.syssys.(module) core.sys.posix.sys.statD header file for POSIX.
stat : fstat, (struct) core.sys.posix.sys.stat.stat_tstat_t;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(module) core.sys.posix.unistdD header file for POSIX.
unistd : (alias) font_libraries_font_scan_timing.close = int core.sys.posix.unistd.close(int) nothrow @nogc @trustedclose;
import (package) stdstd.(module) std.algorithmThis package implements generic algorithms oriented towards the processing of
sequences. Sequences processed by these functions define range-based
interfaces. See also Reference on ranges and
tutorial on ranges.
Algorithms are categorized into the following submodules:
Submodule Functions
| Searching |
all
any
balancedParens
boyerMooreFinder
canFind
commonPrefix
count
countUntil
endsWith
find
findAdjacent
findAmong
findSkip
findSplit
findSplitAfter
findSplitBefore
minCount
maxCount
minElement
maxElement
minIndex
maxIndex
minPos
maxPos
skipOver
startsWith
until
|
| Comparison |
among
castSwitch
clamp
cmp
either
equal
isPermutation
isSameLength
levenshteinDistance
levenshteinDistanceAndPath
max
min
mismatch
predSwitch
|
| Iteration |
cache
cacheBidirectional
chunkBy
cumulativeFold
each
filter
filterBidirectional
fold
group
joiner
map
mean
permutations
reduce
splitWhen
splitter
substitute
sum
uniq
|
| Sorting |
completeSort
isPartitioned
isSorted
isStrictlyMonotonic
ordered
strictlyOrdered
makeIndex
merge
multiSort
nextEvenPermutation
nextPermutation
nthPermutation
partialSort
partition
partition3
schwartzSort
sort
topN
topNCopy
topNIndex
|
| Set operations (setops) |
cartesianProduct
largestPartialIntersection
largestPartialIntersectionWeighted
multiwayMerge
multiwayUnion
setDifference
setIntersection
setSymmetricDifference
|
| Mutation |
bringToFront
copy
fill
initializeAll
move
moveAll
moveSome
moveEmplace
moveEmplaceAll
moveEmplaceSome
remove
reverse
strip
stripLeft
stripRight
swap
swapRanges
uninitializedFill
|
Many functions in this package are parameterized with a predicate.
The predicate may be any suitable callable type
(a function, a delegate, a functor, or a lambda), or a
compile-time string. The string may consist of any legal D
expression that uses the symbol a (for unary functions) or the
symbols a and b (for binary functions). These names will NOT
interfere with other homonym symbols in user code because they are
evaluated in a different context. The default for all binary
comparison predicates is "a == b" for unordered operations and
"a < b" for ordered operations.
Example
int[] a = ...;
static bool greater(int a, int b)
{
return a > b;
}
sort!greater(a); // predicate as alias
sort!((a, b) => a > b)(a); // predicate as a lambda.
sort!"a > b"(a); // predicate as string
// (no ambiguity with array name)
sort(a); // no predicate, "a < b" is implicit
Source
std/algorithm/package.d
algorithm : (alias template) font_libraries_font_scan_timing.count = std.algorithm.searching.count(alias pred = "a == b", Range, E)(Range haystack, E needle) if (isInputRange!Range && !isInfinite!Range && is(typeof(binaryFun!pred(haystack.front, needle))))Counts matches of needle in haystack.
The first overload counts each element e in haystack for
which pred(e, needle) is true. pred defaults to
equality. Performs O(haystack.length) evaluations of pred.
The second overload counts the number of times needle was matched in
haystack. pred compares elements in each range.
Throws an exception if needle.empty is true, as the count
of the empty range in any range would be infinite. Overlapped counts
are not considered, for example ``count("aaa", "aa") is 1, not
2.
Note
Regardless of the overload, count will not accept
infinite ranges for haystack.
count, (alias template) font_libraries_font_scan_timing.endsWith = std.algorithm.searching.endsWith(alias pred = "a == b", Range, Needles...)(Range doesThisEnd, Needles withOneOfThese) if (isBidirectionalRange!Range && (Needles.length > 1) && allSatisfy!(canTestStartsWith!(pred, Range), Needles))Checks if the given range ends with (one of) the given needle(s).
The reciprocal of startsWith.
endsWith, (alias template) font_libraries_font_scan_timing.filter = std.algorithm.iteration.filter(alias predicate) if (is(typeof(unaryFun!predicate)))``filter!(predicate)(range) returns a new range containing only elements x in range for
which predicate(x) returns true.
The predicate is passed to unaryFun, and can be either a string, or
any callable that can be executed via pred(element).
filter, (alias template) font_libraries_font_scan_timing.joiner = std.algorithm.iteration.joiner(RoR, Separator)(RoR r, Separator sep)Lazily joins a range of ranges with a separator. The separator itself
is a range. If a separator is not provided, then the ranges are
joined directly without anything in between them (often called flatten
in other languages).
Note
When both outer and inner ranges of RoR are bidirectional and the joiner is
iterated from the back to the front, the separator will still be consumed from
front to back, even if it is a bidirectional range too.
joiner, (alias template) font_libraries_font_scan_timing.map = std.algorithm.iteration.map(fun...) if (fun.length >= 1)Implements the homonym function (also known as transform) present
in many languages of functional flavor. The call ``map!(fun)(range)
returns a range of which elements are obtained by applying fun(a)
left to right for all elements a in range. The original ranges are
not changed. Evaluation is done lazily.
map, (alias template) font_libraries_font_scan_timing.sort = std.algorithm.sorting.sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r)Sorts a random-access range according to the predicate less.
Performs O(r.length * log(r.length)) evaluations of less. If less involves
expensive computations on the sort key, it may be worthwhile to use
schwartzSort instead.
Stable sorting requires hasAssignableElements!Range to be true.
sort returns a SortedRange over the original range,
allowing functions that can take advantage of sorted data to know that the
range is sorted and adjust accordingly. The SortedRange is a
wrapper around the original range, so both it and the original range are sorted.
Other functions can't know that the original range has been sorted, but
they can know that SortedRange has been sorted.
Preconditions
The predicate is expected to satisfy certain rules in order for sort to
behave as expected - otherwise, the program may fail on certain inputs (but not
others) when not compiled in release mode, due to the cursory assumeSorted
check. Specifically, sort expects less(a,b) && less(b,c) to imply
less(a,c) (transitivity), and, conversely, !less(a,b) && !less(b,c) to
imply !less(a,c). Note that the default predicate ("a < b") does not
always satisfy these conditions for floating point types, because the expression
will always be false when either a or b is NaN.
Use cmp instead.
Algorithms
Introsort is used for unstable sorting and
Timsort is used for stable sorting.
Each algorithm has benefits beyond stability. Introsort is generally faster but
Timsort may achieve greater speeds on data with low entropy or if predicate calls
are expensive. Introsort performs no allocations whereas Timsort will perform one
or more allocations per call. Both algorithms have O(n log n) worst-case
time complexity.
sort, (alias template) font_libraries_font_scan_timing.sum = std.algorithm.iteration.sum(R)(R r) if (isInputRange!R && !isInfinite!R && is(typeof(r.front + r.front)))Sums elements of r, which must be a finite
input range. Although
conceptually sum`(r)` is equivalent to `fold`!((a, b) => a +
b)(r, 0), sum`` uses specialized algorithms to maximize accuracy,
as follows.
If ElementType!R is a floating-point
type and R is a
random-access range with
length and slicing, then sum uses the
pairwise summation
algorithm.
If ElementType!R is a floating-point type and R is a
finite input range (but not a random-access range with slicing), then
sum uses the Kahan summation algorithm.
In all other cases, a simple element by element addition is done.
For floating point inputs, calculations are made in
spec/type, Types, real
precision for real inputs and in double precision otherwise
(Note this is a special case that deviates from fold's behavior,
which would have kept float precision for a float range).
For all other types, the calculations are done in the same type obtained
from from adding two elements of the range, which may be a different
type from the elements themselves (for example, in case of
integral promotion).
A seed may be passed to sum. Not only will this seed be used as an initial
value, but its type will override all the above, and determine the algorithm
and precision used for summation. If a seed is not passed, one is created with
the value of typeof(r.front + r.front)(0), or typeof(r.front + r.front).zero
if no constructor exists that takes an int.
Note that these specialized summing algorithms execute more primitive operations
than vanilla summation. Therefore, if in certain cases maximum speed is required
at expense of precision, one can use fold!((a, b) => a + b)(r, 0), which
is not specialized for summation.
sum, (alias template) font_libraries_font_scan_timing.uniq = std.algorithm.iteration.uniq(alias pred = "a == b", Range)(Range r) if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, r.front)) == bool))Lazily iterates unique consecutive elements of the given range, which is
assumed to be sorted (functionality akin to the
uniq system
utility). Equivalence of elements is assessed by using the predicate
pred, by default "a == b". The predicate is passed to
binaryFun, and can either accept a string, or any callable
that can be executed via pred(element, element). If the given range is
bidirectional, uniq also yields a
bidirectional range.
uniq;
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) font_libraries_font_scan_timing.array = std.array.array(Range)(Range r) if (isIterable!Range && !isAutodecodableString!Range && !isInfinite!Range)Allocates an array and initializes it with copies of the elements
of range r.
Narrow strings are handled as follows:
If autodecoding is turned on (default), then they are handled as a separate overload.
If autodecoding is turned off, then this is equivalent to duplicating the array.
array, (alias template) font_libraries_font_scan_timing.split = std.array.split(S)(S s) if (isSomeString!S)Eagerly splits range into an array, using sep as the delimiter.
When no delimiter is provided, strings are split into an array of words,
using whitespace as delimiter.
Runs of whitespace are merged together (no empty words are produced).
The range must be a forward range.
The separator can be a value of the same type as the elements in range
or it can be another forward range.
split;
import (package) stdstd.(module) std.convA one-stop shop for converting values from one type to another.
Category Functions Generic asOriginalType castFrom parse to toChars bitCast Strings text wtext dtext writeText writeWText writeDText hexString Numeric octal roundTo signed unsigned Exceptions ConvException ConvOverflowException
Source
std/conv.d
conv : (alias template) font_libraries_font_scan_timing.to = std.conv.to(T)The to template converts a value from one type to another.
The source type is deduced and the target type must be specified, for example the
expression to`!int(42.0)` converts the number 42 from
`double` to `int`. The conversion is "safe", i.e.,
it checks for overflow; to!int(4.2e10) would throw the
ConvOverflowException exception. Overflow checks are only
inserted when necessary, e.g., ``to!double(42) does not do
any checking because any int fits in a double.
Conversions from string to numeric types differ from the C equivalents
atoi() and atol() by checking for overflow and not allowing whitespace.
For conversion of strings to signed types, the grammar recognized is:
Integer:
Sign UnsignedInteger
UnsignedInteger
Sign:
+
-
For conversion to unsigned types, the grammar recognized is:
UnsignedInteger:
DecimalDigit
DecimalDigit UnsignedInteger
to;
import (package) stdstd.(package) std.datetimedatetime.(module) std.datetime.stopwatchModule containing some basic benchmarking and timing functionality.
For convenience, this module publicly imports core.time.
Category Functions Main functionality StopWatch benchmark Flags AutoStart
Unlike the other modules in std.datetime, this module is not currently
publicly imported in std.datetime.package, because the old
versions of this functionality which use
TickDuration are in std.datetime.package and would
conflict with the symbols in this module. After the old symbols have
gone through the deprecation cycle and have been fully removed, then
this module will be publicly imported in std.datetime.package. The
old, deprecated symbols has been removed from the documentation in
December 2019 and currently scheduled to be fully removed from Phobos
after 2.094.
So, for now, when using std.datetime.stopwatch, if other modules from
std.datetime are needed, then either import them individually rather than
importing std.datetime, or use selective or static imports to import
std.datetime.stopwatch. e.g.
import std.datetime;
import std.datetime.stopwatch : benchmark, StopWatch;
The compiler will then know to use the symbols from std.datetime.stopwatch
rather than the deprecated ones from std.datetime.package.
Source
std/datetime/stopwatch.d
stopwatch : (enum) std.typecons.Flag!"autoStart"Examples
Flag!"abc" flag;
assert(flag == Flag!"abc".no);
assert(flag == No.abc);
assert(!flag);
if (flag) assert(0);
auto flag = Yes.abc;
assert(flag);
assert(flag == Yes.abc);
if (!flag) assert(0);
if (flag) {} else assert(0);
AutoStart, (struct) std.datetime.stopwatch.StopWatchStopWatch is used to measure time just like one would do with a physical
stopwatch, including stopping, restarting, and/or resetting it.
MonoTime is used to hold the time, and it uses the system's
monotonic clock, which is high precision and never counts backwards (unlike
the wall clock time, which can count backwards, which is why
SysTime should not be used for timing).
Note that the precision of StopWatch differs from system to system. It is
impossible for it to be the same for all systems, since the precision of the
system clock and other system-dependent and situation-dependent factors
(such as the overhead of a context switch between threads) varies from
system to system and can affect StopWatch's accuracy.
Examples
Measure a time in milliseconds, microseconds, or nanoseconds
auto sw = StopWatch(AutoStart.no);
sw.start();
// ... Insert operations to be timed here ...
sw.stop();
long msecs = sw.peek.total!"msecs";
long usecs = sw.peek.total!"usecs";
long nsecs = sw.peek.total!"nsecs";
assert(usecs >= msecs * 1000);
assert(nsecs >= usecs * 1000);
import core.thread : Thread;
auto sw = StopWatch(AutoStart.yes);
Duration t1 = sw.peek();
Thread.sleep(usecs(1));
Duration t2 = sw.peek();
assert(t2 > t1);
Thread.sleep(usecs(1));
sw.stop();
Duration t3 = sw.peek();
assert(t3 > t2);
Duration t4 = sw.peek();
assert(t3 == t4);
sw.start();
Thread.sleep(usecs(1));
Duration t5 = sw.peek();
assert(t5 > t4);
// If stopping or resetting the StopWatch is not required, then
// MonoTime can easily be used by itself without StopWatch.
auto before = MonoTime.currTime;
// do stuff...
auto timeElapsed = MonoTime.currTime - before;
StopWatch;
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) font_libraries_font_scan_timing.exists = std.file.exists(R)(R name) if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)Determine whether the given file (or directory) exists.
exists, (alias template) font_libraries_font_scan_timing.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;
import (package) stdstd.(module) std.parallelismstd.parallelism implements high-level primitives for SMP `parallelism`.
These include parallel foreach, parallel reduce, parallel eager map, pipelining
and future/promise `parallelism`. `std.`parallelism is recommended when the
same operation is to be executed in parallel on different data, or when a
function is to be executed in a background thread and its result returned to a
well-defined main thread. For communication between arbitrary threads, see
std.concurrency.
std.parallelism`` is based on the concept of a Task. A Task is an
object that represents the fundamental unit of work in this library and may be
executed in parallel with any other Task. Using Task
directly allows programming with a future/promise paradigm. All other
supported parallelism paradigms (parallel foreach, map, reduce, pipelining)
represent an additional level of abstraction over Task. They
automatically create one or more Task objects, or closely related types
that are conceptually identical but not part of the public API.
After creation, a Task may be executed in a new thread, or submitted
to a TaskPool for execution. A TaskPool encapsulates a task queue
and its worker threads. Its purpose is to efficiently map a large
number of Tasks onto a smaller number of threads. A task queue is a
FIFO queue of Task objects that have been submitted to the
TaskPool and are awaiting execution. A worker thread is a thread that
is associated with exactly one task queue. It executes the Task at the
front of its queue when the queue has work available, or sleeps when
no work is available. Each task queue is associated with zero or
more worker threads. If the result of a Task is needed before execution
by a worker thread has begun, the Task can be removed from the task queue
and executed immediately in the thread where the result is needed.
Warning
Unless marked as @trusted or @safe, artifacts in
this module allow implicit data sharing between threads and cannot
guarantee that client code is free from low level data races.
Source
std/parallelism.d
Author
David Simcha
parallelism : (alias template) font_libraries_font_scan_timing.parallel = std.parallelism.parallel(R)(R range)Convenience functions that forwards to taskPool.parallel``. The
purpose of these is to make parallel foreach less verbose and more
readable.
Example
// Find the logarithm of every number from
// 1 to 1_000_000 in parallel, using the
// default TaskPool instance.
auto logs = new double[1_000_000];
foreach (i, ref elem; parallel(logs))
{
elem = log(i + 1.0);
}
parallel;
import (package) stdstd.(module) std.processFunctions for starting and interacting with other processes, and for
working with the current process' execution environment.
Process handling
`spawnProcess` spawns a new `process`, optionally assigning it an
arbitrary set of standard input, output, and error streams.
The function returns immediately, leaving the child process to execute
in parallel with its parent. All other functions in this module that
spawn processes are built around spawnProcess.
`wait` makes the parent `process` wait for a child `process` to
terminate. In general one should always do this, to avoid
child processes becoming "zombies" when the parent process exits.
Scope guards are perfect for this – see the spawnProcess
documentation for examples. tryWait is similar to wait,
but does not block if the process has not yet terminated.
`pipeProcess` also spawns a child `process` which runs
in parallel with its parent. However, instead of taking
arbitrary streams, it automatically creates a set of
pipes that allow the parent to communicate with the child
through the child's standard input, output, and/or error streams.
This function corresponds roughly to C's popen function.
`execute` starts a new `process` and waits for it
to complete before returning. Additionally, it captures
the process' standard output and error streams and returns
the output of these as a string.
`spawnShell`, `pipeShell` and `executeShell` work like
spawnProcess, pipeProcess and execute, respectively,
except that they take a single command string and run it through
the current user's default command interpreter.
executeShell corresponds roughly to C's system function.
`kill` attempts to terminate a running `process`.
The following table compactly summarises the different process creation
functions and how they relate to each other:
Runs program directly
Runs shell command Low-level process creation spawnProcess spawnShell Automatic input/output redirection using pipes pipeProcess pipeShell Execute and wait for completion, collect output execute executeShell
Other functionality
`pipe` is used to create unidirectional pipes.
`environment` is an interface through which the current `process`'
environment variables can be read and manipulated.
`escapeShellCommand` and `escapeShellFileName` are useful
for constructing shell command lines in a portable way.
Source
std/process.d
Note
Most of the functionality in this module is not available on iOS, tvOS
and watchOS. The only functions available on those platforms are:
environment, thisProcessID and thisThreadID.
process : (alias) font_libraries_font_scan_timing.execute = std.typecons.Tuple!(int, "status", string, "output") std.process.execute(scope const(char[])[] args, const(string[string]) env = cast(const(string[string]))null, std.process.Config config = Config(Flags.none, null, null), ulong maxOutput = 18446744073709551615LU, scope const(char)[] workDir = null) @safeExecutes the given program or shell command and returns its exit
code and output.
execute and executeShell start a new process using
spawnProcess and spawnShell, respectively, and wait
for the process to complete before returning. The functions capture
what the child process prints to both its standard output and
standard error streams, and return this together with its exit code.
auto dmd = execute(["dmd", "myapp.d"]);
if (dmd.status != 0) writeln("Compilation failed:\n", dmd.output);
auto ls = executeShell("ls -l");
if (ls.status != 0) writeln("Failed to retrieve file listing");
else writeln(ls.output);
The args/program/command, env and config
parameters are forwarded straight to the underlying spawn functions,
and we refer to their documentation for details.
POSIX specific
If the process is terminated by a signal, the status field of
the return value will contain a negative number whose absolute
value is the signal number. (See wait for details.)
execute;
import (package) stdstd.(module) std.rangeThis module defines the notion of a range. Ranges generalize the concept of
arrays, lists, or anything that involves sequential access. This abstraction
enables the same set of algorithms (see std.algorithm) to be used
with a vast variety of different concrete types. For example,
a linear search algorithm such as find
works not just for arrays, but for linked-lists, input files,
incoming network data, etc.
Guides
There are many articles available that can bolster understanding ranges:
Ali Çehreli's tutorial on ranges
for the basics of working with and creating range-based code.
Jonathan M. Davis Introduction to Ranges
talk at DConf 2015 a vivid introduction from its core constructs to practical advice.
The DLang Tour's chapter on ranges
for an interactive introduction.
H. S. Teoh's tutorial on
component programming with ranges for a real-world showcase of the influence
of range-based programming on complex algorithms.
Andrei Alexandrescu's article
On Iteration for conceptual aspect of ranges and the motivation
Submodules
This module has two submodules:
The std.range.primitives submodule
provides basic range functionality. It defines several templates for testing
whether a given object is a range, what kind of range it is, and provides
some common range operations.
The std.range.interfaces submodule
provides object-based interfaces for working with ranges via runtime
polymorphism.
The remainder of this module provides a rich set of range creation and
composition templates that let you construct new ranges out of existing ranges:
| chain |
Concatenates several ranges into a single range.
|
| choose |
Chooses one of two ranges at runtime based on a boolean condition.
|
| chooseAmong |
Chooses one of several ranges at runtime based on an index.
|
| chunks |
Creates a range that returns fixed-size chunks of the original
range.
|
| cycle |
Creates an infinite range that repeats the given forward range
indefinitely. Good for implementing circular buffers.
|
| drop |
Creates the range that results from discarding the first n
elements from the given range.
|
| dropBack |
Creates the range that results from discarding the last n
elements from the given range.
|
| dropExactly |
Creates the range that results from discarding exactly n
of the first elements from the given range.
|
| dropBackExactly |
Creates the range that results from discarding exactly n
of the last elements from the given range.
|
| dropOne |
Creates the range that results from discarding
the first element from the given range.
|
| dropBackOne |
Creates the range that results from discarding
the last element from the given range.
|
| enumerate |
Iterates a range with an attached index variable.
|
| evenChunks |
Creates a range that returns a number of chunks of
approximately equal length from the original range.
|
| frontTransversal |
Creates a range that iterates over the first elements of the
given ranges.
|
| generate |
Creates a range by successive calls to a given function. This
allows to create ranges as a single delegate.
|
| indexed |
Creates a range that offers a view of a given range as though
its elements were reordered according to a given range of indices.
|
| iota |
Creates a range consisting of numbers between a starting point
and ending point, spaced apart by a given interval.
|
| lockstep |
Iterates n ranges in lockstep, for use in a foreach
loop. Similar to zip, except that lockstep is designed
especially for foreach loops.
|
| nullSink |
An output range that discards the data it receives.
|
| only |
Creates a range that iterates over the given arguments.
|
| padLeft |
Pads a range to a specified length by adding a given element to
the front of the range. Is lazy if the range has a known length.
|
| padRight |
Lazily pads a range to a specified length by adding a given element to
the back of the range.
|
| radial |
Given a random-access range and a starting point, creates a
range that alternately returns the next left and next right element to
the starting point.
|
| recurrence |
Creates a forward range whose values are defined by a
mathematical recurrence relation.
|
| refRange |
Pass a range by reference. Both the original range and the RefRange
will always have the exact same elements.
Any operation done on one will affect the other.
|
| repeat |
Creates a range that consists of a single element repeated n
times, or an infinite range repeating that element indefinitely.
|
| retro |
Iterates a bidirectional range backwards.
|
| roundRobin |
Given n ranges, creates a new range that return the n
first elements of each range, in turn, then the second element of each
range, and so on, in a round-robin fashion.
|
| sequence |
Similar to recurrence, except that a random-access range is
created.
|
| slide |
Creates a range that returns a fixed-size sliding window
over the original range. Unlike chunks,
it advances a configurable number of items at a time,
not one chunk at a time.
|
| stride |
Iterates a range with stride n.
|
| tail |
Return a range advanced to within n elements of the end of
the given range.
|
| take |
Creates a sub-range consisting of only up to the first n
elements of the given range.
|
| takeExactly |
Like take, but assumes the given range actually has n
elements, and therefore also defines the length property.
|
| takeNone |
Creates a random-access range consisting of zero elements of the
given range.
|
| takeOne |
Creates a random-access range consisting of exactly the first
element of the given range.
|
| tee |
Creates a range that wraps a given range, forwarding along
its elements while also calling a provided function with each element.
|
| transposed |
Transposes a range of ranges.
|
| transversal |
Creates a range that iterates over the n'th elements of the
given random-access ranges.
|
| zip |
Given n ranges, creates a range that successively returns a
tuple of all the first elements, a tuple of all the second elements,
etc.
|
Sortedness
Ranges whose elements are sorted afford better efficiency with certain
operations. For this, the assumeSorted function can be used to
construct a SortedRange from a pre-sorted range. The sort function also conveniently
returns a SortedRange. SortedRange objects provide some additional
range operations that take advantage of the fact that the range is sorted.
Source
std/range/package.d
range : (alias template) font_libraries_font_scan_timing.walkLength = std.range.primitives.walkLength(Range)(Range range) if (isInputRange!Range && !isInfinite!Range)This is a best-effort implementation of length for any kind of
range.
If hasLength!Range, simply returns range.length without
checking upTo (when specified).
Otherwise, walks the range through its length and returns the number
of elements seen. Performes O(n) evaluations of range.empty
and range.popFront(), where n is the effective length of range.
The upTo parameter is useful to "cut the losses" in case
the interest is in seeing whether the range has at least some number
of elements. If the parameter upTo is specified, stops if upTo steps have been taken and returns upTo.
Infinite ranges are compatible, provided the parameter upTo is
specified, in which case the implementation simply returns upTo.
walkLength;
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) font_libraries_font_scan_timing.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))Equivalent to writef(fmt, args, '\n').
writefln, (alias template) font_libraries_font_scan_timing.writeln = std.stdio.writeln(T...)(T args)Equivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln;
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) font_libraries_font_scan_timing.lineSplitter = std.string.lineSplitter(Flag keepTerm = No.keepTerminator, Range)(Range r) if (hasSlicing!Range && hasLength!Range && isSomeChar!(ElementType!Range) && !isSomeString!Range)Split an array or slicable range of characters into a range of lines
using '\r', '\n', '\v', '\f', "\r\n",
lineSep, paraSep and '\u0085' (NEL)
as delimiters. If keepTerm is set to Yes.keepTerminator, then the
delimiter is included in the slices returned.
Does not throw on invalid UTF; such is simply passed unchanged
to the output.
Adheres to Unicode 7.0.
Does not allocate memory.
lineSplitter, (alias template) font_libraries_font_scan_timing.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) font_libraries_font_scan_timing.toStringz = immutable(char)* std.string.toStringz(scope const(char)[] s) pure nothrow @trustedtoStringz;
/// What a catalog keeps per face.
struct (struct) font_libraries_font_scan_timing.FaceRecordWhat a catalog keeps per face.
FaceRecord
{
(alias) object.string = stringstring (field) string font_libraries_font_scan_timing.FaceRecord.familyfamily;
uint (field) uint font_libraries_font_scan_timing.FaceRecord.weightClassweightClass;
uint (field) uint font_libraries_font_scan_timing.FaceRecord.codepointscodepoints, (field) uint font_libraries_font_scan_timing.FaceRecord.rangesranges;
bool (field) bool font_libraries_font_scan_timing.FaceRecord.hasCmaphasCmap;
}
uint uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16(const(ubyte)[] (parameter) const(ubyte)[] dd, (alias) object.size_t = ulongsize_t (parameter) ulong oo) @safe pure nothrow @nogc
=> (parameter) ulong oo + 2 <= (parameter) const(ubyte)[] dd.(field) ulong const(ubyte)[].lengthlength ? ((parameter) const(ubyte)[] dd[(parameter) ulong oo] << 8) | (parameter) const(ubyte)[] dd[(parameter) ulong oo + 1] : 0;
uint uint font_libraries_font_scan_timing.u32(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu32(const(ubyte)[] (parameter) const(ubyte)[] dd, (alias) object.size_t = ulongsize_t (parameter) ulong oo) @safe pure nothrow @nogc
=> (parameter) ulong oo + 4 <= (parameter) const(ubyte)[] dd.(field) ulong const(ubyte)[].lengthlength
? (uint((parameter) const(ubyte)[] dd[(parameter) ulong oo]) << 24) | ((parameter) const(ubyte)[] dd[(parameter) ulong oo + 1] << 16) | ((parameter) const(ubyte)[] dd[(parameter) ulong oo + 2] << 8) | (parameter) const(ubyte)[] dd[(parameter) ulong oo + 3] : 0;
/// The table `tag` of the face whose directory starts at `dir`, or `null`.
const(ubyte)[] const(ubyte)[] font_libraries_font_scan_timing.table(const(ubyte)[] d, ulong dir, string tag) pure nothrow @nogc @safeThe table tag of the face whose directory starts at dir, or null.
table(const(ubyte)[] (parameter) const(ubyte)[] dd, (alias) object.size_t = ulongsize_t (parameter) ulong dirdir, (alias) object.string = stringstring (parameter) string tagtag) @safe pure nothrow @nogc
{
const (local variable) const(uint) tt = (uint((parameter) string tagtag[0]) << 24) | ((parameter) string tagtag[1] << 16) | ((parameter) string tagtag[2] << 8) | (parameter) string tagtag[3];
foreach ((local variable) uint ii; 0 .. uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] dd, (parameter) ulong dirdir + 4))
{
const (local variable) const(ulong) rr = (parameter) ulong dirdir + 12 + (local variable) uint ii * 16;
if (uint font_libraries_font_scan_timing.u32(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu32((parameter) const(ubyte)[] dd, (local variable) const(ulong) rr) != (local variable) const(uint) tt)
continue;
const (local variable) const(ulong) offoff = (ulong) ulongsize_t(uint font_libraries_font_scan_timing.u32(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu32((parameter) const(ubyte)[] dd, (local variable) const(ulong) rr + 8)), (local variable) const(ulong) lenlen = (ulong) ulongsize_t(uint font_libraries_font_scan_timing.u32(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu32((parameter) const(ubyte)[] dd, (local variable) const(ulong) rr + 12));
return (local variable) const(ulong) offoff + (local variable) const(ulong) lenlen <= (parameter) const(ubyte)[] dd.(field) ulong const(ubyte)[].lengthlength ? (parameter) const(ubyte)[] dd[(local variable) const(ulong) offoff .. (local variable) const(ulong) offoff + (local variable) const(ulong) lenlen] : null;
}
return null;
}
/// Counts the code points and ranges of the best Unicode subtable:
/// format 12 (full repertoire) over format 4 (BMP).
void void font_libraries_font_scan_timing.readCoverage(const(ubyte)[] cmap, ref font_libraries_font_scan_timing.FaceRecord rec) pure nothrow @nogc @safeCounts the code points and ranges of the best Unicode subtable:
format 12 (full repertoire) over format 4 (BMP).
readCoverage(const(ubyte)[] (parameter) const(ubyte)[] cmapcmap, ref (struct) font_libraries_font_scan_timing.FaceRecordWhat a catalog keeps per face.
FaceRecord (parameter) font_libraries_font_scan_timing.FaceRecord recrec) @safe pure nothrow @nogc
{
(alias) object.size_t = ulongsize_t (local variable) ulong bestbest;
int (local variable) int bestScorebestScore;
foreach ((local variable) uint ii; 0 .. uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] cmapcmap, 2))
{
const (local variable) const(uint) platformplatform = uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] cmapcmap, 4 + (local variable) uint ii * 8), (local variable) const(uint) encodingencoding = uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] cmapcmap, 6 + (local variable) uint ii * 8);
const (local variable) const(uint) offoff = uint font_libraries_font_scan_timing.u32(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu32((parameter) const(ubyte)[] cmapcmap, 8 + (local variable) uint ii * 8), (local variable) const(uint) formatformat = uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] cmapcmap, (local variable) const(uint) offoff);
const (local variable) const(bool) unicodeunicode = (local variable) const(uint) platformplatform == 0 || ((local variable) const(uint) platformplatform == 3 && ((local variable) const(uint) encodingencoding == 1 || (local variable) const(uint) encodingencoding == 10));
const (local variable) const(int) scorescore = !(local variable) const(bool) unicodeunicode ? 0 : (local variable) const(uint) formatformat == 12 ? 2 : (local variable) const(uint) formatformat == 4 ? 1 : 0;
if ((local variable) const(int) scorescore > (local variable) int bestScorebestScore)
{
(local variable) int bestScorebestScore = (local variable) const(int) scorescore;
(local variable) ulong bestbest = (local variable) const(uint) offoff;
}
}
(parameter) font_libraries_font_scan_timing.FaceRecord recrec.(field) bool font_libraries_font_scan_timing.FaceRecord.hasCmaphasCmap = (local variable) int bestScorebestScore > 0;
uint (local variable) uint nextnext = uint.(constant) uint uint.max = 4294967295umax;
void void font_libraries_font_scan_timing.readCoverage.add(uint lo, uint hi) pure nothrow @nogc @safeadd(uint (parameter) uint lolo, uint (parameter) uint hihi)
{
(parameter) font_libraries_font_scan_timing.FaceRecord recrec.(field) uint font_libraries_font_scan_timing.FaceRecord.codepointscodepoints += (parameter) uint hihi - (parameter) uint lolo + 1;
if ((parameter) uint lolo != (local variable) uint nextnext)
++(parameter) font_libraries_font_scan_timing.FaceRecord recrec.(field) uint font_libraries_font_scan_timing.FaceRecord.rangesranges;
(local variable) uint nextnext = (parameter) uint hihi + 1;
}
if ((local variable) int bestScorebestScore == 1)
{
const (local variable) const(uint) segX2segX2 = uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] cmapcmap, (local variable) ulong bestbest + 6);
foreach ((local variable) uint ss; 0 .. (local variable) const(uint) segX2segX2 / 2)
{
const (local variable) const(uint) endend = uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] cmapcmap, (local variable) ulong bestbest + 14 + (local variable) uint ss * 2), (local variable) const(uint) startstart = uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] cmapcmap, (local variable) ulong bestbest + 16 + (local variable) const(uint) segX2segX2 + (local variable) uint ss * 2);
if ((local variable) const(uint) startstart <= (local variable) const(uint) endend && (local variable) const(uint) startstart != 0xFFFF)
void font_libraries_font_scan_timing.readCoverage.add(uint lo, uint hi) pure nothrow @nogc @safeadd((local variable) const(uint) startstart, (local variable) const(uint) endend);
}
}
else if ((local variable) int bestScorebestScore == 2)
foreach ((local variable) uint gg; 0 .. uint font_libraries_font_scan_timing.u32(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu32((parameter) const(ubyte)[] cmapcmap, (local variable) ulong bestbest + 12))
{
const (local variable) const(uint) lolo = uint font_libraries_font_scan_timing.u32(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu32((parameter) const(ubyte)[] cmapcmap, (local variable) ulong bestbest + 16 + (local variable) uint gg * 12), (local variable) const(uint) hihi = uint font_libraries_font_scan_timing.u32(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu32((parameter) const(ubyte)[] cmapcmap, (local variable) ulong bestbest + 20 + (local variable) uint gg * 12);
if ((local variable) const(uint) lolo <= (local variable) const(uint) hihi && (local variable) const(uint) hihi <= 0x10FFFF)
void font_libraries_font_scan_timing.readCoverage.add(uint lo, uint hi) pure nothrow @nogc @safeadd((local variable) const(uint) lolo, (local variable) const(uint) hihi);
}
}
/// The typographic family (name ID 16), else the family (ID 1), Windows platform.
(alias) object.string = stringstring string font_libraries_font_scan_timing.familyName(const(ubyte)[] name) pure @safeThe typographic family (name ID 16), else the family (ID 1), Windows platform.
familyName(const(ubyte)[] (parameter) const(ubyte)[] namename) @safe pure
{
const (local variable) const(uint) stringsstrings = uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] namename, 4);
(alias) object.string = stringstring (local variable) string foundfound;
foreach ((local variable) uint ii; 0 .. uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] namename, 2))
{
const (local variable) const(uint) rr = 6 + (local variable) uint ii * 12, (local variable) const(uint) idid = uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] namename, (local variable) const(uint) rr + 6);
if (uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] namename, (local variable) const(uint) rr) != 3 || ((local variable) const(uint) idid != 1 && (local variable) const(uint) idid != 16))
continue;
const (local variable) const(uint) startstart = (local variable) const(uint) stringsstrings + uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] namename, (local variable) const(uint) rr + 10), (local variable) const(uint) lenlen = uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] namename, (local variable) const(uint) rr + 8);
if ((local variable) const(uint) startstart + (local variable) const(uint) lenlen > (parameter) const(ubyte)[] namename.(field) ulong const(ubyte)[].lengthlength)
continue;
wchar[] (local variable) wchar[] utf16utf16;
foreach ((local variable) uint kk; 0 .. (local variable) const(uint) lenlen / 2)
(local variable) wchar[] utf16utf16 ~= cast(wchar) uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16((parameter) const(ubyte)[] namename, (local variable) const(uint) startstart + (local variable) uint kk * 2);
(local variable) string foundfound = (local variable) wchar[] utf16utf16.string std.conv.to!string.to!(wchar[])(wchar[] __param_0) pure @safeThe to template converts a value from one type to another.
The source type is deduced and the target type must be specified, for example the
expression to`!int(42.0)` converts the number 42 from
`double` to `int`. The conversion is "safe", i.e.,
it checks for overflow; to!int(4.2e10) would throw the
ConvOverflowException exception. Overflow checks are only
inserted when necessary, e.g., ``to!double(42) does not do
any checking because any int fits in a double.
Conversions from string to numeric types differ from the C equivalents
atoi() and atol() by checking for overflow and not allowing whitespace.
For conversion of strings to signed types, the grammar recognized is:
Integer:
Sign UnsignedInteger
UnsignedInteger
Sign:
+
-
For conversion to unsigned types, the grammar recognized is:
UnsignedInteger:
DecimalDigit
DecimalDigit UnsignedInteger
Examples
Converting a value to its own type (useful mostly for generic code)
simply returns its argument.
int a = 42;
int b = to!int(a);
double c = to!double(3.14); // c is double with value 3.14
Converting among numeric types is a safe way to cast them around.
Conversions from floating-point types to integral types allow loss of
precision (the fractional part of a floating-point number). The
conversion is truncating towards zero, the same way a cast would
truncate. (To round a floating point value when casting to an
integral, use roundTo.)
import std.exception : assertThrown;
int a = 420;
assert(to!long(a) == a);
assertThrown!ConvOverflowException(to!byte(a));
assert(to!int(4.2e6) == 4200000);
assertThrown!ConvOverflowException(to!uint(-3.14));
assert(to!uint(3.14) == 3);
assert(to!uint(3.99) == 3);
assert(to!int(-3.99) == -3);
When converting strings to numeric types, note that D hexadecimal and binary
literals are not handled. Neither the prefixes that indicate the base, nor the
horizontal bar used to separate groups of digits are recognized. This also
applies to the suffixes that indicate the type.
To work around this, you can specify a radix for conversions involving numbers.
auto str = to!string(42, 16);
assert(str == "2A");
auto i = to!int(str, 16);
assert(i == 42);
Conversions from integral types to floating-point types always
succeed, but might lose accuracy. The largest integers with a
predecessor representable in floating-point format are 2^24-1 for
float, 2^53-1 for double, and 2^64-1 for real (when
real is 80-bit, e.g. on Intel machines).
// 2^24 - 1, largest proper integer representable as float
int a = 16_777_215;
assert(to!int(to!float(a)) == a);
assert(to!int(to!float(-a)) == -a);
Conversion from string types to char types enforces the input
to consist of a single code point, and said code point must
fit in the target type. Otherwise, ConvException is thrown.
import std.exception : assertThrown;
assert(to!char("a") == 'a');
assertThrown(to!char("ñ")); // 'ñ' does not fit into a char
assert(to!wchar("ñ") == 'ñ');
assertThrown(to!wchar("😃")); // '😃' does not fit into a wchar
assert(to!dchar("😃") == '😃');
// Using wstring or dstring as source type does not affect the result
assert(to!char("a"w) == 'a');
assert(to!char("a"d) == 'a');
// Two code points cannot be converted to a single one
assertThrown(to!char("ab"));
Converting an array to another array type works by converting each
element in turn. Associative arrays can be converted to associative
arrays as long as keys and values can in turn be converted.
import std.string : split;
int[] a = [1, 2, 3];
auto b = to!(float[])(a);
assert(b == [1.0f, 2, 3]);
string str = "1 2 3 4 5 6";
auto numbers = to!(double[])(split(str));
assert(numbers == [1.0, 2, 3, 4, 5, 6]);
int[string] c;
c["a"] = 1;
c["b"] = 2;
auto d = to!(double[wstring])(c);
assert(d["a"w] == 1 && d["b"w] == 2);
Conversions operate transitively, meaning that they work on arrays and
associative arrays of any complexity.
This conversion works because to`!short` applies to an `int`, to!wstring
applies to a string, to`!string` applies to a `double`, and
to!(double[]) applies to an int[]. The conversion might throw an
exception because ``to!short might fail the range check.
int[string][double[int[]]] a;
auto b = to!(short[wstring][string[double[]]])(a);
Object-to-object conversions by dynamic casting throw exception when
the source is non-null and the target is null.
import std.exception : assertThrown;
// Testing object conversions
class A {}
class B : A {}
class C : A {}
A a1 = new A, a2 = new B, a3 = new C;
assert(to!B(a2) is a2);
assert(to!C(a3) is a3);
assertThrown!ConvException(to!B(a3));
Stringize conversion from all types is supported.
String to string conversion works for any two string types having
(char, wchar, dchar) character widths and any
combination of qualifiers (mutable, const, or immutable).
Converts array (other than strings) to string.
Each element is converted by calling ``to!T.
Associative array to string conversion.
Each element is converted by calling ``to!T.
Object to string conversion calls toString against the object or
returns "null" if the object is null.
Struct to string conversion calls toString against the struct if
it is defined.
For structs that do not define toString, the conversion to string
produces the list of fields.
Enumerated types are converted to strings as their symbolic names.
Boolean values are converted to "true" or "false".
char, wchar, dchar to a string type.
Unsigned or signed integers to strings.
[special case]
: Convert integral value to string in radix radix.
radix must be a value from 2 to 36.
value is treated as a signed value only if radix is 10.
The characters A through Z are used to represent values 10 through 36
and their case is determined by the letterCase parameter.
All floating point types to all string types.
Pointer to string conversions convert the pointer to a size_t value.
If pointer is char*, treat it as C-style strings.
In that case, this function is @system.
See formatValue on how toString should be defined.
// Conversion representing dynamic/static array with string
long[] a = [ 1, 3, 5 ];
assert(to!string(a) == "[1, 3, 5]");
// Conversion representing associative array with string
int[string] associativeArray = ["0":1, "1":2];
assert(to!string(associativeArray) == `["0":1, "1":2]` ||
to!string(associativeArray) == `["1":2, "0":1]`);
// char* to string conversion
assert(to!string(cast(char*) null) == "");
assert(to!string("foo\0".ptr) == "foo");
// Conversion reinterpreting void array to string
auto w = "abcx"w;
const(void)[] b = w;
assert(b.length == 8);
auto c = to!(wchar[])(b);
assert(c == "abcx");
Strings can be converted to enum types. The enum member with the same name as the
input string is returned. The comparison is case-sensitive.
A ConvException is thrown if the enum does not have the specified member.
import std.exception : assertThrown;
enum E { a, b, c }
assert(to!E("a") == E.a);
assert(to!E("b") == E.b);
assertThrown!ConvException(to!E("A"));
to!(alias) object.string = stringstring;
if ((local variable) const(uint) idid == 16)
break;
}
return (local variable) string foundfound;
}
(struct) font_libraries_font_scan_timing.FaceRecordWhat a catalog keeps per face.
FaceRecord[] font_libraries_font_scan_timing.FaceRecord[] font_libraries_font_scan_timing.describe(const(ubyte)[] d) pure @safedescribe(const(ubyte)[] (parameter) const(ubyte)[] dd) @safe pure
{
(alias) object.size_t = ulongsize_t[] (local variable) ulong[] dirsdirs = uint font_libraries_font_scan_timing.u32(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu32((parameter) const(ubyte)[] dd, 0) == 0x74746366 // 'ttcf'
? ((alias) object.size_t = ulongsize_t (parameter) ulong nn) { (alias) object.size_t = ulongsize_t[] (local variable) ulong[] rr; foreach ((local variable) ulong ii; 0 .. (parameter) ulong nn) (local variable) ulong[] rr ~= uint font_libraries_font_scan_timing.u32(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu32((parameter) const(ubyte)[] dd, 12 + (local variable) ulong ii * 4); return (local variable) ulong[] rr; }(uint font_libraries_font_scan_timing.u32(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu32((parameter) const(ubyte)[] dd, 8))
: [(ulong) ulongsize_t(0)];
(struct) font_libraries_font_scan_timing.FaceRecordWhat a catalog keeps per face.
FaceRecord[] (local variable) font_libraries_font_scan_timing.FaceRecord[] facesfaces;
foreach ((parameter) ulong dirdir; (local variable) ulong[] dirsdirs)
{
(struct) font_libraries_font_scan_timing.FaceRecordWhat a catalog keeps per face.
FaceRecord (local variable) font_libraries_font_scan_timing.FaceRecord recrec;
void font_libraries_font_scan_timing.readCoverage(const(ubyte)[] cmap, ref font_libraries_font_scan_timing.FaceRecord rec) pure nothrow @nogc @safeCounts the code points and ranges of the best Unicode subtable:
format 12 (full repertoire) over format 4 (BMP).
readCoverage(const(ubyte)[] font_libraries_font_scan_timing.table(const(ubyte)[] d, ulong dir, string tag) pure nothrow @nogc @safeThe table tag of the face whose directory starts at dir, or null.
table((parameter) const(ubyte)[] dd, (local variable) ulong dirdir, "cmap"), (local variable) font_libraries_font_scan_timing.FaceRecord recrec);
(local variable) font_libraries_font_scan_timing.FaceRecord recrec.(field) string font_libraries_font_scan_timing.FaceRecord.familyfamily = string font_libraries_font_scan_timing.familyName(const(ubyte)[] name) pure @safeThe typographic family (name ID 16), else the family (ID 1), Windows platform.
familyName(const(ubyte)[] font_libraries_font_scan_timing.table(const(ubyte)[] d, ulong dir, string tag) pure nothrow @nogc @safeThe table tag of the face whose directory starts at dir, or null.
table((parameter) const(ubyte)[] dd, (local variable) ulong dirdir, "name"));
(local variable) font_libraries_font_scan_timing.FaceRecord recrec.(field) uint font_libraries_font_scan_timing.FaceRecord.weightClassweightClass = uint font_libraries_font_scan_timing.u16(const(ubyte)[] d, ulong o) pure nothrow @nogc @safeu16(const(ubyte)[] font_libraries_font_scan_timing.table(const(ubyte)[] d, ulong dir, string tag) pure nothrow @nogc @safeThe table tag of the face whose directory starts at dir, or null.
table((parameter) const(ubyte)[] dd, (local variable) ulong dirdir, "OS/2"), 4);
(local variable) font_libraries_font_scan_timing.FaceRecord[] facesfaces ~= (local variable) font_libraries_font_scan_timing.FaceRecord recrec;
}
return (local variable) font_libraries_font_scan_timing.FaceRecord[] facesfaces;
}
(struct) font_libraries_font_scan_timing.FaceRecordWhat a catalog keeps per face.
FaceRecord[] font_libraries_font_scan_timing.FaceRecord[] font_libraries_font_scan_timing.scanFile(string path) @trustedscanFile((alias) object.string = stringstring (parameter) string pathpath) @trusted
{
const (local variable) const(int) fdfd = open(int core.sys.posix.fcntl.open64(scope const(char*), int, ...) nothrow @nogcpath.immutable(char)* std.string.toStringz(scope const(char)[] s) pure nothrow @trustedExamples
import core.stdc.string : strlen;
import std.conv : to;
auto p = toStringz("foo");
assert(strlen(p) == 3);
const(char)[] foo = "abbzxyzzy";
p = toStringz(foo[3 .. 5]);
assert(strlen(p) == 2);
string test = "";
p = toStringz(test);
assert(*p == 0);
test = "\0";
p = toStringz(test);
assert(*p == 0);
test = "foo\0";
p = toStringz(test);
assert(p[0] == 'f' && p[1] == 'o' && p[2] == 'o' && p[3] == 0);
const string test2 = "";
p = toStringz(test2);
assert(*p == 0);
assert(toStringz([]) is toStringz(""));
toStringz, (constant) int core.sys.posix.fcntl.O_RDONLY = 0O_RDONLY);
if ((local variable) const(int) fdfd < 0)
return null;
scope (exit) int core.sys.posix.unistd.close(int) nothrow @nogc @trustedclose((local variable) const(int) fdfd);
(struct) core.sys.posix.sys.stat.stat_tstat_t (local variable) core.sys.posix.sys.stat.stat_t stst;
if (fstat(int core.sys.posix.sys.stat.fstat64(int, core.sys.posix.sys.stat.stat_t*) nothrow @nogc @trustedfd, &(local variable) core.sys.posix.sys.stat.stat_t stst) != 0 || (local variable) core.sys.posix.sys.stat.stat_t stst.(field) long core.sys.posix.sys.stat.stat_t.st_sizest_size < 12)
return null;
auto (local variable) void* pp = mmap(null, (local variable) core.sys.posix.sys.stat.stat_t stst.(field) long core.sys.posix.sys.stat.stat_t.st_sizest_size, (constant) int core.sys.posix.sys.mman.PROT_READ = 1PROT_READ, (constant) int core.sys.posix.sys.mman.MAP_PRIVATE = 2MAP_PRIVATE, (local variable) const(int) fdfd, 0);
if ((local variable) void* pp == (constant) void* core.sys.posix.sys.mman.MAP_FAILED = cast(void*)cast(size_t)18446744073709551615LUMAP_FAILED)
return null;
scope (exit) int core.sys.posix.sys.mman.munmap(void*, ulong) nothrow @nogcmunmap((local variable) void* pp, (local variable) core.sys.posix.sys.stat.stat_t stst.(field) long core.sys.posix.sys.stat.stat_t.st_sizest_size);
return font_libraries_font_scan_timing.FaceRecord[] font_libraries_font_scan_timing.describe(const(ubyte)[] d) pure @safedescribe((cast(const(ubyte)*) (local variable) void* pp)[0 .. (local variable) core.sys.posix.sys.stat.stat_t stst.(field) long core.sys.posix.sys.stat.stat_t.st_sizest_size]);
}
void void font_libraries_font_scan_timing.pass(string label, string[] paths, bool pooled)pass((alias) object.string = stringstring (parameter) string labellabel, (alias) object.string = stringstring[] (parameter) string[] pathspaths, bool (parameter) bool pooledpooled)
{
auto (local variable) font_libraries_font_scan_timing.FaceRecord[][] recordsrecords = new (struct) font_libraries_font_scan_timing.FaceRecordWhat a catalog keeps per face.
FaceRecord[][]((parameter) string[] pathspaths.(field) ulong string[].lengthlength);
auto (local variable) std.datetime.stopwatch.StopWatch swsw = (struct) std.datetime.stopwatch.StopWatchStopWatch is used to measure time just like one would do with a physical
stopwatch, including stopping, restarting, and/or resetting it.
MonoTime is used to hold the time, and it uses the system's
monotonic clock, which is high precision and never counts backwards (unlike
the wall clock time, which can count backwards, which is why
SysTime should not be used for timing).
Note that the precision of StopWatch differs from system to system. It is
impossible for it to be the same for all systems, since the precision of the
system clock and other system-dependent and situation-dependent factors
(such as the overhead of a context switch between threads) varies from
system to system and can affect StopWatch's accuracy.
Examples
Measure a time in milliseconds, microseconds, or nanoseconds
auto sw = StopWatch(AutoStart.no);
sw.start();
// ... Insert operations to be timed here ...
sw.stop();
long msecs = sw.peek.total!"msecs";
long usecs = sw.peek.total!"usecs";
long nsecs = sw.peek.total!"nsecs";
assert(usecs >= msecs * 1000);
assert(nsecs >= usecs * 1000);
import core.thread : Thread;
auto sw = StopWatch(AutoStart.yes);
Duration t1 = sw.peek();
Thread.sleep(usecs(1));
Duration t2 = sw.peek();
assert(t2 > t1);
Thread.sleep(usecs(1));
sw.stop();
Duration t3 = sw.peek();
assert(t3 > t2);
Duration t4 = sw.peek();
assert(t3 == t4);
sw.start();
Thread.sleep(usecs(1));
Duration t5 = sw.peek();
assert(t5 > t4);
// If stopping or resetting the StopWatch is not required, then
// MonoTime can easily be used by itself without StopWatch.
auto before = MonoTime.currTime;
// do stuff...
auto timeElapsed = MonoTime.currTime - before;
StopWatch(std.datetime.stopwatch.StopWatch std.datetime.stopwatch.StopWatch.this(std.typecons.Flag!"autoStart" autostart) nothrow @nogc ref @safeConstructs a StopWatch. Whether it starts immediately depends on the
AutoStart argument.
If StopWatch.init is used, then the constructed StopWatch isn't
running (and can't be, since no constructor ran).
Examples
import core.thread : Thread;
{
auto sw = StopWatch(AutoStart.yes);
assert(sw.running);
Thread.sleep(usecs(1));
assert(sw.peek() > Duration.zero);
}
{
auto sw = StopWatch(AutoStart.no);
assert(!sw.running);
Thread.sleep(usecs(1));
assert(sw.peek() == Duration.zero);
}
{
StopWatch sw;
assert(!sw.running);
Thread.sleep(usecs(1));
assert(sw.peek() == Duration.zero);
}
assert(StopWatch.init == StopWatch(AutoStart.no));
assert(StopWatch.init != StopWatch(AutoStart.yes));
AutoStart.(enum value) std.typecons.Flag!"autoStart".yes = trueyes);
if ((parameter) bool pooledpooled)
foreach ((foreach variable) ulong ii, (parameter) string pathpath; (parameter) string[] pathspaths.std.parallelism.ParallelForeach!(string[]) std.parallelism.parallel!(string[])(string[] range, ulong workUnitSize) @safeConvenience functions that forwards to taskPool.parallel``. The
purpose of these is to make parallel foreach less verbose and more
readable.
Example
// Find the logarithm of every number from
// 1 to 1_000_000 in parallel, using the
// default TaskPool instance.
auto logs = new double[1_000_000];
foreach (i, ref elem; parallel(logs))
{
elem = log(i + 1.0);
}
parallel(4))
(local variable) font_libraries_font_scan_timing.FaceRecord[][] recordsrecords[(foreach variable) ulong ii] = font_libraries_font_scan_timing.FaceRecord[] font_libraries_font_scan_timing.scanFile(string path) @trustedscanFile((local variable) string pathpath);
else
foreach ((parameter) ulong ii, (parameter) string pathpath; (parameter) string[] pathspaths)
(local variable) font_libraries_font_scan_timing.FaceRecord[][] recordsrecords[(local variable) ulong ii] = font_libraries_font_scan_timing.FaceRecord[] font_libraries_font_scan_timing.scanFile(string path) @trustedscanFile((local variable) string pathpath);
const (local variable) const(double) msms = (local variable) std.datetime.stopwatch.StopWatch swsw.core.time.Duration std.datetime.stopwatch.StopWatch.peek() const nothrow @nogc @safePeek at the amount of time that the StopWatch has been running.
This does not include any time during which the StopWatch was stopped but
does include all of the time that it was running and not just the
time since it was started last.
Calling reset will reset this to Duration.zero.
Examples
import core.thread : Thread;
auto sw = StopWatch(AutoStart.no);
assert(sw.peek() == Duration.zero);
sw.start();
Thread.sleep(usecs(1));
assert(sw.peek() >= usecs(1));
Thread.sleep(usecs(1));
assert(sw.peek() >= usecs(2));
sw.stop();
immutable stopped = sw.peek();
Thread.sleep(usecs(1));
assert(sw.peek() == stopped);
sw.start();
Thread.sleep(usecs(1));
assert(sw.peek() > stopped);
peek.long core.time.Duration.total!"usecs"() const pure nothrow @nogc @property @safeReturns the total number of the given units in this Duration.
So, unlike split, it does not strip out the larger units.
Examples
assert(dur!"weeks"(12).total!"weeks" == 12);
assert(dur!"weeks"(12).total!"days" == 84);
assert(dur!"days"(13).total!"weeks" == 1);
assert(dur!"days"(13).total!"days" == 13);
assert(dur!"hours"(49).total!"days" == 2);
assert(dur!"hours"(49).total!"hours" == 49);
assert(dur!"nsecs"(2007).total!"hnsecs" == 20);
assert(dur!"nsecs"(2007).total!"nsecs" == 2000);
total!"usecs" / 1000.0;
auto (local variable) font_libraries_font_scan_timing.FaceRecord[] facesfaces = (local variable) font_libraries_font_scan_timing.FaceRecord[][] recordsrecords.std.algorithm.iteration.joiner!(FaceRecord[][]).Result std.algorithm.iteration.joiner!(font_libraries_font_scan_timing.FaceRecord[][])(font_libraries_font_scan_timing.FaceRecord[][] r) pure nothrow @nogc @safeExamples
import std.algorithm.comparison : equal;
import std.range : repeat;
assert([""].joiner.equal(""));
assert(["", ""].joiner.equal(""));
assert(["", "abc"].joiner.equal("abc"));
assert(["abc", ""].joiner.equal("abc"));
assert(["abc", "def"].joiner.equal("abcdef"));
assert(["Mary", "has", "a", "little", "lamb"].joiner.equal("Maryhasalittlelamb"));
assert("abc".repeat(3).joiner.equal("abcabcabc"));
joiner allows in-place mutation!
import std.algorithm.comparison : equal;
auto a = [ [1, 2, 3], [42, 43] ];
auto j = joiner(a);
j.front = 44;
assert(a == [ [44, 2, 3], [42, 43] ]);
assert(equal(j, [44, 2, 3, 42, 43]));
insert characters fully lazily into a string
import std.algorithm.comparison : equal;
import std.range : chain, cycle, iota, only, retro, take, zip;
import std.format : format;
static immutable number = "12345678";
static immutable delimiter = ",";
auto formatted = number.retro
.zip(3.iota.cycle.take(number.length))
.map!(z => chain(z[0].only, z[1] == 2 ? delimiter : null))
.joiner
.retro;
static immutable expected = "12,345,678";
assert(formatted.equal(expected));
joiner can be bidirectional
import std.algorithm.comparison : equal;
import std.range : retro;
auto a = [[1, 2, 3], [4, 5]];
auto j = a.joiner;
j.back = 44;
assert(a == [[1, 2, 3], [4, 44]]);
assert(equal(j.retro, [44, 4, 3, 2, 1]));
joiner.font_libraries_font_scan_timing.FaceRecord[] std.array.array!(std.algorithm.iteration.joiner!(FaceRecord[][]).Result)(std.algorithm.iteration.joiner!(FaceRecord[][]).Result r) pure nothrow @safeAllocates an array and initializes it with copies of the elements
of range r.
Narrow strings are handled as follows:
If autodecoding is turned on (default), then they are handled as a separate overload.
If autodecoding is turned off, then this is equivalent to duplicating the array.
array;
void std.stdio.writefln!(char, string, ulong, ulong, const(double), double, ulong, ulong)(in char[] fmt, string __param_1, ulong __param_2, ulong __param_3, const(double) __param_4, double __param_5, ulong __param_6, ulong __param_7) @safeEquivalent to writef(fmt, args, '\n').
writefln("%-16s %5d files %5d faces %8.1f ms %6.1f us/file %4d families %d code points",
(parameter) string labellabel, (parameter) string[] pathspaths.(field) ulong string[].lengthlength, (local variable) font_libraries_font_scan_timing.FaceRecord[] facesfaces.(field) ulong font_libraries_font_scan_timing.FaceRecord[].lengthlength, (local variable) const(double) msms, (local variable) const(double) msms * 1000 / (parameter) string[] pathspaths.(field) ulong string[].lengthlength,
(local variable) font_libraries_font_scan_timing.FaceRecord[] facesfaces.font_libraries_font_scan_timing.pass.MapResult!(__lambda_L195_C20, FaceRecord[]) font_libraries_font_scan_timing.pass.map!(font_libraries_font_scan_timing.FaceRecord[])(font_libraries_font_scan_timing.FaceRecord[] r) pure nothrow @nogc @safeImplements the homonym function (also known as transform) present
in many languages of functional flavor. The call ``map!(fun)(range)
returns a range of which elements are obtained by applying fun(a)
left to right for all elements a in range. The original ranges are
not changed. Evaluation is done lazily.
Examples
import std.algorithm.comparison : equal;
import std.range : chain, only;
auto squares =
chain(only(1, 2, 3, 4), only(5, 6)).map!(a => a * a);
assert(equal(squares, only(1, 4, 9, 16, 25, 36)));
Multiple functions can be passed to map. In that case, the
element type of map is a tuple containing one element for each
function.
auto sums = [2, 4, 6, 8];
auto products = [1, 4, 9, 16];
size_t i = 0;
foreach (result; [ 1, 2, 3, 4 ].map!("a + a", "a * a"))
{
assert(result[0] == sums[i]);
assert(result[1] == products[i]);
++i;
}
You may alias map with some function(s) to a symbol and use
it separately:
import std.algorithm.comparison : equal;
import std.conv : to;
alias stringize = map!(to!string);
assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ]));
map!(f => f.family).string[] std.array.array!(font_libraries_font_scan_timing.pass.MapResult!(__lambda_L195_C20, FaceRecord[]))(font_libraries_font_scan_timing.pass.MapResult!(__lambda_L195_C20, FaceRecord[]) r) pure @safeAllocates an array and initializes it with copies of the elements
of range r.
Narrow strings are handled as follows:
If autodecoding is turned on (default), then they are handled as a separate overload.
If autodecoding is turned off, then this is equivalent to duplicating the array.
array.std.range.SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted) std.algorithm.sorting.sort!("a < b", SwapStrategy.unstable, string[])(string[] r) pure nothrow @nogc @safeSorts a random-access range according to the predicate less.
Performs O(r.length * log(r.length)) evaluations of less. If less involves
expensive computations on the sort key, it may be worthwhile to use
schwartzSort instead.
Stable sorting requires hasAssignableElements!Range to be true.
sort returns a SortedRange over the original range,
allowing functions that can take advantage of sorted data to know that the
range is sorted and adjust accordingly. The SortedRange is a
wrapper around the original range, so both it and the original range are sorted.
Other functions can't know that the original range has been sorted, but
they can know that SortedRange has been sorted.
Preconditions
The predicate is expected to satisfy certain rules in order for sort to
behave as expected - otherwise, the program may fail on certain inputs (but not
others) when not compiled in release mode, due to the cursory assumeSorted
check. Specifically, sort expects less(a,b) && less(b,c) to imply
less(a,c) (transitivity), and, conversely, !less(a,b) && !less(b,c) to
imply !less(a,c). Note that the default predicate ("a < b") does not
always satisfy these conditions for floating point types, because the expression
will always be false when either a or b is NaN.
Use cmp instead.
Algorithms
Introsort is used for unstable sorting and
Timsort is used for stable sorting.
Each algorithm has benefits beyond stability. Introsort is generally faster but
Timsort may achieve greater speeds on data with low entropy or if predicate calls
are expensive. Introsort performs no allocations whereas Timsort will perform one
or more allocations per call. Both algorithms have O(n log n) worst-case
time complexity.
Examples
int[] array = [ 1, 2, 3, 4 ];
// sort in descending order
array.sort!("a > b");
assert(array == [ 4, 3, 2, 1 ]);
// sort in ascending order
array.sort();
assert(array == [ 1, 2, 3, 4 ]);
// sort with reusable comparator and chain
alias myComp = (x, y) => x > y;
assert(array.sort!(myComp).release == [ 4, 3, 2, 1 ]);
// Showcase stable sorting
import std.algorithm.mutation : SwapStrategy;
string[] words = [ "aBc", "a", "abc", "b", "ABC", "c" ];
sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable)(words);
assert(words == [ "a", "aBc", "abc", "ABC", "b", "c" ]);
// Sorting floating-point numbers in presence of NaN
double[] numbers = [-0.0, 3.0, -2.0, double.nan, 0.0, -double.nan];
import std.algorithm.comparison : equal;
import std.math.operations : cmp;
import std.math.traits : isIdentical;
sort!((a, b) => cmp(a, b) < 0)(numbers);
double[] sorted = [-double.nan, -2.0, -0.0, 0.0, 3.0, double.nan];
assert(numbers.equal!isIdentical(sorted));
sort.std.algorithm.iteration.UniqResult!(binaryFun, SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted)) std.algorithm.iteration.uniq!("a == b", std.range.SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted))(std.range.SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted) r) pure nothrow @nogc @safeLazily iterates unique consecutive elements of the given range, which is
assumed to be sorted (functionality akin to the
uniq system
utility). Equivalence of elements is assessed by using the predicate
pred, by default "a == b". The predicate is passed to
binaryFun, and can either accept a string, or any callable
that can be executed via pred(element, element). If the given range is
bidirectional, uniq also yields a
bidirectional range.
Examples
import std.algorithm.comparison : equal;
import std.algorithm.mutation : copy;
int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];
assert(equal(uniq(arr), [ 1, 2, 3, 4, 5 ][]));
// Filter duplicates in-place using copy
arr.length -= arr.uniq().copy(arr).length;
assert(arr == [ 1, 2, 3, 4, 5 ]);
// Note that uniqueness is only determined consecutively; duplicated
// elements separated by an intervening different element will not be
// eliminated:
assert(equal(uniq([ 1, 1, 2, 1, 1, 3, 1]), [1, 2, 1, 3, 1]));
uniq.ulong std.range.primitives.walkLength!(std.algorithm.iteration.UniqResult!(binaryFun, SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted)))(std.algorithm.iteration.UniqResult!(binaryFun, SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted)) range) pure nothrow @nogc @safeThis is a best-effort implementation of length for any kind of
range.
If hasLength!Range, simply returns ``range.length without
checking upTo (when specified).
Otherwise, walks the range through its length and returns the number
of elements seen. Performes O(n) evaluations of range`.empty`
and range.popFront(), where n is the effective length of range.
The upTo parameter is useful to "cut the losses" in case
the interest is in seeing whether the range has at least some number
of elements. If the parameter upTo is specified, stops if upTo steps have been taken and returns upTo.
Infinite ranges are compatible, provided the parameter upTo is
specified, in which case the implementation simply returns upTo.
walkLength,
(local variable) font_libraries_font_scan_timing.FaceRecord[] facesfaces.font_libraries_font_scan_timing.pass.MapResult!(__lambda_L196_C20, FaceRecord[]) font_libraries_font_scan_timing.pass.map!(font_libraries_font_scan_timing.FaceRecord[])(font_libraries_font_scan_timing.FaceRecord[] r) pure nothrow @nogc @safeImplements the homonym function (also known as transform) present
in many languages of functional flavor. The call ``map!(fun)(range)
returns a range of which elements are obtained by applying fun(a)
left to right for all elements a in range. The original ranges are
not changed. Evaluation is done lazily.
Examples
import std.algorithm.comparison : equal;
import std.range : chain, only;
auto squares =
chain(only(1, 2, 3, 4), only(5, 6)).map!(a => a * a);
assert(equal(squares, only(1, 4, 9, 16, 25, 36)));
Multiple functions can be passed to map. In that case, the
element type of map is a tuple containing one element for each
function.
auto sums = [2, 4, 6, 8];
auto products = [1, 4, 9, 16];
size_t i = 0;
foreach (result; [ 1, 2, 3, 4 ].map!("a + a", "a * a"))
{
assert(result[0] == sums[i]);
assert(result[1] == products[i]);
++i;
}
You may alias map with some function(s) to a symbol and use
it separately:
import std.algorithm.comparison : equal;
import std.conv : to;
alias stringize = map!(to!string);
assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ]));
map!(f => ulong(f.codepoints)).ulong std.algorithm.iteration.sum!(font_libraries_font_scan_timing.pass.MapResult!(__lambda_L196_C20, FaceRecord[]))(font_libraries_font_scan_timing.pass.MapResult!(__lambda_L196_C20, FaceRecord[]) r) pure nothrow @nogc @safeSums elements of r, which must be a finite
input range. Although
conceptually sum`(`r`)` is equivalent to `fold`!((a, b) => a +
b)(`r`, 0), sum`` uses specialized algorithms to maximize accuracy,
as follows.
If ElementType!R is a floating-point
type and R is a
random-access range with
length and slicing, then sum uses the
pairwise summation
algorithm.
If ElementType!R is a floating-point type and R is a
finite input range (but not a random-access range with slicing), then
sum uses the Kahan summation algorithm.
In all other cases, a simple element by element addition is done.
For floating point inputs, calculations are made in
spec/type, Types, real
precision for real inputs and in double precision otherwise
(Note this is a special case that deviates from fold's behavior,
which would have kept float precision for a float range).
For all other types, the calculations are done in the same type obtained
from from adding two elements of the range, which may be a different
type from the elements themselves (for example, in case of
integral promotion).
A seed may be passed to sum. Not only will this seed be used as an initial
value, but its type will override all the above, and determine the algorithm
and precision used for summation. If a seed is not passed, one is created with
the value of typeof(r.front + r.front)(0), or typeof(r.front + r.front).zero
if no constructor exists that takes an int.
Note that these specialized summing algorithms execute more primitive operations
than vanilla summation. Therefore, if in certain cases maximum speed is required
at expense of precision, one can use fold!((a, b) => a + b)(r, 0), which
is not specialized for summation.
sum);
}
(alias) object.string = stringstring[] string[] font_libraries_font_scan_timing.fontPaths(string[] args)fontPaths((alias) object.string = stringstring[] (parameter) string[] argsargs)
{
(alias) object.string = stringstring (local variable) string listinglisting;
if ((parameter) string[] argsargs.(field) ulong string[].lengthlength > 1 && bool std.file.exists!string(string name) nothrow @nogc @safeDetermine whether the given file (or directory) exists.
exists((parameter) string[] argsargs[1]))
(local variable) string listinglisting = string std.file.readText!(string, string)(ref 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((parameter) string[] argsargs[1]);
else
try
{
auto (local variable) std.typecons.Tuple!(int, "status", string, "output") rr = std.typecons.Tuple!(int, "status", string, "output") std.process.execute(scope const(char[])[] args, const(string[string]) env = cast(const(string[string]))null, std.process.Config config = Config(Flags.none, null, null), ulong maxOutput = 18446744073709551615LU, scope const(char)[] workDir = null) @safeExecutes the given program or shell command and returns its exit
code and output.
execute and executeShell start a new process using
spawnProcess and spawnShell, respectively, and wait
for the process to complete before returning. The functions capture
what the child process prints to both its standard output and
standard error streams, and return this together with its exit code.
auto dmd = execute(["dmd", "myapp.d"]);
if (dmd.status != 0) writeln("Compilation failed:\n", dmd.output);
auto ls = executeShell("ls -l");
if (ls.status != 0) writeln("Failed to retrieve file listing");
else writeln(ls.output);
The args/program/command, env and config
parameters are forwarded straight to the underlying spawn functions,
and we refer to their documentation for details.
POSIX specific
If the process is terminated by a signal, the status field of
the return value will contain a negative number whose absolute
value is the signal number. (See wait for details.)
execute(["fc-list", ":", "file"]);
if ((local variable) std.typecons.Tuple!(int, "status", string, "output") rr.status == 0)
(local variable) string listinglisting = (local variable) std.typecons.Tuple!(int, "status", string, "output") rr.output;
}
catch ((class) object.ExceptionThe base class of all errors that are safe to catch and handle.
In principle, only thrown objects derived from this class are safe to catch
inside a catch block. Thrown objects not derived from Exception
represent runtime errors that should not be caught, as certain runtime
guarantees may not hold, making it unsafe to continue program execution.
Examples
bool gotCaught;
try
{
throw new Exception("msg");
}
catch (Exception e)
{
gotCaught = true;
assert(e.msg == "msg");
}
assert(gotCaught);
Exception) {}
return (local variable) string listinglisting.std.string.LineSplitter!(Flag.no, string) std.string.lineSplitter!(Flag.no, immutable(char))(string r) pure nothrow @nogc @safeSplit an array or slicable range of characters into a range of lines
using '\r', '\n', '\v', '\f', "\r\n",
lineSep, paraSep and '\u0085' (NEL)
as delimiters. If keepTerm is set to Yes.keepTerminator, then the
delimiter is included in the slices returned.
Does not throw on invalid UTF; such is simply passed unchanged
to the output.
Adheres to Unicode 7.0.
Does not allocate memory.
Examples
import std.array : array;
string s = "Hello\nmy\rname\nis";
/* notice the call to 'array' to turn the lazy range created by
lineSplitter comparable to the string[] created by splitLines.
*/
assert(lineSplitter(s).array == splitLines(s));
auto s = "\rpeter\n\rpaul\r\njerry\u2028ice\u2029cream\n\nsunday\nmon\u2030day\n";
auto lines = s.lineSplitter();
static immutable witness = ["", "peter", "", "paul", "jerry", "ice", "cream", "", "sunday", "mon\u2030day"];
uint i;
foreach (line; lines)
{
assert(line == witness[i++]);
}
assert(i == witness.length);
lineSplitter
.font_libraries_font_scan_timing.fontPaths.MapResult!(__lambda_L213_C15, LineSplitter!(Flag.no, string)) font_libraries_font_scan_timing.fontPaths.map!(std.string.LineSplitter!(Flag.no, string))(std.string.LineSplitter!(Flag.no, string) r) pure nothrow @nogc @safeImplements the homonym function (also known as transform) present
in many languages of functional flavor. The call ``map!(fun)(range)
returns a range of which elements are obtained by applying fun(a)
left to right for all elements a in range. The original ranges are
not changed. Evaluation is done lazily.
Examples
import std.algorithm.comparison : equal;
import std.range : chain, only;
auto squares =
chain(only(1, 2, 3, 4), only(5, 6)).map!(a => a * a);
assert(equal(squares, only(1, 4, 9, 16, 25, 36)));
Multiple functions can be passed to map. In that case, the
element type of map is a tuple containing one element for each
function.
auto sums = [2, 4, 6, 8];
auto products = [1, 4, 9, 16];
size_t i = 0;
foreach (result; [ 1, 2, 3, 4 ].map!("a + a", "a * a"))
{
assert(result[0] == sums[i]);
assert(result[1] == products[i]);
++i;
}
You may alias map with some function(s) to a symbol and use
it separately:
import std.algorithm.comparison : equal;
import std.conv : to;
alias stringize = map!(to!string);
assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ]));
map!(l => l.split(":")[0].strip)
.font_libraries_font_scan_timing.fontPaths.FilterResult!(__lambda_L214_C18, MapResult!(__lambda_L213_C15, LineSplitter!(Flag.no, string))) font_libraries_font_scan_timing.fontPaths.filter!(font_libraries_font_scan_timing.fontPaths.MapResult!(__lambda_L213_C15, LineSplitter!(Flag.no, string)))(font_libraries_font_scan_timing.fontPaths.MapResult!(__lambda_L213_C15, LineSplitter!(Flag.no, string)) range) pure nothrow @nogc @safefilter`!(predicate)(`range`)` returns a new `range` containing only elements `x` in range`` for
which predicate(x) returns true.
The predicate is passed to unaryFun, and can be either a string, or
any callable that can be executed via pred(element).
Examples
import std.algorithm.comparison : equal;
import std.math.operations : isClose;
import std.range;
int[] arr = [ 1, 2, 3, 4, 5 ];
// Filter below 3
auto small = filter!(a => a < 3)(arr);
assert(equal(small, [ 1, 2 ]));
// Filter again, but with Uniform Function Call Syntax (UFCS)
auto sum = arr.filter!(a => a < 3);
assert(equal(sum, [ 1, 2 ]));
// In combination with chain() to span multiple ranges
int[] a = [ 3, -2, 400 ];
int[] b = [ 100, -101, 102 ];
auto r = chain(a, b).filter!(a => a > 0);
assert(equal(r, [ 3, 400, 100, 102 ]));
// Mixing convertible types is fair game, too
double[] c = [ 2.5, 3.0 ];
auto r1 = chain(c, a, b).filter!(a => cast(int) a != a);
assert(isClose(r1, [ 2.5 ]));
filter!(p => p.endsWith(".ttf", ".otf", ".ttc", ".otc") && exists(p))
.string[] std.array.array!(font_libraries_font_scan_timing.fontPaths.FilterResult!(__lambda_L214_C18, MapResult!(__lambda_L213_C15, LineSplitter!(Flag.no, string))))(font_libraries_font_scan_timing.fontPaths.FilterResult!(__lambda_L214_C18, MapResult!(__lambda_L213_C15, LineSplitter!(Flag.no, string))) r) @safeAllocates an array and initializes it with copies of the elements
of range r.
Narrow strings are handled as follows:
If autodecoding is turned on (default), then they are handled as a separate overload.
If autodecoding is turned off, then this is equivalent to duplicating the array.
array.std.range.SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted) std.algorithm.sorting.sort!("a < b", SwapStrategy.unstable, string[])(string[] r) pure nothrow @nogc @safeSorts a random-access range according to the predicate less.
Performs O(r.length * log(r.length)) evaluations of less. If less involves
expensive computations on the sort key, it may be worthwhile to use
schwartzSort instead.
Stable sorting requires hasAssignableElements!Range to be true.
sort returns a SortedRange over the original range,
allowing functions that can take advantage of sorted data to know that the
range is sorted and adjust accordingly. The SortedRange is a
wrapper around the original range, so both it and the original range are sorted.
Other functions can't know that the original range has been sorted, but
they can know that SortedRange has been sorted.
Preconditions
The predicate is expected to satisfy certain rules in order for sort to
behave as expected - otherwise, the program may fail on certain inputs (but not
others) when not compiled in release mode, due to the cursory assumeSorted
check. Specifically, sort expects less(a,b) && less(b,c) to imply
less(a,c) (transitivity), and, conversely, !less(a,b) && !less(b,c) to
imply !less(a,c). Note that the default predicate ("a < b") does not
always satisfy these conditions for floating point types, because the expression
will always be false when either a or b is NaN.
Use cmp instead.
Algorithms
Introsort is used for unstable sorting and
Timsort is used for stable sorting.
Each algorithm has benefits beyond stability. Introsort is generally faster but
Timsort may achieve greater speeds on data with low entropy or if predicate calls
are expensive. Introsort performs no allocations whereas Timsort will perform one
or more allocations per call. Both algorithms have O(n log n) worst-case
time complexity.
Examples
int[] array = [ 1, 2, 3, 4 ];
// sort in descending order
array.sort!("a > b");
assert(array == [ 4, 3, 2, 1 ]);
// sort in ascending order
array.sort();
assert(array == [ 1, 2, 3, 4 ]);
// sort with reusable comparator and chain
alias myComp = (x, y) => x > y;
assert(array.sort!(myComp).release == [ 4, 3, 2, 1 ]);
// Showcase stable sorting
import std.algorithm.mutation : SwapStrategy;
string[] words = [ "aBc", "a", "abc", "b", "ABC", "c" ];
sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable)(words);
assert(words == [ "a", "aBc", "abc", "ABC", "b", "c" ]);
// Sorting floating-point numbers in presence of NaN
double[] numbers = [-0.0, 3.0, -2.0, double.nan, 0.0, -double.nan];
import std.algorithm.comparison : equal;
import std.math.operations : cmp;
import std.math.traits : isIdentical;
sort!((a, b) => cmp(a, b) < 0)(numbers);
double[] sorted = [-double.nan, -2.0, -0.0, 0.0, 3.0, double.nan];
assert(numbers.equal!isIdentical(sorted));
sort.std.algorithm.iteration.UniqResult!(binaryFun, SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted)) std.algorithm.iteration.uniq!("a == b", std.range.SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted))(std.range.SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted) r) pure nothrow @nogc @safeLazily iterates unique consecutive elements of the given range, which is
assumed to be sorted (functionality akin to the
uniq system
utility). Equivalence of elements is assessed by using the predicate
pred, by default "a == b". The predicate is passed to
binaryFun, and can either accept a string, or any callable
that can be executed via pred(element, element). If the given range is
bidirectional, uniq also yields a
bidirectional range.
Examples
import std.algorithm.comparison : equal;
import std.algorithm.mutation : copy;
int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];
assert(equal(uniq(arr), [ 1, 2, 3, 4, 5 ][]));
// Filter duplicates in-place using copy
arr.length -= arr.uniq().copy(arr).length;
assert(arr == [ 1, 2, 3, 4, 5 ]);
// Note that uniqueness is only determined consecutively; duplicated
// elements separated by an intervening different element will not be
// eliminated:
assert(equal(uniq([ 1, 1, 2, 1, 1, 3, 1]), [1, 2, 1, 3, 1]));
uniq.string[] std.array.array!(std.algorithm.iteration.UniqResult!(binaryFun, SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted)))(std.algorithm.iteration.UniqResult!(binaryFun, SortedRange!(string[], "a < b", SortedRangeOptions.assumeSorted)) r) pure nothrow @safeAllocates an array and initializes it with copies of the elements
of range r.
Narrow strings are handled as follows:
If autodecoding is turned on (default), then they are handled as a separate overload.
If autodecoding is turned off, then this is equivalent to duplicating the array.
array;
}
int int D main(string[] args)main((alias) object.string = stringstring[] (parameter) string[] argsargs)
{
auto (local variable) string[] pathspaths = string[] font_libraries_font_scan_timing.fontPaths(string[] args)fontPaths((parameter) string[] argsargs);
if (!(local variable) string[] pathspaths.(field) ulong string[].lengthlength)
{
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("SKIP: no font files found (pass a list, or install fontconfig)");
return 0;
}
void font_libraries_font_scan_timing.pass(string label, string[] paths, bool pooled)pass("first, serial", (local variable) string[] pathspaths, false);
void font_libraries_font_scan_timing.pass(string label, string[] paths, bool pooled)pass("warm, serial", (local variable) string[] pathspaths, false);
void font_libraries_font_scan_timing.pass(string label, string[] paths, bool pooled)pass("warm, 4 workers", (local variable) string[] pathspaths, true);
void font_libraries_font_scan_timing.pass(string label, string[] paths, bool pooled)pass("warm, 4 workers", (local variable) string[] pathspaths, true);
return 0;
}