gen_unicode_tables.dhover×873 errorall
#!/usr/bin/env dub
/+ dub.sdl:
    name "gen_unicode_tables"
    dependency "sparkles:base" path="../../.."
    dependency "sparkles:core-cli" path="../../.."
    libs "curl"
+/

/**
 * Generator for `sparkles.base.text.unicode_tables`.
 *
 * Emits East Asian Width (UAX #11), emoji variation-selector bases (UTS #51),
 * and the normalization/case-fold/word-break tables needed by the bounded text
 * analyzer as `@safe pure nothrow @nogc` lookup functions. Property sets use
 * Phobos's `CodepointSet.toSourceCode`; sequence mappings use compact sorted
 * indexes over flat immutable data arrays.
 *
 * Usage — regenerate the in-tree table for the pinned Unicode version:
 *   dub run --single gen_unicode_tables.d
 *
 * With no arguments it downloads the width, emoji, normalization, case-fold,
 * and word-break inputs from unicode.org (via `curl`) into a temp directory,
 * generates the module, and writes it back into the source tree.
 * Overrides:
 *   --unicode-version <ver>   target a different Unicode version (default below)
 *   --ucd-dir <dir>           use local UCD files instead of downloading
 *   --out-file <path>         write somewhere other than the in-tree module
 *
 * When `--ucd-dir` is given, `<dir>` must contain `EastAsianWidth.txt`,
 * `emoji-variation-sequences.txt`, `UnicodeData.txt`, `CaseFolding.txt`,
 * `DerivedNormalizationProps.txt`, and `WordBreakProperty.txt`.
 */
module 
(package) sparkles
sparkles
.
(package) sparkles.base
base
.
(package) sparkles.base.tools
tools
.
(module) sparkles.base.tools.gen_unicode_tables

Generator for sparkles.base.text.unicode_tables.

Emits East Asian Width (UAX #11), emoji variation-selector bases (UTS #51), and the normalization/case-fold/word-break tables needed by the bounded text analyzer as @safe pure nothrow @nogc lookup functions. Property sets use Phobos's CodepointSet.toSourceCode; sequence mappings use compact sorted indexes over flat immutable data arrays.

Usage — regenerate the in-tree table for the pinned Unicode version: dub run --single gen_unicode_tables.d

With no arguments it downloads the width, emoji, normalization, case-fold, and word-break inputs from unicode.org (via curl) into a temp directory, generates the module, and writes it back into the source tree.

Overrides

--unicode-version <ver> target a different Unicode version (default below) --ucd-dir <dir> use local UCD files instead of downloading --out-file <path> write somewhere other than the in-tree module

When --ucd-dir is given, <dir> must contain EastAsianWidth.txt, emoji-variation-sequences.txt, UnicodeData.txt, CaseFolding.txt, DerivedNormalizationProps.txt, and WordBreakProperty.txt.

gen_unicode_tables
;
import
(package) std
std
.
(module) std.algorithm

This 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

@copyrightAndrei Alexandrescu 2008-.@licenseBoost License 1.0.@authorsAndrei Alexandrescu
algorithm
:
(alias template) sparkles.base.tools.gen_unicode_tables.splitter = std.algorithm.iteration.splitter(alias pred = "a == b", Flag keepSeparators = No.keepSeparators, Range, Separator)(Range r, Separator s) if (is(typeof(binaryFun!pred(r.front, s)) : bool) && (hasSlicing!Range && hasLength!Range || isNarrowString!Range) && (is(ElementType!Range : Separator) || !(isForwardRange!Separator && (hasLength!Separator || isNarrowString!Separator))))

Lazily splits a range using an element or range as a separator. Separator ranges can be any narrow string type or sliceable range type.

Two adjacent separators are considered to surround an empty element in the split range. Use filter!(a => !a.empty) on the result to compress empty elements.

The predicate is passed to binaryFun and accepts any callable function that can be executed via pred(element, s).

Note

If splitting a string on whitespace and token compression is desired, consider using the ``splitter(r) overload.

Constraints

The predicate pred needs to accept an element of r and the separator s.

@parampred The predicate for comparing each element with the separator, defaulting to "a == b".@paramr The input range to be split. Must support slicing and .length or be a narrow string type.@params The element (or range) to be treated as the separator between range segments to be split.@paramkeepSeparators The flag for deciding if the separators are kept@returns

An input range of the subranges of elements between separators. If r is a forward range or bidirectional range, the returned range will be likewise. When a range is used a separator, bidirectionality isn't possible.

If keepSeparators is equal to Yes.keepSeparators the output will also contain the separators.

If an empty range is given, the result is an empty range. If a range with one separator is given, the result is a range with two empty elements.

@see
  • splitter for a version that splits using a regular expression defined separator.

  • split for a version that splits eagerly.

  • splitWhen, which compares adjacent elements instead of element against separator.

splitter
,
(alias template) sparkles.base.tools.gen_unicode_tables.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.

@paramfun one or more transformation functions@seeMap (higher-order function)
map
,
(alias template) sparkles.base.tools.gen_unicode_tables.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).

@parampredicate Function to apply to each element of range@returnsAn input range that contains the filtered elements. If range is at least a forward range, the return value of filter will also be a forward range.@seeFilter (higher-order function), filterBidirectional
filter
,
(alias template) sparkles.base.tools.gen_unicode_tables.canFind = std.algorithm.searching.canFind(alias pred = "a == b")

Convenience function. Like find, but only returns whether or not the search was successful.

For more information about pred see find.

@seeamong for checking a value against multiple arguments.
canFind
,
(alias template) sparkles.base.tools.gen_unicode_tables.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.

@paramless The predicate to sort by.@paramss The swapping strategy to use.@paramr The range to sort.@returnsThe initial range wrapped as a SortedRange with the predicate binaryFun!less.@see

assumeSorted

SortedRange

SwapStrategy

binaryFun

sort
,
(alias template) sparkles.base.tools.gen_unicode_tables.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.

@paramseed the initial value of the summation@paramr a finite input range@returnsThe sum of all the elements in the range r.
sum
,
(alias template) sparkles.base.tools.gen_unicode_tables.findSplit = std.algorithm.searching.findSplit(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle) if (isForwardRange!R1 && isForwardRange!R2)

These functions find the first occurrence of needle in haystack and then split haystack as follows.

findSplit returns a tuple result containing three ranges.

  • result[0] is the portion of haystack before needle

  • result[1] is the portion of haystack that matches needle

  • result[2] is the portion of haystack after the match.

If needle was not found, result[0] comprehends haystack entirely and result[1] and result[2] are empty.

findSplitBefore returns a tuple result containing two ranges.

  • result[0] is the portion of haystack before needle

  • result[1] is the balance of haystack starting with the match.

If needle was not found, result[0] comprehends haystack entirely and result[1] is empty.

findSplitAfter returns a tuple result containing two ranges.

  • result[0] is the portion of haystack up to and including the match

  • result[1] is the balance of haystack starting after the match.

If needle was not found, result[0] is empty and result[1] is haystack.

In all cases, the concatenation of the returned ranges spans the entire haystack.

If haystack is a random-access range, all three components of the tuple have the same type as haystack. Otherwise, haystack must be a forward range and the type of result[0] (and result[1] for findSplit) is the same as the result of takeExactly.

For more information about pred see find.

@parampred Predicate to compare 2 elements.@paramhaystack The forward range to search.@paramneedle The forward range to look for.@returnsA sub-type of Tuple of the split portions of haystack (see above for details). This sub-type of Tuple defines opCast!bool, which returns true when the separating needle was found and false otherwise.@seefind
findSplit
;
import
(package) std
std
.
(module) std.array

Functions 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

@copyrightCopyright Andrei Alexandrescu 2008- and Jonathan M Davis 2011-.@licenseBoost License 1.0.@authorsAndrei Alexandrescu and Jonathan M Davis
array
:
(alias template) sparkles.base.tools.gen_unicode_tables.appender = std.array.appender(A)() if (isDynamicArray!A)

Convenience function that returns an Appender instance, optionally initialized with array.

appender
,
(alias template) sparkles.base.tools.gen_unicode_tables.join = std.array.join(RoR, R)(RoR ror, R sep) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)) && isInputRange!R && (is(immutable(ElementType!(ElementType!RoR)) == immutable(ElementType!R)) || isSomeChar!(ElementType!(ElementType!RoR)) && isSomeChar!(ElementType!R)))

Eagerly concatenates all of the ranges in ror together (with the GC) into one array using sep as the separator if present.

@paramror An input range of input ranges@paramsep An input range, or a single element, to join the ranges on@returnsAn array of elements@seeFor a lazy version, see joiner
join
,
(alias template) sparkles.base.tools.gen_unicode_tables.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.

@paramr range (or aggregate with opApply function) whose elements are copied into the allocated array@returnsallocated and initialized array
array
;
import
(package) std
std
.
(module) std.conv

A 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

@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Shin Fujishiro, Adam D. Ruppe, Kenji Hara
conv
:
(alias template) sparkles.base.tools.gen_unicode_tables.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) std
std
.
(module) std.file

Utilities 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

@copyrightCopyright The D Language Foundation 2007 - 2011.@seeThe official tutorial for an introduction to working with files in D, module std.stdio for opening files and manipulating them via handles, and module std.path for manipulating path strings.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Jonathan M Davis
file
:
(alias) sparkles.base.tools.gen_unicode_tables.mkdirRecurse = void std.file.mkdirRecurse(scope const(char)[] pathname) @safe

Make directory and all parent directories as needed.

Does nothing if the directory specified by pathname already exists.

@parampathname the full path of the directory to create@throwsFileException on error.
mkdirRecurse
,
(alias template) sparkles.base.tools.gen_unicode_tables.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.

@paramS the string type of the file@paramname string or range of characters representing the file name@returnsArray of characters read.@throwsFileException if there is an error reading the file, UTFException on UTF decoding error.@seeread for reading a binary file.
readText
,
(alias) sparkles.base.tools.gen_unicode_tables.rmdirRecurse = void std.file.rmdirRecurse(scope const(char)[] pathname) @safe

Remove directory and all of its content and subdirectories, recursively.

@parampathname the path of the directory to completely remove@paramde The DirEntry to remove@throwsFileException if there is an error (including if the given file is not a directory).
rmdirRecurse
,
(alias) sparkles.base.tools.gen_unicode_tables.tempDir = string std.file.tempDir() @trusted

Returns the path to a directory for temporary files. On POSIX platforms, it searches through the following list of directories and returns the first one which is found to exist:

  1. The directory given by the TMPDIR environment variable.

  2. The directory given by the TEMP environment variable.

  3. The directory given by the TMP environment variable.

  4. /tmp/

  5. /var/tmp/

  6. /usr/tmp/

On all platforms, tempDir returns the current working directory on failure.

The return value of the function is cached, so the procedures described below will only be performed the first time the function is called. All subsequent runs will return the same string, regardless of whether environment variables and directory structures have changed in the meantime.

The POSIX tempDir algorithm is inspired by Python's tempfile.tempdir.

@returns

On Windows, this function returns the result of calling the Windows API function GetTempPath.

On POSIX platforms, it searches through the following list of directories and returns the first one which is found to exist:

  1. The directory given by the TMPDIR environment variable.

  2. The directory given by the TEMP environment variable.

  3. The directory given by the TMP environment variable.

  4. /tmp

  5. /var/tmp

  6. /usr/tmp

On all platforms, tempDir returns "." on failure, representing the current working directory.

tempDir
,
(alias template) sparkles.base.tools.gen_unicode_tables.write = std.file.write(R)(R name, const void[] buffer) if ((isSomeFiniteCharInputRange!R || isSomeString!R) && !isConvertibleToString!R)

Write buffer to file name.

Creates the file if it does not already exist.

@paramname string or range of characters representing the file name@parambuffer data to be written to file@throwsFileException on error.@seetoFile
write
;
import
(package) std
std
.
(module) std.format

This package provides string formatting functionality using printf style format strings.

Submodule Function Name Description
package
format
Converts its arguments according to a format string into a string.

| package | sformat | Converts its arguments according to a format string into a buffer. |

| package | FormatException | Signals a problem while formatting. |

| write | formattedWrite | Converts its arguments according to a format string and writes the result to an output range. |

| write | formatValue | Formats a value of any type according to a format specifier and writes the result to an output range. |

| read | formattedRead | Reads an input range according to a format string and stores the read values into its arguments. |

| read | unformatValue | Reads a value from the given input range and converts it according to a format specifier. |

| spec | FormatSpec | A general handler for format strings. |

| spec | singleSpec | Helper function that returns a FormatSpec for a single format specifier. |

Limitation

This package does not support localization, but adheres to the rounding mode of the floating point unit, if available.

Format Strings

The functions contained in this package use format strings. A format string describes the layout of another string for reading or writing purposes. A format string is composed of normal text interspersed with format specifiers. A format specifier starts with a percentage sign '%', optionally followed by one or more parameters and ends with a format indicator. A format indicator may be a simple format character or a compound indicator.

Format strings are composed according to the following grammar:

FormatString: FormatStringItem FormatString FormatStringItem: Character FormatSpecifier FormatSpecifier: '%' Parameters FormatIndicator

FormatIndicator: FormatCharacter CompoundIndicator FormatCharacter: see remark below CompoundIndicator: '(' FormatString '%)' '(' FormatString '%|' Delimiter '%)' Delimiter empty Character Delimiter

Parameters: Position Flags Width Precision Separator Position: empty Integer '$'** *Integer* **':'** *Integer* **'$' Integer ':' '$'** *Flags*: *empty* *Flag* *Flags* *Flag*: **'-'**|**'+'**|**'&nbsp;'**|**'0'**|**'#'**|**'='** *Width*: *OptionalPositionalInteger* *Precision*: *empty* **'.'** *OptionalPositionalInteger* *Separator*: *empty* **','** *OptionalInteger* **','** *OptionalInteger* **'?'** *OptionalInteger*: *empty* *Integer* **'*'** *OptionalPositionalInteger*: *OptionalInteger* **'*'** *Integer* **'$'

Character '%%' AnyCharacterExceptPercent Integer: NonZeroDigit Digits Digits: empty Digit Digits NonZeroDigit: '1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' Digit: '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'

Note

FormatCharacter is unspecified. It can be any character that has no other purpose in this grammar, but it is recommended to assign (lower- and uppercase) letters.

Note

The Parameters of a CompoundIndicator are currently limited to a '-' flag.

Format Indicator

The format indicator can either be a single character or an expression surrounded by '%(' and '%)'. It specifies the basic manner in which a value will be formatted and is the minimum requirement to format a value.

The following characters can be used as format characters:

FormatCharacter Semantics
's'
To be formatted in a human readable format.
Can be used with all types.
'c'
To be formatted as a character.
'd'
To be formatted as a signed decimal integer.
'u'
To be formatted as a decimal image of the underlying bit representation.
'b'
To be formatted as a binary image of the underlying bit representation.
'o'
To be formatted as an octal image of the underlying bit representation.
'x' / 'X'
To be formatted as a hexadecimal image of the underlying bit representation.
'e' / 'E'
To be formatted as a real number in decimal scientific notation.
'f' / 'F'
To be formatted as a real number in decimal natural notation.
'g' / 'G'
To be formatted as a real number in decimal short notation.
Depending on the number, a scientific notation or
a natural notation is used.
'a' / 'A'
To be formatted as a real number in hexadecimal scientific notation.
'r'
To be formatted as raw bytes.
The output may not be printable and depends on endianness.

The compound indicator can be used to describe compound types like arrays or structs in more detail. A compound type is enclosed within '%(' and '%)'. The enclosed sub-format string is applied to individual elements. The trailing portion of the sub-format string following the specifier for the element is interpreted as the delimiter, and is therefore omitted following the last element. The '%|' specifier may be used to explicitly indicate the start of the delimiter, so that the preceding portion of the string will be included following the last element.

The format string inside of the compound indicator should contain exactly one format specifier (two in case of associative arrays), which specifies the formatting mode of the elements of the compound type. This format specifier can be a compound indicator itself.

Note

Inside a compound indicator, strings and characters are escaped automatically. To avoid this behavior, use "%-(" instead of "%(".

Flags

There are several flags that affect the outcome of the formatting.

Flag Semantics
'-'
When the formatted result is shorter than the value
given by the width parameter, the output is left
justified. Without the '-' flag, the output remains
right justified.

There are two exceptions where the '-' flag has a different meaning: (1) with 'r' it denotes to use little endian and (2) in case of a compound indicator it means that no special handling of the members is applied. | | '=' | When the formatted result is shorter than the value given by the width parameter, the output is centered. If the central position is not possible it is moved slightly to the right. In this case, if '-' flag is present in addition to the '=' flag, it is moved slightly to the left. | | '+'&nbsp;/&nbsp;*'&nbsp;'* | Applies to numerical values. By default, positive numbers are not formatted to include the + sign. With one of these two flags present, positive numbers are preceded by a plus sign or a space. When both flags are present, a plus sign is used.

In case of 'r', a big endian format is used. | | '0' | Is applied to numerical values that are printed right justified. If the zero flag is present, the space left to the number is filled with zeros instead of spaces. | | '#' | Denotes that an alternative output must be used. This depends on the type to be formatted and the format character used. See the sections below for more information. |

Width, Precision and Separator

The width parameter specifies the minimum width of the result.

The meaning of precision depends on the format indicator. For integers it denotes the minimum number of digits printed, for real numbers it denotes the number of fractional digits and for strings and compound types it denotes the maximum number of elements that are included in the output.

A separator is used for formatting numbers. If it is specified, the output is divided into chunks of three digits, separated by a ','. The number of digits in a chunk can be given explicitly by providing a number or a ''* after the ','.

In all three cases the number of digits can be replaced by a ''*. In this scenario, the next argument is used as the number of digits. If the argument is a negative number, the precision and separator parameters are considered unspecified. For width, the absolute value is used and the '-' flag is set.

The separator can also be followed by a '?'. In that case, an additional argument is used to specify the symbol that should be used to separate the chunks.

Position

By default, the arguments are processed in the provided order. With the position parameter it is possible to address arguments directly. It is also possible to denote a series of arguments with two numbers separated by ':', that are all processed in the same way. The second number can be omitted. In that case the series ends with the last argument.

It's also possible to use positional arguments for width, precision and separator by adding a number and a '$' after the ''*.

Types

This section describes the result of combining types with format characters. It is organized in 2 subsections: a list of general information regarding the formatting of types in the presence of format characters and a table that contains details for every available combination of type and format character.

When formatting types, the following rules apply:

  • If the format character is upper case, the resulting string will be formatted using upper case letters.

  • The default precision for floating point numbers is 6 digits.

  • Rounding of floating point numbers adheres to the rounding mode of the floating point unit, if available.

  • The floating point values NaN and Infinity are formatted as nan and inf, possibly preceded by '+' or '-' sign.

  • Formatting reals is only supported for 64 bit reals and 80 bit reals. All other reals are cast to double before they are formatted. This will cause the result to be inf for very large numbers.

  • Characters and strings formatted with the 's' format character inside of compound types are surrounded by single and double quotes and unprintable characters are escaped. To avoid this, a '-' flag can be specified for the compound specifier (e.g. "%-(%s%)" instead of "%(%s%)" ).

  • Structs, unions, classes and interfaces are formatted by calling a toString method if available. See module std.format.write for more details.

  • Only part of these combinations can be used for reading. See module std.format.read for more detailed information.

This table contains descriptions for every possible combination of type and format character:

<th scope="col" width="20%">Type</th> <th scope="col" width="20%">Format Character</th> Formatted as...
<td rowspan="1">null</td> 's'
null

|<td rowspan="3">bool</td> 's' | false or true |

| 'b', 'd', 'o', 'u', 'x', 'X' | As the integrals 0 or 1 with the same format character.

Please note, that 'o' and 'x' with '#' flag might produce unexpected results due to special handling of the value 0. |

| 'r' | \0 or \1 |

|<td rowspan="4">Integral</td> 's', 'd' | A signed decimal number. The '#' flag is ignored. |

| 'b', 'o', 'u', 'x', 'X' | An unsigned binary, decimal, octal or hexadecimal number.

In case of 'o' and 'x', the '#' flag denotes that the number must be preceded by 0 and 0x, with the exception of the value 0, where this does not apply. For 'b' and 'u' the '#' flag has no effect. |

| 'e', 'E', 'f', 'F', 'g', 'G', 'a', 'A' | As a floating point value with the same specifier.

Default precision is large enough to add all digits of the integral value.

In case of 'a' and 'A', the integral digit can be any hexadecimal digit. |

| 'r' | Characters taken directly from the binary representation. |

|<td rowspan="5">Floating Point</td> 'e', 'E' | Scientific notation: Exactly one integral digit followed by a dot and fractional digits, followed by the exponent. The exponent is formatted as 'e' followed by a '+' or '-' sign, followed by at least two digits.

When there are no fractional digits and the '#' flag is not present, the dot is omitted. |

| 'f', 'F' | Natural notation: Integral digits followed by a dot and fractional digits.

When there are no fractional digits and the '#' flag is not present, the dot is omitted.

Please note: the difference between 'f' and 'F' is only visible for NaN and Infinity. |

| 's', 'g', 'G' | Short notation: If the absolute value is larger than 10 ^^ precision or smaller than 0.0001, the scientific notation is used. If not, the natural notation is applied.

In both cases precision denotes the count of all digits, including the integral digits. Trailing zeros (including a trailing dot) are removed.

If '#' flag is present, trailing zeros are not removed. |

| 'a', 'A' | Hexadecimal scientific notation: 0x followed by 1 (or 0 in case of value zero or denormalized number) followed by a dot, fractional digits in hexadecimal notation and an exponent. The exponent is build by p, followed by a sign and the exponent in decimal notation.

When there are no fractional digits and the '#' flag is not present, the dot is omitted. |

| 'r' | Characters taken directly from the binary representation. |

|<td rowspan="3">Character</td> 's', 'c' | As the character.

Inside of a compound indicator 's' is treated differently: The character is surrounded by single quotes and non printable characters are escaped. This can be avoided by preceding the compound indicator with a '-' flag (e.g. "%-(%s%)"). |

| 'b', 'd', 'o', 'u', 'x', 'X' | As the integral that represents the character. |

| 'r' | Characters taken directly from the binary representation. |

|<td rowspan="3">String</td> 's' | The sequence of characters that form the string.

Inside of a compound indicator the string is surrounded by double quotes and non printable characters are escaped. This can be avoided by preceding the compound indicator with a '-' flag (e.g. "%-(%s%)"). |

| 'r' | The sequence of characters, each formatted with 'r'. |

| compound | As an array of characters. |

|<td rowspan="3">Array</td> 's' | When the elements are characters, the array is formatted as a string. In all other cases the array is surrounded by square brackets and the elements are separated by a comma and a space. If the elements are strings, they are surrounded by double quotes and non printable characters are escaped. |

| 'r' | The sequence of the elements, each formatted with 'r'. |

| compound | The sequence of the elements, each formatted according to the specifications given inside of the compound specifier. |

|<td rowspan="2">Associative Array</td> 's' | As a sequence of the elements in unpredictable order. The output is surrounded by square brackets. The elements are separated by a comma and a space. The elements are formatted as key:value. |

| compound | As a sequence of the elements in unpredictable order. Each element is formatted according to the specifications given inside of the compound specifier. The first specifier is used for formatting the key and the second specifier is used for formatting the value. The order can be changed with positional arguments. For example "%(%2$s (%1$s), %)" will write the value, followed by the key in parenthesis. |

|<td rowspan="2">Enum</td> 's' | The name of the value. If the name is not available, the base value is used, preceeded by a cast. |

| All, but 's' | Enums can be formatted with all format characters that can be used with the base value. In that case they are formatted like the base value. |

|<td rowspan="3">Input Range</td> 's' | When the elements of the range are characters, they are written like a string. In all other cases, the elements are enclosed by square brackets and separated by a comma and a space. |

| 'r' | The sequence of the elements, each formatted with 'r'. |

| compound | The sequence of the elements, each formatted according to the specifications given inside of the compound specifier. |

|<td rowspan="1">Struct</td> 's' | When the struct has neither an applicable toString nor is an input range, it is formatted as follows: StructType(field1, field2, ...). |

|<td rowspan="1">Class</td> 's' | When the class has neither an applicable toString nor is an input range, it is formatted as the fully qualified name of the class. |

|<td rowspan="1">Union</td> 's' | When the union has neither an applicable toString nor is an input range, it is formatted as its base name. |

|<td rowspan="2">Pointer</td> 's' | A null pointer is formatted as 'null'. All other pointers are formatted as hexadecimal numbers with the format character 'X'. |

| 'x', 'X' | Formatted as a hexadecimal number. |

|<td rowspan="3">SIMD vector</td> 's' | The array is surrounded by square brackets and the elements are separated by a comma and a space. |

| 'r' | The sequence of the elements, each formatted with 'r'. |

| compound | The sequence of the elements, each formatted according to the specifications given inside of the compound specifier. |

|<td rowspan="1">Delegate</td> 's', 'r', compound | As the .stringof of this delegate treated as a string.

Please note: The implementation is currently buggy and its use is discouraged. |

Source

std/format/package.d

Examples

Simple use:

// Easiest way is to use `%s` everywhere:
assert(format("I got %s %s for %s euros.", 30, "eggs", 5.27) == "I got 30 eggs for 5.27 euros.");

// Other format characters provide more control:
assert(format("I got %b %(%X%) for %f euros.", 30, "eggs", 5.27) == "I got 11110 65676773 for 5.270000 euros.");

Compound specifiers allow formatting arrays and other compound types:

/*
The trailing end of the sub-format string following the specifier for
each item is interpreted as the array delimiter, and is therefore
omitted following the last array item:
 */
    assert(format("My items are %(%s %).", [1,2,3]) == "My items are 1 2 3.");
    assert(format("My items are %(%s, %).", [1,2,3]) == "My items are 1, 2, 3.");

/*
The "%|" delimiter specifier may be used to indicate where the
delimiter begins, so that the portion of the format string prior to
it will be retained in the last array element:
 */
    assert(format("My items are %(-%s-%|, %).", [1,2,3]) == "My items are -1-, -2-, -3-.");

/*
These compound format specifiers may be nested in the case of a
nested array argument:
 */
    auto mat = [[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]];

    assert(format("%(%(%d %) - %)", mat), "1 2 3 - 4 5 6 - 7 8 9");
    assert(format("[%(%(%d %) - %)]", mat), "[1 2 3 - 4 5 6 - 7 8 9]");
    assert(format("[%([%(%d %)]%| - %)]", mat), "[1 2 3] - [4 5 6] - [7 8 9]");

/*
Strings and characters are escaped automatically inside compound
format specifiers. To avoid this behavior, use "%-(" instead of "%(":
 */
    assert(format("My friends are %s.", ["John", "Nancy"]) == `My friends are ["John", "Nancy"].`);
    assert(format("My friends are %(%s, %).", ["John", "Nancy"]) == `My friends are "John", "Nancy".`);
    assert(format("My friends are %-(%s, %).", ["John", "Nancy"]) == `My friends are John, Nancy.`);

Using parameters:

// Flags can be used to influence to outcome:
assert(format("%g != %+#g", 3.14, 3.14) == "3.14 != +3.14000");

// Width and precision help to arrange the formatted result:
assert(format(">%10.2f<", 1234.56789) == ">   1234.57<");

// Numbers can be grouped:
assert(format("%,4d", int.max) == "21,4748,3647");

// It's possible to specify the position of an argument:
assert(format("%3$s %1$s", 3, 17, 5) == "5 3");

Providing parameters as arguments:

// Width as argument
assert(format(">%*s<", 10, "abc") == ">       abc<");

// Precision as argument
assert(format(">%.*f<", 5, 123.2) == ">123.20000<");

// Grouping as argument
assert(format("%,*d", 1, int.max) == "2,1,4,7,4,8,3,6,4,7");

// Grouping separator as argument
assert(format("%,3?d", '_', int.max) == "2_147_483_647");

// All at once
assert(format("%*.*,*?d", 20, 15, 6, '/', int.max) == "   000/002147/483647");
@copyrightCopyright The D Language Foundation 2000-2021.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, and Kenji Hara
format
:
(alias template) sparkles.base.tools.gen_unicode_tables.format = std.format.format(Char, Args...)(in Char[] fmt, Args args) if (isSomeChar!Char)

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
,
(alias template) sparkles.base.tools.gen_unicode_tables.formattedRead = std.format.read.formattedRead(Range, Char, Args...)(auto ref Range r, const(Char)[] fmt, auto ref Args args)

Reads an input range according to a format string and stores the read values into its arguments.

Format specifiers with format character 'd', 'u' and 'c' can take a ''* parameter for skipping values.

The second version of formattedRead takes the format string as template argument. In this case, it is checked for consistency at compile-time.

Note

For backward compatibility the arguments args can be given as pointers to that variable, but it is not recommended to do so, because this option might be removed in the future.

@paramr an input range, where the formatted input is read from@paramfmt a format string@paramargs a variadic list of arguments where the read values are stored@paramRange the type of the input range r@paramChar the character type used for fmt@paramArgs a variadic list of types of the arguments@returnsThe number of variables filled. If the input range r ends early, this number will be less than the number of variables provided.@throwsA FormatException if reading did not succeed.
formattedRead
,
(alias template) sparkles.base.tools.gen_unicode_tables.formattedWrite = std.format.write.formattedWrite(Writer, Char, Args...)(auto ref Writer w, scope const Char[] fmt, Args args)

Converts its arguments according to a format string and writes the result to an output range.

The second version of formattedWrite takes the format string as a template argument. In this case, it is checked for consistency at compile-time.

Note

In theory this function should be @nogc. But with the current implementation there are some cases where allocations occur. See sformat for more details.

@paramw an output range, where the formatted result is written to@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramWriter the type of the writer w@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe index of the last argument that was formatted. If no positional arguments are used, this is the number of arguments that where formatted.@throwsA FormatException if formatting did not succeed.
formattedWrite
;
import
(package) std
std
.
(package) std.net
net
.
(module) std.net.curl

Networking client functionality as provided by libcurl. The libcurl library must be installed on the system in order to use this module.

Category Functions

| High level | download upload get post put del options trace connect byLine byChunk byLineAsync byChunkAsync |

| Low level | HTTP FTP SMTP |

Note

You may need to link with the curl library, e.g. by adding "libs": ["curl"] to your dub.json file if you are using DUB.

Windows x86 note: A DMD compatible libcurl static library can be downloaded from the dlang.org download archive page.

This module is not available for iOS, tvOS or watchOS.

Compared to using libcurl directly, this module allows simpler client code for common uses, requires no unsafe operations, and integrates better with the rest of the language. Furthermore it provides range access to protocols supported by libcurl both synchronously and asynchronously.

A high level and a low level API are available. The high level API is built entirely on top of the low level one.

The high level API is for commonly used functionality such as HTTP/FTP get. The byLineAsync and byChunkAsync functions asynchronously perform the request given, outputting the fetched content into a range.

The low level API allows for streaming, setting request headers and cookies, and other advanced features.

Function Name Description

High level | download | download("ftp.digitalmars.com/sieve.ds", "/tmp/downloaded-ftp-file") downloads file from URL to file system. |

| upload | upload("/tmp/downloaded-ftp-file", "ftp.digitalmars.com/sieve.ds"); uploads file from file system to URL. |

| get | get("dlang.org") returns a char[] containing the dlang.org web page. |

| put | put("dlang.org", "Hi") returns a char[] containing the dlang.org web page. after a HTTP PUT of "hi" |

| post | post("dlang.org", "Hi") returns a char[] containing the dlang.org web page. after a HTTP POST of "hi" |

| byLine | byLine("dlang.org") returns a range of char[] containing the dlang.org web page. |

| byChunk | byChunk("dlang.org", 10) returns a range of ubyte10 containing the dlang.org web page. |

| byLineAsync | byLineAsync("dlang.org") asynchronously returns a range of char[] containing the dlang.org web page. |

| byChunkAsync | byChunkAsync("dlang.org", 10) asynchronously returns a range of ubyte10 containing the dlang.org web page. |

Low level

| HTTP | Struct for advanced HTTP usage | | FTP | Struct for advanced FTP usage | | SMTP | Struct for advanced SMTP usage |

Example

import std.net.curl, std.stdio;

// Return a char[] containing the content specified by a URL
auto content = get("dlang.org");

// Post data and return a char[] containing the content specified by a URL
auto content = post("mydomain.com/here.cgi", ["name1" : "value1", "name2" : "value2"]);

// Get content of file from ftp server
auto content = get("ftp.digitalmars.com/sieve.ds");

// Post and print out content line by line. The request is done in another thread.
foreach (line; byLineAsync("dlang.org", "Post data"))
    writeln(line);

// Get using a line range and proxy settings
auto client = HTTP();
client.proxy = "1.2.3.4";
foreach (line; byLine("dlang.org", client))
    writeln(line);

For more control than the high level functions provide, use the low level API:

Example

import std.net.curl, std.stdio;

// GET with custom data receivers
auto http = HTTP("dlang.org");
http.onReceiveHeader =
    (in char[] key, in char[] value) { writeln(key, ": ", value); };
http.onReceive = (ubyte[] data) { /+ drop +/ return data.length; };
http.perform();

First, an instance of the reference-counted HTTP struct is created. Then the custom delegates are set. These will be called whenever the HTTP instance receives a header and a data buffer, respectively. In this simple example, the headers are written to stdout and the data is ignored. If the request is stopped before it has finished then return something less than data.length from the onReceive callback. See onReceiveHeader/onReceive for more information. Finally, the HTTP request is performed by calling perform(), which is synchronous.

Source

std/net/curl.d

Credits

The functionality is based on libcurl. libcurl is licensed under an MIT/X derivative license.

@copyrightCopyright Jonas Drewsen 2011-2012@licenseBoost License 1.0.@authorsJonas Drewsen. Some of the SMTP code contributed by Jimmy Cao.
curl
:
(alias template) sparkles.base.tools.gen_unicode_tables.download = std.net.curl.download(Conn = AutoProtocol)(const(char)[] url, string saveToPath, Conn conn = Conn()) if (isCurlConn!Conn)

HTTP/FTP download to local file system.

Example

import std.net.curl;
download("https://httpbin.org/get", "/tmp/downloaded-http-file");
@paramurl resource to download@paramsaveToPath path to store the downloaded content on local disk@paramconn connection to use e.g. FTP or HTTP. The default AutoProtocol will guess connection type and create a new instance for this call only.
download
,
(struct) std.net.curl.HTTP

HTTP client functionality.

Example

Get with custom data receivers:

import std.net.curl, std.stdio;

auto http = HTTP("https://dlang.org");
http.onReceiveHeader =
    (in char[] key, in char[] value) { writeln(key ~ ": " ~ value); };
http.onReceive = (ubyte[] data) { /+ drop +/ return data.length; };
http.perform();

Put with data senders:

import std.net.curl, std.stdio;

auto http = HTTP("https://dlang.org");
auto msg = "Hello world";
http.contentLength = msg.length;
http.onSend = (void[] data)
{
    auto m = cast(void[]) msg;
    size_t len = m.length > data.length ? data.length : m.length;
    if (len == 0) return len;
    data[0 .. len] = m[0 .. len];
    msg = msg[len..$];
    return len;
};
http.perform();

Tracking progress:

import std.net.curl, std.stdio;

auto http = HTTP();
http.method = HTTP.Method.get;
http.url = "http://upload.wikimedia.org/wikipedia/commons/" ~
           "5/53/Wikipedia-logo-en-big.png";
http.onReceive = (ubyte[] data) { return data.length; };
http.onProgress = (size_t dltotal, size_t dlnow,
                   size_t ultotal, size_t ulnow)
{
    writeln("Progress ", dltotal, ", ", dlnow, ", ", ultotal, ", ", ulnow);
    return 0;
};
http.perform();
HTTP
,
(class) std.net.curl.CurlException

Exception thrown on errors in std.net.curl functions.

CurlException
,
(enum) etc.c.curl.CurlOption
CurlOption
;
import
(package) std
std
.
(module) std.path

This module is used to manipulate path strings.

All functions, with the exception of expandTilde (and in some cases absolutePath and relativePath), are pure string manipulation functions; they don't depend on any state outside the program, nor do they perform any actual file system actions. This has the consequence that the module does not make any distinction between a path that points to a directory and a path that points to a file, and it does not know whether or not the object pointed to by the path actually exists in the file system. To differentiate between these cases, use isDir and exists.

Note that on Windows, both the backslash (\) and the slash (/) are in principle valid directory separators. This module treats them both on equal footing, but in cases where a new separator is added, a backslash will be used. Furthermore, the buildNormalizedPath function will replace all slashes with backslashes on that platform.

In general, the functions in this module assume that the input paths are well-formed. (That is, they should not contain invalid characters, they should follow the file system's path format, etc.) The result of calling a function on an ill-formed path is undefined. When there is a chance that a path or a file name is invalid (for instance, when it has been input by the user), it may sometimes be desirable to use the isValidFilename and isValidPath functions to check this.

Most functions do not perform any memory allocations, and if a string is returned, it is usually a slice of an input string. If a function allocates, this is explicitly mentioned in the documentation.

Category Functions
Normalization absolutePath asAbsolutePath asNormalizedPath asRelativePath buildNormalizedPath buildPath chainPath expandTilde
Partitioning baseName dirName dirSeparator driveName pathSeparator pathSplitter relativePath rootName stripDrive
Validation isAbsolute isDirSeparator isRooted isValidFilename isValidPath
Extension defaultExtension extension setExtension stripExtension withDefaultExtension withExtension
Other filenameCharCmp filenameCmp globMatch CaseSensitive

Source

std/path.d

@authorsLars Tandle Kyllingstad, Walter Bright, Grzegorz Adam Hankiewicz, Thomas Khne, Andrei Alexandrescu@copyrightCopyright (c) 2000-2014, the authors. All rights reserved.@licenseBoost License 1.0
path
:
(alias template) sparkles.base.tools.gen_unicode_tables.buildNormalizedPath = std.path.buildNormalizedPath(C)(const(C[])[] paths...) if (isSomeChar!C)

Performs the same task as buildPath, while at the same time resolving current/parent directory symbols ("." and "..") and removing superfluous directory separators. It will return "." if the path leads to the starting directory. On Windows, slashes are replaced with backslashes.

Using buildNormalizedPath on null paths will always return null.

Note that this function does not resolve symbolic links.

This function always allocates memory to hold the resulting path. Use asNormalizedPath to not allocate memory.

@parampaths An array of paths to assemble.@returnsThe assembled path.
buildNormalizedPath
,
(alias template) sparkles.base.tools.gen_unicode_tables.buildPath = std.path.buildPath(Range)(scope Range segments) if (isInputRange!Range && !isInfinite!Range && isSomeString!(ElementType!Range))

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
,
(alias template) sparkles.base.tools.gen_unicode_tables.dirName = std.path.dirName(R)(return scope R path) if (isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) && !isSomeString!R)

Returns the parent directory of path. On Windows, this includes the drive letter if present. If path is a relative path and the parent directory is the current working directory, returns ".".

@parampath A path name.@returnsA slice of path or ".".@standardsThis function complies with the POSIX requirements for the 'dirname' shell utility (with suitable adaptations for Windows paths).
dirName
;
import
(package) std
std
.
(module) std.process

Functions 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.

@authorsLars Tandle Kyllingstad, Steven Schveighoffer, Vladimir Panteleev@copyrightCopyright (c) 2013, the authors. All rights reserved.@licenseBoost License 1.0.
process
:
(alias) sparkles.base.tools.gen_unicode_tables.thisProcessID = int std.process.thisProcessID() nothrow @nogc @property @trusted

Returns the process ID of the current process, which is guaranteed to be unique on the system.

Example

writefln("Current process ID: %d", thisProcessID);
thisProcessID
;
import
(package) std
std
.
(module) std.string

String 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

@seestd.algorithm and std.range for generic range algorithms , std.ascii for functions that work with ASCII strings , std.uni for functions that work with unicode strings@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Jonathan M Davis, and David L. 'SpottedTiger' Davis
string
:
(alias template) sparkles.base.tools.gen_unicode_tables.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.

@paramstr string or random access range of characters@paramchars string of characters to be stripped@paramleftChars string of leading characters to be stripped@paramrightChars string of trailing characters to be stripped@returnsslice of str stripped of leading and trailing whitespace or characters as specified in the second argument.@seeGeneric stripping on ranges: strip
strip
,
(alias template) sparkles.base.tools.gen_unicode_tables.startsWith = std.algorithm.searching.startsWith(alias pred = (a, b) => a == b, Range, Needles...)(Range doesThisStart, Needles withOneOfThese) if (isInputRange!Range && (Needles.length > 1) && allSatisfy!(canTestStartsWith!(pred, Range), Needles))

Checks whether the given input range starts with (one of) the given needle(s) or, if no needles are given, if its front element fulfils predicate pred.

For more information about pred see find.

@parampred Predicate to use in comparing the elements of the haystack and the needle(s). Mandatory if no needles are given.@paramdoesThisStart The input range to check.@paramwithOneOfThese The needles against which the range is to be checked, which may be individual elements or input ranges of elements.@paramwithThis The single needle to check, which may be either a single element or an input range of elements.@returns

0 if the needle(s) do not occur at the beginning of the given range; otherwise the position of the matching needle, that is, 1 if the range starts with withOneOfThese[0], 2 if it starts with withOneOfThese[1], and so on.

In the case where doesThisStart starts with multiple of the ranges or elements in withOneOfThese, then the shortest one matches (if there are two which match which are of the same length (e.g. "a" and 'a'), then the left-most of them in the argument list matches).

In the case when no needle parameters are given, return true iff front of doesThisStart fulfils predicate pred.

startsWith
,
(alias template) sparkles.base.tools.gen_unicode_tables.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.

@paramr array of chars, wchars, or dchars or a slicable range@paramkeepTerm whether delimiter is included or not in the results@returnsrange of slices of the input range r@seesplitLines splitter splitter
lineSplitter
,
(alias template) sparkles.base.tools.gen_unicode_tables.outdent = std.string.outdent(S)(S str) if (isSomeString!S)

Removes one level of indentation from a multi-line string.

This uniformly outdents the text as much as possible. Whitespace-only lines are always converted to blank lines.

Does not allocate memory if it does not throw.

@paramstr multi-line string@returnsoutdented string@throwsStringException if indentation is done with different sequences of whitespace characters.
outdent
;
import
(package) std
std
.
(module) std.uni

The std.uni`` module provides an implementation of fundamental Unicode algorithms and data structures. This doesn't include UTF encoding and decoding primitives, see decode and encode in std.utf for this functionality.

Category Functions
Decode byCodePoint byGrapheme decodeGrapheme graphemeStride popGrapheme
Comparison icmp sicmp
Classification isAlpha isAlphaNum isCodepointSet isControl isFormat isGraphical isIntegralPair isMark isNonCharacter isNumber isPrivateUse isPunctuation isSpace isSurrogate isSurrogateHi isSurrogateLo isSymbol isWhite
Normalization NFC NFD NFKD NormalizationForm normalize
Decompose decompose decomposeHangul UnicodeDecomposition
Compose compose composeJamo
Sets CodepointInterval CodepointSet InversionList unicode
Trie codepointSetTrie CodepointSetTrie codepointTrie CodepointTrie toTrie toDelegate
Casing asCapitalized asLowerCase asUpperCase isLower isUpper toLower toLowerInPlace toUpper toUpperInPlace
Utf8Matcher isUtfMatcher MatcherConcept utfMatcher
Separators lineSep nelSep paraSep
Building blocks allowedIn combiningClass Grapheme

All primitives listed operate on Unicode characters and sets of characters. For functions which operate on ASCII characters and ignore Unicode <a href="#Character">characters</a>, see std.ascii. For definitions of Unicode <a href="#Character">character</a>, <a href="#Code point">code point</a> and other terms used throughout this module see the <a href="#Terminology">terminology</a> section below.

The focus of this module is the core needs of developing Unicode-aware applications. To that effect it provides the following optimized primitives:

  • Character classification by category and common properties: isAlpha, isWhite and others.

  • Case-insensitive string comparison (`sicmp`, `icmp`).
    
  • Converting text to any of the four normalization forms via `normalize`.
    
  • Decoding (`decodeGrapheme`)  and iteration (`byGrapheme`, `graphemeStride`)
        

    by user-perceived characters, that is by Grapheme clusters.

  • Decomposing and composing of individual character(s) according to canonical
        

    or compatibility rules, see compose and decompose, including the specific version for Hangul syllables composeJamo and decomposeHangul.

It's recognized that an application may need further enhancements and extensions, such as less commonly known algorithms, or tailoring existing ones for region specific needs. To help users with building any extra functionality beyond the core primitives, the module provides:

  • `CodepointSet`, a type for easy manipulation of sets of characters.
        

    Besides the typical set algebra it provides an unusual feature: a D source code generator for detection of <a href="#Code point">code points</a> in this set. This is a boon for meta-programming parser frameworks, and is used internally to power classification in small sets like isWhite.

  • A way to construct optimal packed multi-stage tables also known as a
        

    special case of Trie. The functions codepointTrie, codepointSetTrie construct custom tries that map dchar to value. The end result is a fast and predictable O(1) lookup that powers functions like isAlpha and combiningClass, but for user-defined data sets.

  • A useful technique for Unicode-aware parsers that perform
        

    character classification of encoded <a href="#Code point">code points</a> is to avoid unnecassary decoding at all costs. utfMatcher provides an improvement over the usual workflow of decode-classify-process, combining the decoding and classification steps. By extracting necessary bits directly from encoded <a href="#Code unit">code units</a> matchers achieve significant performance improvements. See MatcherConcept for the common interface of UTF matchers.

  • Generally useful building blocks for customized normalization:
        

    combiningClass for querying combining class and allowedIn for testing the Quick_Check property of a given normalization form.

  • Access to a large selection of commonly used sets of <a href="#Code point">code points</a>.
        

    <a href="#Unicode properties">Supported sets</a> include Script, Block and General Category. The exact contents of a set can be observed in the CLDR utility, on the property index page of the Unicode website. See unicode for easy and (optionally) compile-time checked set queries.

<h3><a id="Synopsis">Synopsis</a></h3>

import std.uni;
void main()
{
    // initialize code point sets using script/block or property name
    // now 'set' contains code points from both scripts.
    auto set = unicode("Cyrillic") | unicode("Armenian");
    // same thing but simpler and checked at compile-time
    auto ascii = unicode.ASCII;
    auto currency = unicode.Currency_Symbol;

    // easy set ops
    auto a = set & ascii;
    assert(a.empty); // as it has no intersection with ascii
    a = set | ascii;
    auto b = currency - a; // subtract all ASCII, Cyrillic and Armenian

    // some properties of code point sets
    assert(b.length > 45); // 46 items in Unicode 6.1, even more in 6.2
    // testing presence of a code point in a set
    // is just fine, it is O(logN)
    assert(!b['$']);
    assert(!b['\u058F']); // Armenian dram sign
    assert(b['¥']);

    // building fast lookup tables, these guarantee O(1) complexity
    // 1-level Trie lookup table essentially a huge bit-set ~262Kb
    auto oneTrie = toTrie!1(b);
    // 2-level far more compact but typically slightly slower
    auto twoTrie = toTrie!2(b);
    // 3-level even smaller, and a bit slower yet
    auto threeTrie = toTrie!3(b);
    assert(oneTrie['£']);
    assert(twoTrie['£']);
    assert(threeTrie['£']);

    // build the trie with the most sensible trie level
    // and bind it as a functor
    auto cyrillicOrArmenian = toDelegate(set);
    auto balance = find!(cyrillicOrArmenian)("Hello ընկեր!");
    assert(balance == "ընկեր!");
    // compatible with bool delegate(dchar)
    bool delegate(dchar) bindIt = cyrillicOrArmenian;

    // Normalization
    string s = "Plain ascii (and not only), is always normalized!";
    assert(s is normalize(s));// is the same string

    string nonS = "A\u0308ffin"; // A ligature
    auto nS = normalize(nonS); // to NFC, the W3C endorsed standard
    assert(nS == "Äffin");
    assert(nS != nonS);
    string composed = "Äffin";

    assert(normalize!NFD(composed) == "A\u0308ffin");
    // to NFKD, compatibility decomposition useful for fuzzy matching/searching
    assert(normalize!NFKD("2¹⁰") == "210");
}

<h3><a id="Terminology">Terminology</a></h3> The following is a list of important Unicode notions and definitions. Any conventions used specifically in this module alone are marked as such. The descriptions are based on the formal definition as found in chapter three of The Unicode Standard Core Specification.

A unit of information used for the organization, control, or representation of textual data. Note that:
  • When representing data, the nature of that data is generally symbolic as opposed to some other kind of data (for example, visual).

  • An abstract character has no concrete form and should not be confused with a <a href="#Glyph">glyph</a>.

  • An abstract character does not necessarily correspond to what a user thinks of as a “character” and should not be confused with a Grapheme.

  • The abstract characters encoded (see Encoded character) are known as Unicode abstract characters.

  • Abstract characters not directly encoded by the Unicode Standard can often be represented by the use of combining character sequences.

The decomposition of a character or character sequence that results from recursively applying the canonical mappings found in the Unicode Character Database and these described in Conjoining Jamo Behavior (section 12 of [Unicode Conformance](http://www.unicode.org/uni2book/ch03.pdf)). The precise definition of the Canonical composition is the algorithm as specified in [ Unicode Conformance](http://www.unicode.org/uni2book/ch03.pdf) section 11. Informally it's the process that does the reverse of the canonical decomposition with the addition of certain rules that e.g. prevent legacy characters from appearing in the composed result. Two character sequences are said to be canonical equivalents if their full canonical decompositions are identical. Typically differs by context. For the purpose of this documentation the term *character* implies *encoded character*, that is, a code point having an assigned abstract character (a symbolic meaning). Any value in the Unicode codespace; that is, the range of integers from 0 to 10FFFF (hex). Not all code points are assigned to encoded characters. The minimal bit combination that can represent a unit of encoded text for processing or interchange. Depending on the encoding this could be: 8-bit code units in the UTF-8 (`char`), 16-bit code units in the UTF-16 (`wchar`), and 32-bit code units in the UTF-32 (`dchar`). *Note that in UTF-32, a code unit is a code point and is represented by the D `dchar` type.* A character with the General Category of Combining Mark(M).
  • All characters with non-zero canonical combining class are combining characters, but the reverse is not the case: there are combining characters with a zero combining class.

  • These characters are not normally used in isolation unless they are being described. They include such characters as accents, diacritics, Hebrew points, Arabic vowel signs, and Indic matras.

A numerical value used by the Unicode Canonical Ordering Algorithm to determine which sequences of combining marks are to be considered canonically equivalent and which are not. The decomposition of a character or character sequence that results from recursively applying both the compatibility mappings and the canonical mappings found in the Unicode Character Database, and those described in Conjoining Jamo Behavior no characters can be further decomposed. Two character sequences are said to be compatibility equivalents if their full compatibility decompositions are identical. An association (or mapping) between an abstract character and a code point. The actual, concrete image of a glyph representation having been rasterized or otherwise imaged onto some display surface. A character with the property Grapheme_Base, or any standard Korean syllable block. Defined as the text between grapheme boundaries as specified by Unicode Standard Annex #29, [Unicode text segmentation](http://www.unicode.org/reports/tr29/). Important general properties of a grapheme:
  • The grapheme cluster represents a horizontally segmentable unit of text, consisting of some grapheme base (which may consist of a Korean syllable) together with any number of nonspacing marks applied to it.

  • A grapheme cluster typically starts with a grapheme base and then extends across any subsequent sequence of nonspacing marks. A grapheme cluster is most directly relevant to text rendering and processes such as cursor placement and text selection in editing, but may also be relevant to comparison and searching.

  • For many processes, a grapheme cluster behaves as if it was a single character with the same properties as its grapheme base. Effectively, nonspacing marks apply graphically to the base, but do not change its properties.

This module defines a number of primitives that work with graphemes: Grapheme, decodeGrapheme and graphemeStride. All of them are using extended grapheme boundaries as defined in the aforementioned standard annex.

A combining character with the General Category of Nonspacing Mark (Mn) or Enclosing Mark (Me). A combining character that is not a nonspacing mark.

<h3><a id="Normalization">Normalization</a></h3> The concepts of <a href="#Canonical equivalent">canonical equivalent</a> or <a href="#Compatibility equivalent">compatibility equivalent</a> characters in the Unicode Standard make it necessary to have a full, formal definition of equivalence for Unicode strings. String equivalence is determined by a process called normalization, whereby strings are converted into forms which are compared directly for identity. This is the primary goal of the normalization process, see the function normalize to convert into any of the four defined forms.

A very important attribute of the Unicode Normalization Forms is that they must remain stable between versions of the Unicode Standard. A Unicode string normalized to a particular Unicode Normalization Form in one version of the standard is guaranteed to remain in that Normalization Form for implementations of future versions of the standard.

The Unicode Standard specifies four normalization forms. Informally, two of these forms are defined by maximal decomposition of equivalent sequences, and two of these forms are defined by maximal composition of equivalent sequences.

  • Normalization Form D (NFD): The <a href="#Canonical decomposition"> canonical decomposition</a> of a character sequence.

  • Normalization Form KD (NFKD): The <a href="#Compatibility decomposition"> compatibility decomposition</a> of a character sequence.

  • Normalization Form C (NFC): The canonical composition of the <a href="#Canonical decomposition">canonical decomposition</a> of a coded character sequence.

  • Normalization Form KC (NFKC): The canonical composition of the <a href="#Compatibility decomposition"> compatibility decomposition</a> of a character sequence

The choice of the normalization form depends on the particular use case. NFC is the best form for general text, since it's more compatible with strings converted from legacy encodings. NFKC is the preferred form for identifiers, especially where there are security concerns. NFD and NFKD are the most useful for internal processing.

<h3><a id="Construction of lookup tables">Construction of lookup tables</a></h3> The Unicode standard describes a set of algorithms that depend on having the ability to quickly look up various properties of a code point. Given the codespace of about 1 million <a href="#Code point">code points</a>, it is not a trivial task to provide a space-efficient solution for the multitude of properties.

Common approaches such as hash-tables or binary search over sorted code point intervals (as in InversionList) are insufficient. Hash-tables have enormous memory footprint and binary search over intervals is not fast enough for some heavy-duty algorithms.

The recommended solution (see Unicode Implementation Guidelines) is using multi-stage tables that are an implementation of the Trie data structure with integer keys and a fixed number of stages. For the remainder of the section this will be called a fixed trie. The following describes a particular implementation that is aimed for the speed of access at the expense of ideal size savings.

Taking a 2-level Trie as an example the principle of operation is as follows. Split the number of bits in a key (code point, 21 bits) into 2 components (e.g. 15 and 8). The first is the number of bits in the index of the trie and the other is number of bits in each page of the trie. The layout of the trie is then an array of size 2^^bits-of-index followed an array of memory chunks of size 2^^bits-of-page/bits-per-element.

The number of pages is variable (but not less then 1) unlike the number of entries in the index. The slots of the index all have to contain a number of a page that is present. The lookup is then just a couple of operations - slice the upper bits, lookup an index for these, take a page at this index and use the lower bits as an offset within this page.

Assuming that pages are laid out consequently in one array at pages, the pseudo-code is:

auto elemsPerPage = (2 ^^ bits_per_page) / Value.sizeOfInBits;
pages[index[n >> bits_per_page]][n & (elemsPerPage - 1)];

Where if elemsPerPage is a power of 2 the whole process is a handful of simple instructions and 2 array reads. Subsequent levels of the trie are introduced by recursing on this notion - the index array is treated as values. The number of bits in index is then again split into 2 parts, with pages over 'current-index' and the new 'upper-index'.

For completeness a level 1 trie is simply an array. The current implementation takes advantage of bit-packing values when the range is known to be limited in advance (such as bool). See also BitPacked for enforcing it manually. The major size advantage however comes from the fact that multiple identical pages on every level are merged by construction.

The process of constructing a trie is more involved and is hidden from the user in a form of the convenience functions codepointTrie, codepointSetTrie and the even more convenient toTrie. In general a set or built-in AA with dchar type can be turned into a trie. The trie object in this module is read-only (immutable); it's effectively frozen after construction.

<h3><a id="Unicode properties">Unicode properties</a></h3> This is a full list of Unicode properties accessible through unicode with specific helpers per category nested within. Consult the CLDR utility when in doubt about the contents of a particular set.

General category sets listed below are only accessible with the unicode shorthand accessor.

Abb. Long form
Abb. Long form Abb. Long form
L Letter
Cn Unassigned Po Other_Punctuation
Ll Lowercase_Letter
Co Private_Use Ps Open_Punctuation
Lm Modifier_Letter
Cs Surrogate S Symbol
Lo Other_Letter
N Number Sc Currency_Symbol
Lt Titlecase_Letter
Nd Decimal_Number Sk Modifier_Symbol
Lu Uppercase_Letter
Nl Letter_Number Sm Math_Symbol
M Mark
No Other_Number So Other_Symbol
Mc Spacing_Mark
P Punctuation Z Separator
Me Enclosing_Mark
Pc Connector_Punctuation Zl Line_Separator
Mn Nonspacing_Mark
Pd Dash_Punctuation Zp Paragraph_Separator
C Other
Pe Close_Punctuation Zs Space_Separator
Cc Control Pf
Final_Punctuation - Any
Cf Format
Pi Initial_Punctuation - ASCII

Sets for other commonly useful properties that are accessible with unicode:

Name Name Name
Alphabetic Ideographic Other_Uppercase
ASCII_Hex_Digit IDS_Binary_Operator Pattern_Syntax
Bidi_Control ID_Start Pattern_White_Space
Cased IDS_Trinary_Operator Quotation_Mark
Case_Ignorable Join_Control Radical
Dash Logical_Order_Exception Soft_Dotted
Default_Ignorable_Code_Point Lowercase STerm
Deprecated Math Terminal_Punctuation
Diacritic Noncharacter_Code_Point Unified_Ideograph
Extender Other_Alphabetic Uppercase
Grapheme_Base Other_Default_Ignorable_Code_Point Variation_Selector
Grapheme_Extend Other_Grapheme_Extend White_Space
Grapheme_Link Other_ID_Continue XID_Continue
Hex_Digit Other_ID_Start XID_Start
Hyphen Other_Lowercase
ID_Continue Other_Math

Below is the table with block names accepted by unicode.block. Note that the shorthand version unicode requires "In" to be prepended to the names of blocks so as to disambiguate scripts and blocks.

| Aegean Numbers | Ethiopic Extended | Mongolian | | Alchemical Symbols | Ethiopic Extended-A | Musical Symbols | | Alphabetic Presentation Forms | Ethiopic Supplement | Myanmar | | Ancient Greek Musical Notation | General Punctuation | Myanmar Extended-A | | Ancient Greek Numbers | Geometric Shapes | New Tai Lue | | Ancient Symbols | Georgian | NKo | | Arabic | Georgian Supplement | Number Forms | | Arabic Extended-A | Glagolitic | Ogham | | Arabic Mathematical Alphabetic Symbols | Gothic | Ol Chiki | | Arabic Presentation Forms-A | Greek and Coptic | Old Italic | | Arabic Presentation Forms-B | Greek Extended | Old Persian | | Arabic Supplement | Gujarati | Old South Arabian | | Armenian | Gurmukhi | Old Turkic | | Arrows | Halfwidth and Fullwidth Forms | Optical Character Recognition | | Avestan | Hangul Compatibility Jamo | Oriya | | Balinese | Hangul Jamo | Osmanya | | Bamum | Hangul Jamo Extended-A | Phags-pa | | Bamum Supplement | Hangul Jamo Extended-B | Phaistos Disc | | Basic Latin | Hangul Syllables | Phoenician | | Batak | Hanunoo | Phonetic Extensions | | Bengali | Hebrew | Phonetic Extensions Supplement | | Block Elements | High Private Use Surrogates | Playing Cards | | Bopomofo | High Surrogates | Private Use Area | | Bopomofo Extended | Hiragana | Rejang | | Box Drawing | Ideographic Description Characters | Rumi Numeral Symbols | | Brahmi | Imperial Aramaic | Runic | | Braille Patterns | Inscriptional Pahlavi | Samaritan | | Buginese | Inscriptional Parthian | Saurashtra | | Buhid | IPA Extensions | Sharada | | Byzantine Musical Symbols | Javanese | Shavian | | Carian | Kaithi | Sinhala | | Chakma | Kana Supplement | Small Form Variants | | Cham | Kanbun | Sora Sompeng | | Cherokee | Kangxi Radicals | Spacing Modifier Letters | | CJK Compatibility | Kannada | Specials | | CJK Compatibility Forms | Katakana | Sundanese | | CJK Compatibility Ideographs | Katakana Phonetic Extensions | Sundanese Supplement | | CJK Compatibility Ideographs Supplement | Kayah Li | Superscripts and Subscripts | | CJK Radicals Supplement | Kharoshthi | Supplemental Arrows-A | | CJK Strokes | Khmer | Supplemental Arrows-B | | CJK Symbols and Punctuation | Khmer Symbols | Supplemental Mathematical Operators | | CJK Unified Ideographs | Lao | Supplemental Punctuation | | CJK Unified Ideographs Extension A | Latin-1 Supplement | Supplementary Private Use Area-A | | CJK Unified Ideographs Extension B | Latin Extended-A | Supplementary Private Use Area-B | | CJK Unified Ideographs Extension C | Latin Extended Additional | Syloti Nagri | | CJK Unified Ideographs Extension D | Latin Extended-B | Syriac | | Combining Diacritical Marks | Latin Extended-C | Tagalog | | Combining Diacritical Marks for Symbols | Latin Extended-D | Tagbanwa | | Combining Diacritical Marks Supplement | Lepcha | Tags | | Combining Half Marks | Letterlike Symbols | Tai Le | | Common Indic Number Forms | Limbu | Tai Tham | | Control Pictures | Linear B Ideograms | Tai Viet | | Coptic | Linear B Syllabary | Tai Xuan Jing Symbols | | Counting Rod Numerals | Lisu | Takri | | Cuneiform | Low Surrogates | Tamil | | Cuneiform Numbers and Punctuation | Lycian | Telugu | | Currency Symbols | Lydian | Thaana | | Cypriot Syllabary | Mahjong Tiles | Thai | | Cyrillic | Malayalam | Tibetan | | Cyrillic Extended-A | Mandaic | Tifinagh | | Cyrillic Extended-B | Mathematical Alphanumeric Symbols | Transport And Map Symbols | | Cyrillic Supplement | Mathematical Operators | Ugaritic | | Deseret | Meetei Mayek | Unified Canadian Aboriginal Syllabics | | Devanagari | Meetei Mayek Extensions | Unified Canadian Aboriginal Syllabics Extended | | Devanagari Extended | Meroitic Cursive | Vai | | Dingbats | Meroitic Hieroglyphs | Variation Selectors | | Domino Tiles | Miao | Variation Selectors Supplement | | Egyptian Hieroglyphs | Miscellaneous Mathematical Symbols-A | Vedic Extensions | | Emoticons | Miscellaneous Mathematical Symbols-B | Vertical Forms | | Enclosed Alphanumerics | Miscellaneous Symbols | Yijing Hexagram Symbols | | Enclosed Alphanumeric Supplement | Miscellaneous Symbols and Arrows | Yi Radicals | | Enclosed CJK Letters and Months | Miscellaneous Symbols And Pictographs | Yi Syllables | | Enclosed Ideographic Supplement | Miscellaneous Technical | | Ethiopic | Modifier Tone Letters |

Below is the table with script names accepted by unicode.script and by the shorthand version unicode:

| Arabic | Hanunoo | Old_Italic | | Armenian | Hebrew | Old_Persian | | Avestan | Hiragana | Old_South_Arabian | | Balinese | Imperial_Aramaic | Old_Turkic | | Bamum | Inherited | Oriya | | Batak | Inscriptional_Pahlavi | Osmanya | | Bengali | Inscriptional_Parthian | Phags_Pa | | Bopomofo | Javanese | Phoenician | | Brahmi | Kaithi | Rejang | | Braille | Kannada | Runic | | Buginese | Katakana | Samaritan | | Buhid | Kayah_Li | Saurashtra | | Canadian_Aboriginal | Kharoshthi | Sharada | | Carian | Khmer | Shavian | | Chakma | Lao | Sinhala | | Cham | Latin | Sora_Sompeng | | Cherokee | Lepcha | Sundanese | | Common | Limbu | Syloti_Nagri | | Coptic | Linear_B | Syriac | | Cuneiform | Lisu | Tagalog | | Cypriot | Lycian | Tagbanwa | | Cyrillic | Lydian | Tai_Le | | Deseret | Malayalam | Tai_Tham | | Devanagari | Mandaic | Tai_Viet | | Egyptian_Hieroglyphs | Meetei_Mayek | Takri | | Ethiopic | Meroitic_Cursive | Tamil | | Georgian | Meroitic_Hieroglyphs | Telugu | | Glagolitic | Miao | Thaana | | Gothic | Mongolian | Thai | | Greek | Myanmar | Tibetan | | Gujarati | New_Tai_Lue | Tifinagh | | Gurmukhi | Nko | Ugaritic | | Han | Ogham | Vai | | Hangul | Ol_Chiki | Yi |

Below is the table of names accepted by unicode.hangulSyllableType.

Abb. Long form
L Leading_Jamo
LV LV_Syllable
LVT LVT_Syllable
T Trailing_Jamo
V Vowel_Jamo

References

ASCII Table, Wikipedia, The Unicode Consortium, Unicode normalization forms, Unicode text segmentation Unicode Implementation Guidelines Unicode Conformance

Trademarks

Unicode(tm) is a trademark of Unicode, Inc.

Source

std/uni/package.d

@copyrightCopyright 2013 -@licenseBoost License 1.0.@authorsDmitry Olshansky@standardsUnicode v6.2
uni
:
(struct) std.uni.InversionList!(GcPolicy)
CodepointSet
,
(alias) sparkles.base.tools.gen_unicode_tables.isWhite = bool std.uni.isWhite(dchar c) pure nothrow @nogc @safe

Whether or not c is a Unicode whitespace . (general Unicode category: Part of C0(tab, vertical tab, form feed, carriage return, and linefeed characters), Zs, Zl, Zp, and NEL(U+0085))

isWhite
;
import
(package) sparkles
sparkles
.
(package) sparkles.base
base
.
(module) sparkles.base.styled_template

Style template processing for IES (Interpolated Expression Sequences).

Provides a template syntax for applying terminal styles to IES strings:

import sparkles.base.styled_template;

int cpu = 75;
styledWriteln(i"CPU: {red $(cpu)%} Status: {green OK}");

Supported syntax:

  • {red text} — Apply single style

  • {bold.red text} — Chain multiple styles

  • {bold outer {red nested}} — Nested blocks (inner inherits outer)

  • {red text {~red normal}} — Negation with ~ removes a style

  • #{ — Escaped literal {

  • #} — Escaped literal }

styled_template
:
(alias template) sparkles.base.tools.gen_unicode_tables.styledWriteln = sparkles.base.styled_template.styledWriteln(Args...)(ColorDepth depth, InterpolationHeader header, Args args, InterpolationFooter footer)

Write styled IES to stdout with newline.

styledWriteln
,
(alias template) sparkles.base.tools.gen_unicode_tables.styledWritelnErr = sparkles.base.styled_template.styledWritelnErr(Args...)(ColorDepth depth, InterpolationHeader header, Args args, InterpolationFooter footer)

Write styled IES to stderr with newline.

styledWritelnErr
;
import
(package) sparkles
sparkles
.
(package) sparkles.core_cli
core_cli
.
(module) sparkles.core_cli.args
args
:
(struct) sparkles.core_cli.help_formatting.HelpInfo
HelpInfo
,
(struct) sparkles.core_cli.args.uda.Option
Option
,
(alias template) sparkles.base.tools.gen_unicode_tables.parseCli = sparkles.core_cli.args.internal.parseCli(Cli)(string[] argv, HelpInfo helpInfo = HelpInfo.init)
parseCli
,
(alias) sparkles.base.tools.gen_unicode_tables.reportCliError = int sparkles.core_cli.args.internal.reportCliError(in sparkles.core_cli.args.error.CliError e)

Reports a failed parse and returns the exit code the program should use.

A help request is a failure in the Expected sense but a success to the user, and carries exitCode == 0 to say so — returning this value is what keeps --help from looking like an error to a shell.

For a program whose commands have run methods, prefer runCli, which calls this. This is the entry point for a program that parses into a struct and then does its own work.

reportCliError
;
/// Unicode version this generator targets by default. All properties consumed /// by the bounded analyzer, including canonical combining classes, are emitted /// here so its behavior does not silently follow the compiler's `std.uni`. enum
(constant) string sparkles.base.tools.gen_unicode_tables.pinnedUnicodeVersion = "17.0.0"

Unicode version this generator targets by default. All properties consumed by the bounded analyzer, including canonical combining classes, are emitted here so its behavior does not silently follow the compiler's std.uni.

pinnedUnicodeVersion
= "17.0.0";
/// Base URL of the Unicode Character Database. enum
(constant) string sparkles.base.tools.gen_unicode_tables.ucdBaseUrl = "https://www.unicode.org/Public"

Base URL of the Unicode Character Database.

ucdBaseUrl
= "https://www.unicode.org/Public";
/// Default output: the in-tree generated module, resolved relative to this /// source file so `dub run --single` writes straight into the work tree. enum
(constant) string sparkles.base.tools.gen_unicode_tables.defaultOutFile = __error

Default output: the in-tree generated module, resolved relative to this source file so dub run --single writes straight into the work tree.

defaultOutFile
= __FILE_FULL_PATH__
.
string std.path.dirName!(immutable(char))(return scope string path) pure nothrow @nogc @safe

Returns the parent directory of path. On Windows, this includes the drive letter if present. If path is a relative path and the parent directory is the current working directory, returns ".".

Examples

assert(dirName("") == ".");
assert(dirName("file"w) == ".");
assert(dirName("dir/"d) == ".");
assert(dirName("dir///") == ".");
assert(dirName("dir/file"w.dup) == "dir");
assert(dirName("dir///file"d.dup) == "dir");
assert(dirName("dir/subdir/") == "dir");
assert(dirName("/dir/file"w) == "/dir");
assert(dirName("/file"d) == "/");
assert(dirName("/") == "/");
assert(dirName("///") == "/");

version (Windows)
{
    assert(dirName(`dir\`) == `.`);
    assert(dirName(`dir\\\`) == `.`);
    assert(dirName(`dir\file`) == `dir`);
    assert(dirName(`dir\\\file`) == `dir`);
    assert(dirName(`dir\subdir\`) == `dir`);
    assert(dirName(`\dir\file`) == `\dir`);
    assert(dirName(`\file`) == `\`);
    assert(dirName(`\`) == `\`);
    assert(dirName(`\\\`) == `\`);
    assert(dirName(`d:`) == `d:`);
    assert(dirName(`d:file`) == `d:`);
    assert(dirName(`d:\`) == `d:\`);
    assert(dirName(`d:\file`) == `d:\`);
    assert(dirName(`d:\dir\file`) == `d:\dir`);
    assert(dirName(`\\server\share\dir\file`) == `\\server\share\dir`);
    assert(dirName(`\\server\share\file`) == `\\server\share`);
    assert(dirName(`\\server\share\`) == `\\server\share`);
    assert(dirName(`\\server\share`) == `\\server\share`);
}
@parampath A path name.@returnsA slice of path or ".".@standardsThis function complies with the POSIX requirements for the 'dirname' shell utility (with suitable adaptations for Windows paths).
dirName
.
string std.path.buildNormalizedPath!char(const(char[])[] paths...) pure nothrow @safe

Performs the same task as buildPath, while at the same time resolving current/parent directory symbols ("." and "..") and removing superfluous directory separators. It will return "." if the path leads to the starting directory. On Windows, slashes are replaced with backslashes.

Using buildNormalizedPath on null paths will always return null.

Note that this function does not resolve symbolic links.

This function always allocates memory to hold the resulting path. Use asNormalizedPath to not allocate memory.

Examples

assert(buildNormalizedPath("foo", "..") == ".");

version (Posix)
{
    assert(buildNormalizedPath("/foo/./bar/..//baz/") == "/foo/baz");
    assert(buildNormalizedPath("../foo/.") == "../foo");
    assert(buildNormalizedPath("/foo", "bar/baz/") == "/foo/bar/baz");
    assert(buildNormalizedPath("/foo", "/bar/..", "baz") == "/baz");
    assert(buildNormalizedPath("foo/./bar", "../../", "../baz") == "../baz");
    assert(buildNormalizedPath("/foo/./bar", "../../baz") == "/baz");
}

version (Windows)
{
    assert(buildNormalizedPath(`c:\foo\.\bar/..\\baz\`) == `c:\foo\baz`);
    assert(buildNormalizedPath(`..\foo\.`) == `..\foo`);
    assert(buildNormalizedPath(`c:\foo`, `bar\baz\`) == `c:\foo\bar\baz`);
    assert(buildNormalizedPath(`c:\foo`, `bar/..`) == `c:\foo`);
    assert(buildNormalizedPath(`\\server\share\foo`, `..\bar`) ==
            `\\server\share\bar`);
}
@parampaths An array of paths to assemble.@returnsThe assembled path.
buildNormalizedPath
("../src/sparkles/base/text/unicode_tables.d");
CTFE failed because of previous errors in `buildNormalizedPath`
struct
(struct) sparkles.base.tools.gen_unicode_tables.CliParams
CliParams
{ @(
(struct) sparkles.core_cli.args.uda.Option
Option
(`u|ucd-dir`, description: "Directory with the six documented UCD/emoji inputs. If omitted, they are downloaded from unicode.org for --unicode-version."))
(alias) object.string = string
string
(field) string sparkles.base.tools.gen_unicode_tables.CliParams.ucdDir
ucdDir
;
@(
(struct) sparkles.core_cli.args.uda.Option
Option
(`o|out-file`, description: "Path to write the generated module (default: the in-tree unicode_tables.d)."))
(alias) object.string = string
string
(field) string sparkles.base.tools.gen_unicode_tables.CliParams.outFile
outFile
=
(constant) string sparkles.base.tools.gen_unicode_tables.defaultOutFile = __error

Default output: the in-tree generated module, resolved relative to this source file so dub run --single writes straight into the work tree.

defaultOutFile
;
@(
(struct) sparkles.core_cli.args.uda.Option
Option
(`V|unicode-version`, description: "Unicode version to generate for."))
(alias) object.string = string
string
(field) string sparkles.base.tools.gen_unicode_tables.CliParams.unicodeVersion
unicodeVersion
=
(constant) string sparkles.base.tools.gen_unicode_tables.pinnedUnicodeVersion = "17.0.0"

Unicode version this generator targets by default. All properties consumed by the bounded analyzer, including canonical combining classes, are emitted here so its behavior does not silently follow the compiler's std.uni.

pinnedUnicodeVersion
;
} int
int D main(string[] args)
main
(
(alias) object.string = string
string
[]
(parameter) string[] args
args
)
{ auto
(local variable) expected.Expected!(CliParams, CliError, Abort) parsed
parsed
=
expected.Expected!(CliParams, CliError, Abort) sparkles.core_cli.args.internal.parseCli!(sparkles.base.tools.gen_unicode_tables.CliParams)(string[] argv, sparkles.core_cli.help_formatting.HelpInfo helpInfo = HelpInfo(null, null, null)) @system
parseCli
!
(struct) sparkles.base.tools.gen_unicode_tables.CliParams
CliParams
(
(parameter) string[] args
args
,
(struct) sparkles.core_cli.help_formatting.HelpInfo
HelpInfo
(
"gen_unicode_tables", "Generate sparkles.base.text.unicode_tables from the Unicode Character Database", ), ); if (!
(local variable) expected.Expected!(CliParams, CliError, Abort) parsed
parsed
)
return
int sparkles.core_cli.args.internal.reportCliError(in sparkles.core_cli.args.error.CliError e)

Reports a failed parse and returns the exit code the program should use.

A help request is a failure in the Expected sense but a success to the user, and carries exitCode == 0 to say so — returning this value is what keeps --help from looking like an error to a shell.

For a program whose commands have run methods, prefer runCli, which calls this. This is the entry point for a program that parses into a struct and then does its own work.

reportCliError
(
(local variable) expected.Expected!(CliParams, CliError, Abort) parsed
parsed
.
inout(sparkles.core_cli.args.error.CliError) expected.Expected!(sparkles.base.tools.gen_unicode_tables.CliParams, sparkles.core_cli.args.error.CliError, expected.Abort).error() inout nothrow @nogc @property ref @safe

Returns the error value. May only be called when hasValue returns false.

If there is no error value, it calls hook's onAccessEmptyError.

It returns E.init when hook doesn't provide onAccessEmptyError.

error
);
const
(local variable) const(sparkles.base.tools.gen_unicode_tables.CliParams) cli
cli
=
(local variable) expected.Expected!(CliParams, CliError, Abort) parsed
parsed
.
inout(sparkles.base.tools.gen_unicode_tables.CliParams) expected.Expected!(sparkles.base.tools.gen_unicode_tables.CliParams, sparkles.core_cli.args.error.CliError, expected.Abort).value!()() inout pure nothrow @nogc @property ref @safe

Returns the expected value if there is one.

With default Abort hook, it asserts when there is no value. It calls hook's onAccessEmptyValue otherwise.

It returns T.init when hook doesn't provide onAccessEmptyValue.

value
;
const
(local variable) const(string) ver
ver
=
(local variable) const(sparkles.base.tools.gen_unicode_tables.CliParams) cli
cli
.
(field) string sparkles.base.tools.gen_unicode_tables.CliParams.unicodeVersion
unicodeVersion
;
const
(local variable) const(string) outFile
outFile
=
string std.path.buildNormalizedPath!char(const(char[])[] paths...) pure nothrow @safe

Performs the same task as buildPath, while at the same time resolving current/parent directory symbols ("." and "..") and removing superfluous directory separators. It will return "." if the path leads to the starting directory. On Windows, slashes are replaced with backslashes.

Using buildNormalizedPath on null paths will always return null.

Note that this function does not resolve symbolic links.

This function always allocates memory to hold the resulting path. Use asNormalizedPath to not allocate memory.

Examples

assert(buildNormalizedPath("foo", "..") == ".");

version (Posix)
{
    assert(buildNormalizedPath("/foo/./bar/..//baz/") == "/foo/baz");
    assert(buildNormalizedPath("../foo/.") == "../foo");
    assert(buildNormalizedPath("/foo", "bar/baz/") == "/foo/bar/baz");
    assert(buildNormalizedPath("/foo", "/bar/..", "baz") == "/baz");
    assert(buildNormalizedPath("foo/./bar", "../../", "../baz") == "../baz");
    assert(buildNormalizedPath("/foo/./bar", "../../baz") == "/baz");
}

version (Windows)
{
    assert(buildNormalizedPath(`c:\foo\.\bar/..\\baz\`) == `c:\foo\baz`);
    assert(buildNormalizedPath(`..\foo\.`) == `..\foo`);
    assert(buildNormalizedPath(`c:\foo`, `bar\baz\`) == `c:\foo\bar\baz`);
    assert(buildNormalizedPath(`c:\foo`, `bar/..`) == `c:\foo`);
    assert(buildNormalizedPath(`\\server\share\foo`, `..\bar`) ==
            `\\server\share\bar`);
}
@parampaths An array of paths to assemble.@returnsThe assembled path.
buildNormalizedPath
(
(local variable) const(sparkles.base.tools.gen_unicode_tables.CliParams) cli
cli
.
(field) string sparkles.base.tools.gen_unicode_tables.CliParams.outFile
outFile
);
void sparkles.base.styled_template.styledWritelnErr!(core.interpolation.InterpolatedLiteral!"{dim unicode version}: {cyan ", core.interpolation.InterpolatedExpression!"ver", string, core.interpolation.InterpolatedLiteral!"}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{dim unicode version}: {cyan " __param_1, core.interpolation.InterpolatedExpression!"ver" __param_2, string __param_3, core.interpolation.InterpolatedLiteral!"}" __param_4, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWritelnErr
(i"{dim unicode version}: {cyan $(ver)}");
void sparkles.base.styled_template.styledWritelnErr!(core.interpolation.InterpolatedLiteral!"{dim output file}: {cyan ", core.interpolation.InterpolatedExpression!"outFile", string, core.interpolation.InterpolatedLiteral!"}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{dim output file}: {cyan " __param_1, core.interpolation.InterpolatedExpression!"outFile" __param_2, string __param_3, core.interpolation.InterpolatedLiteral!"}" __param_4, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWritelnErr
(i"{dim output file}: {cyan $(outFile)}");
if (
(local variable) const(sparkles.base.tools.gen_unicode_tables.CliParams) cli
cli
.
(field) string sparkles.base.tools.gen_unicode_tables.CliParams.ucdDir
ucdDir
.
(field) ulong const(string).length
length
)
void sparkles.base.styled_template.styledWritelnErr!(core.interpolation.InterpolatedLiteral!"{dim source}: {dim local} {cyan ", core.interpolation.InterpolatedExpression!"cli.ucdDir", string, core.interpolation.InterpolatedLiteral!"}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{dim source}: {dim local} {cyan " __param_1, core.interpolation.InterpolatedExpression!"cli.ucdDir" __param_2, string __param_3, core.interpolation.InterpolatedLiteral!"}" __param_4, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWritelnErr
(i"{dim source}: {dim local} {cyan $(cli.ucdDir)}");
else
void sparkles.base.styled_template.styledWritelnErr!(core.interpolation.InterpolatedLiteral!"{dim source}: {dim downloading from unicode.org}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{dim source}: {dim downloading from unicode.org}" __param_1, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWritelnErr
(i"{dim source}: {dim downloading from unicode.org}");
// Without --ucd-dir, fetch every pinned input for `ver` into a temp dir // and remove them afterwards.
(alias) object.string = string
string
(local variable) string ucdDir
ucdDir
=
(local variable) const(sparkles.base.tools.gen_unicode_tables.CliParams) cli
cli
.
(field) string sparkles.base.tools.gen_unicode_tables.CliParams.ucdDir
ucdDir
;
(alias) object.string = string
string
(local variable) string tmpDir
tmpDir
;
scope (exit) if (
(local variable) string tmpDir
tmpDir
.
(field) ulong string.length
length
)
void std.file.rmdirRecurse(scope const(char)[] pathname) @safe

Remove directory and all of its content and subdirectories, recursively.

@parampathname the path of the directory to completely remove@paramde The DirEntry to remove@throwsFileException if there is an error (including if the given file is not a directory).
rmdirRecurse
(
(local variable) string tmpDir
tmpDir
);
if (!
(local variable) string ucdDir
ucdDir
.
(field) ulong string.length
length
)
{
(local variable) string tmpDir
tmpDir
=
string std.file.tempDir() @trusted

Returns the path to a directory for temporary files. On POSIX platforms, it searches through the following list of directories and returns the first one which is found to exist:

  1. The directory given by the TMPDIR environment variable.

  2. The directory given by the TEMP environment variable.

  3. The directory given by the TMP environment variable.

  4. /tmp/

  5. /var/tmp/

  6. /usr/tmp/

On all platforms, tempDir returns the current working directory on failure.

The return value of the function is cached, so the procedures described below will only be performed the first time the function is called. All subsequent runs will return the same string, regardless of whether environment variables and directory structures have changed in the meantime.

The POSIX tempDir algorithm is inspired by Python's tempfile.tempdir.

Examples

import std.ascii : letters;
import std.conv : to;
import std.path : buildPath;
import std.random : randomSample;
import std.utf : byCodeUnit;

// random id with 20 letters
auto id = letters.byCodeUnit.randomSample(20).to!string;
auto myFile = tempDir.buildPath(id ~ "my_tmp_file");
scope(exit) myFile.remove;

myFile.write("hello");
assert(myFile.readText == "hello");
@returns

On Windows, this function returns the result of calling the Windows API function GetTempPath.

On POSIX platforms, it searches through the following list of directories and returns the first one which is found to exist:

  1. The directory given by the TMPDIR environment variable.

  2. The directory given by the TEMP environment variable.

  3. The directory given by the TMP environment variable.

  4. /tmp

  5. /var/tmp

  6. /usr/tmp

On all platforms, tempDir returns "." on failure, representing the current working directory.

tempDir
.
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
("gen_unicode_tables-" ~
int std.process.thisProcessID() nothrow @nogc @property @trusted

Returns the process ID of the current process, which is guaranteed to be unique on the system.

Example

writefln("Current process ID: %d", thisProcessID);
thisProcessID
.
string std.conv.to!string.to!int(int __param_0) pure nothrow @safe

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

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 = string
string
);
void std.file.mkdirRecurse(scope const(char)[] pathname) @safe

Make directory and all parent directories as needed.

Does nothing if the directory specified by pathname already exists.

Examples

import std.path : buildPath;

auto dir = deleteme ~ "dir";
scope(exit) dir.rmdirRecurse;

dir.mkdir;
assert(dir.exists);
dir.mkdirRecurse; // does nothing

// creates all parent directories as needed
auto nested = dir.buildPath("a", "b", "c");
nested.mkdirRecurse;
assert(nested.exists);
import std.exception : assertThrown;

scope(exit) deleteme.remove;
deleteme.write("a");

// cannot make directory as it's already a file
assertThrown!FileException(deleteme.mkdirRecurse);
@parampathname the full path of the directory to create@throwsFileException on error.
mkdirRecurse
(
(local variable) string tmpDir
tmpDir
);
void sparkles.base.tools.gen_unicode_tables.fetchUcd(string ver, string remotePath, string dest)

Download a UCD input for Unicode ver into dest via libcurl (std.net.curl). Mirrors curl -fSL: follow redirects and fail on an HTTP error status instead of writing the error page to dest.

fetchUcd
(
(local variable) const(string) ver
ver
, "EastAsianWidth.txt",
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) string tmpDir
tmpDir
, "EastAsianWidth.txt"));
void sparkles.base.tools.gen_unicode_tables.fetchUcd(string ver, string remotePath, string dest)

Download a UCD input for Unicode ver into dest via libcurl (std.net.curl). Mirrors curl -fSL: follow redirects and fail on an HTTP error status instead of writing the error page to dest.

fetchUcd
(
(local variable) const(string) ver
ver
, "emoji/emoji-variation-sequences.txt",
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) string tmpDir
tmpDir
, "emoji-variation-sequences.txt"));
void sparkles.base.tools.gen_unicode_tables.fetchUcd(string ver, string remotePath, string dest)

Download a UCD input for Unicode ver into dest via libcurl (std.net.curl). Mirrors curl -fSL: follow redirects and fail on an HTTP error status instead of writing the error page to dest.

fetchUcd
(
(local variable) const(string) ver
ver
, "UnicodeData.txt",
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) string tmpDir
tmpDir
, "UnicodeData.txt"));
void sparkles.base.tools.gen_unicode_tables.fetchUcd(string ver, string remotePath, string dest)

Download a UCD input for Unicode ver into dest via libcurl (std.net.curl). Mirrors curl -fSL: follow redirects and fail on an HTTP error status instead of writing the error page to dest.

fetchUcd
(
(local variable) const(string) ver
ver
, "CaseFolding.txt",
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) string tmpDir
tmpDir
, "CaseFolding.txt"));
void sparkles.base.tools.gen_unicode_tables.fetchUcd(string ver, string remotePath, string dest)

Download a UCD input for Unicode ver into dest via libcurl (std.net.curl). Mirrors curl -fSL: follow redirects and fail on an HTTP error status instead of writing the error page to dest.

fetchUcd
(
(local variable) const(string) ver
ver
, "DerivedNormalizationProps.txt",
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) string tmpDir
tmpDir
, "DerivedNormalizationProps.txt"));
void sparkles.base.tools.gen_unicode_tables.fetchUcd(string ver, string remotePath, string dest)

Download a UCD input for Unicode ver into dest via libcurl (std.net.curl). Mirrors curl -fSL: follow redirects and fail on an HTTP error status instead of writing the error page to dest.

fetchUcd
(
(local variable) const(string) ver
ver
, "auxiliary/WordBreakProperty.txt",
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) string tmpDir
tmpDir
, "WordBreakProperty.txt"));
(local variable) string ucdDir
ucdDir
=
(local variable) string tmpDir
tmpDir
;
} auto
(local variable) string eaw
eaw
=
(local variable) string ucdDir
ucdDir
.
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
("EastAsianWidth.txt").
string std.file.readText!(string, string)(string name) @safe

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.

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");
@paramS the string type of the file@paramname string or range of characters representing the file name@returnsArray of characters read.@throwsFileException if there is an error reading the file, UTFException on UTF decoding error.@seeread for reading a binary file.
readText
;
auto
(local variable) string emojiVs
emojiVs
=
(local variable) string ucdDir
ucdDir
.
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
("emoji-variation-sequences.txt").
string std.file.readText!(string, string)(string name) @safe

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.

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");
@paramS the string type of the file@paramname string or range of characters representing the file name@returnsArray of characters read.@throwsFileException if there is an error reading the file, UTFException on UTF decoding error.@seeread for reading a binary file.
readText
;
auto
(local variable) string unicodeData
unicodeData
=
(local variable) string ucdDir
ucdDir
.
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
("UnicodeData.txt").
string std.file.readText!(string, string)(string name) @safe

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.

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");
@paramS the string type of the file@paramname string or range of characters representing the file name@returnsArray of characters read.@throwsFileException if there is an error reading the file, UTFException on UTF decoding error.@seeread for reading a binary file.
readText
;
auto
(local variable) string caseFolding
caseFolding
=
(local variable) string ucdDir
ucdDir
.
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
("CaseFolding.txt").
string std.file.readText!(string, string)(string name) @safe

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.

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");
@paramS the string type of the file@paramname string or range of characters representing the file name@returnsArray of characters read.@throwsFileException if there is an error reading the file, UTFException on UTF decoding error.@seeread for reading a binary file.
readText
;
auto
(local variable) string normalizationProps
normalizationProps
=
(local variable) string ucdDir
ucdDir
.
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
("DerivedNormalizationProps.txt").
string std.file.readText!(string, string)(string name) @safe

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.

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");
@paramS the string type of the file@paramname string or range of characters representing the file name@returnsArray of characters read.@throwsFileException if there is an error reading the file, UTFException on UTF decoding error.@seeread for reading a binary file.
readText
;
auto
(local variable) string wordBreak
wordBreak
=
(local variable) string ucdDir
ucdDir
.
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
("WordBreakProperty.txt").
string std.file.readText!(string, string)(string name) @safe

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.

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");
@paramS the string type of the file@paramname string or range of characters representing the file name@returnsArray of characters read.@throwsFileException if there is an error reading the file, UTFException on UTF decoding error.@seeread for reading a binary file.
readText
;
auto
(local variable) std.uni.InversionList!(GcPolicy) wide
wide
=
std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.parseEastAsianWidth(string text, const(string)[] wanted)

Parse a UCD property file (code[..code] ; VALUE # comment) collecting the code points whose property value is one of wanted.

parseEastAsianWidth
(
(local variable) string eaw
eaw
, ["W", "F"]);
auto
(local variable) std.uni.InversionList!(GcPolicy) ambiguous
ambiguous
=
std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.parseEastAsianWidth(string text, const(string)[] wanted)

Parse a UCD property file (code[..code] ; VALUE # comment) collecting the code points whose property value is one of wanted.

parseEastAsianWidth
(
(local variable) string eaw
eaw
, ["A"]);
auto
(local variable) std.uni.InversionList!(GcPolicy) emojiVsBase
emojiVsBase
=
std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.parseEmojiVsBases(string text)

Parse emoji-variation-sequences.txt, collecting the base code points that have an emoji style (… FE0F) presentation sequence — i.e. the bases VS16 promotes to emoji (width 2). Lines look like: 0023 FE0F ; emoji style; # ….

parseEmojiVsBases
(
(local variable) string emojiVs
emojiVs
);
auto
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables analysis
analysis
=
sparkles.base.tools.gen_unicode_tables.AnalysisTables sparkles.base.tools.gen_unicode_tables.buildAnalysisTables(string unicodeData, string caseFolding, string normalizationProps, string wordBreak)
buildAnalysisTables
(
(local variable) string unicodeData
unicodeData
,
(local variable) string caseFolding
caseFolding
,
(local variable) string normalizationProps
normalizationProps
,
(local variable) string wordBreak
wordBreak
);
void sparkles.base.styled_template.styledWritelnErr!(core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold ", core.interpolation.InterpolatedExpression!"countCodePoints(wide)", ulong, core.interpolation.InterpolatedLiteral!"} wide")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold " __param_1, core.interpolation.InterpolatedExpression!"countCodePoints(wide)" __param_2, ulong __param_3, core.interpolation.InterpolatedLiteral!"} wide" __param_4, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWritelnErr
(i"ℹ️ {bold $(countCodePoints(wide))} wide");
void sparkles.base.styled_template.styledWritelnErr!(core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold ", core.interpolation.InterpolatedExpression!"countCodePoints(ambiguous)", ulong, core.interpolation.InterpolatedLiteral!"} ambiguous")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold " __param_1, core.interpolation.InterpolatedExpression!"countCodePoints(ambiguous)" __param_2, ulong __param_3, core.interpolation.InterpolatedLiteral!"} ambiguous" __param_4, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWritelnErr
(i"ℹ️ {bold $(countCodePoints(ambiguous))} ambiguous");
void sparkles.base.styled_template.styledWritelnErr!(core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold ", core.interpolation.InterpolatedExpression!"countCodePoints(emojiVsBase)", ulong, core.interpolation.InterpolatedLiteral!"} emoji-vs bases")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold " __param_1, core.interpolation.InterpolatedExpression!"countCodePoints(emojiVsBase)" __param_2, ulong __param_3, core.interpolation.InterpolatedLiteral!"} emoji-vs bases" __param_4, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWritelnErr
(i"ℹ️ {bold $(countCodePoints(emojiVsBase))} emoji-vs bases");
void sparkles.base.styled_template.styledWritelnErr!(core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold ", core.interpolation.InterpolatedExpression!"analysis.canonical.length", ulong, core.interpolation.InterpolatedLiteral!"} canonical mappings")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold " __param_1, core.interpolation.InterpolatedExpression!"analysis.canonical.length" __param_2, ulong __param_3, core.interpolation.InterpolatedLiteral!"} canonical mappings" __param_4, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWritelnErr
(i"ℹ️ {bold $(analysis.canonical.length)} canonical mappings");
void sparkles.base.styled_template.styledWritelnErr!(core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold ", core.interpolation.InterpolatedExpression!"analysis.compatibility.length", ulong, core.interpolation.InterpolatedLiteral!"} compatibility mappings")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold " __param_1, core.interpolation.InterpolatedExpression!"analysis.compatibility.length" __param_2, ulong __param_3, core.interpolation.InterpolatedLiteral!"} compatibility mappings" __param_4, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWritelnErr
(i"ℹ️ {bold $(analysis.compatibility.length)} compatibility mappings");
void sparkles.base.styled_template.styledWritelnErr!(core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold ", core.interpolation.InterpolatedExpression!"analysis.fullFold.length", ulong, core.interpolation.InterpolatedLiteral!"} full-fold mappings")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"\xe2\x84\xb9\xef\xb8\x8f {bold " __param_1, core.interpolation.InterpolatedExpression!"analysis.fullFold.length" __param_2, ulong __param_3, core.interpolation.InterpolatedLiteral!"} full-fold mappings" __param_4, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWritelnErr
(i"ℹ️ {bold $(analysis.fullFold.length)} full-fold mappings");
void std.file.write!string(string name, const(void[]) buffer) @safe

Write buffer to file name.

Creates the file if it does not already exist.

Examples

scope(exit)
{
    assert(exists(deleteme));
    remove(deleteme);
}

int[] a = [ 0, 1, 1, 2, 3, 5, 8 ];
write(deleteme, a); // deleteme is the name of a temporary file
const bytes = read(deleteme);
const fileInts = () @trusted { return cast(int[]) bytes; }();
assert(fileInts == a);
@paramname string or range of characters representing the file name@parambuffer data to be written to file@throwsFileException on error.@seetoFile
write
(
(local variable) const(string) outFile
outFile
, [
string sparkles.base.tools.gen_unicode_tables.header(string ver)
header
(
(local variable) const(string) ver
ver
),
(local variable) std.uni.InversionList!(GcPolicy) wide
wide
.
string std.uni.InversionList!(std.uni.GcPolicy).toSourceCode(string funcName = "") @safe

Generates string with D source code of unary function with name of funcName taking a single dchar argument. If funcName is empty the code is adjusted to be a lambda function.

The function generated tests if the passed belongs to this set or not. The result is to be used with string mixin. The intended usage area is aggressive optimization via meta programming in parser generators and the like.

Note

Use with care for relatively small or regular sets. It could end up being slower then just using multi-staged tables.

Example

import std.stdio;

// construct set directly from [a, b$RPAREN intervals
auto set = CodepointSet(10, 12, 45, 65, 100, 200);
writeln(set);
writeln(set.toSourceCode("func"));

The above outputs something along the lines of:

bool func(dchar ch)  @safe pure nothrow @nogc
{
    if (ch < 45)
    {
        if (ch == 10 || ch == 11) return true;
        return false;
    }
    else if (ch < 65) return true;
    else
    {
        if (ch < 100) return false;
        if (ch < 200) return true;
        return false;
    }
}
toSourceCode
("isEastAsianWide"),
(local variable) std.uni.InversionList!(GcPolicy) ambiguous
ambiguous
.
string std.uni.InversionList!(std.uni.GcPolicy).toSourceCode(string funcName = "") @safe

Generates string with D source code of unary function with name of funcName taking a single dchar argument. If funcName is empty the code is adjusted to be a lambda function.

The function generated tests if the passed belongs to this set or not. The result is to be used with string mixin. The intended usage area is aggressive optimization via meta programming in parser generators and the like.

Note

Use with care for relatively small or regular sets. It could end up being slower then just using multi-staged tables.

Example

import std.stdio;

// construct set directly from [a, b$RPAREN intervals
auto set = CodepointSet(10, 12, 45, 65, 100, 200);
writeln(set);
writeln(set.toSourceCode("func"));

The above outputs something along the lines of:

bool func(dchar ch)  @safe pure nothrow @nogc
{
    if (ch < 45)
    {
        if (ch == 10 || ch == 11) return true;
        return false;
    }
    else if (ch < 65) return true;
    else
    {
        if (ch < 100) return false;
        if (ch < 200) return true;
        return false;
    }
}
toSourceCode
("isEastAsianAmbiguous"),
(local variable) std.uni.InversionList!(GcPolicy) emojiVsBase
emojiVsBase
.
string std.uni.InversionList!(std.uni.GcPolicy).toSourceCode(string funcName = "") @safe

Generates string with D source code of unary function with name of funcName taking a single dchar argument. If funcName is empty the code is adjusted to be a lambda function.

The function generated tests if the passed belongs to this set or not. The result is to be used with string mixin. The intended usage area is aggressive optimization via meta programming in parser generators and the like.

Note

Use with care for relatively small or regular sets. It could end up being slower then just using multi-staged tables.

Example

import std.stdio;

// construct set directly from [a, b$RPAREN intervals
auto set = CodepointSet(10, 12, 45, 65, 100, 200);
writeln(set);
writeln(set.toSourceCode("func"));

The above outputs something along the lines of:

bool func(dchar ch)  @safe pure nothrow @nogc
{
    if (ch < 45)
    {
        if (ch == 10 || ch == 11) return true;
        return false;
    }
    else if (ch < 65) return true;
    else
    {
        if (ch < 100) return false;
        if (ch < 200) return true;
        return false;
    }
}
toSourceCode
("isEmojiVsBase"),
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables analysis
analysis
.
string sparkles.base.tools.gen_unicode_tables.AnalysisTables.toSourceCode()
toSourceCode
,
].
string std.array.join!(string[], string)(string[] ror, string sep) pure nothrow @safe

Eagerly concatenates all of the ranges in ror together (with the GC) into one array using sep as the separator if present.

@paramror An input range of input ranges@paramsep An input range, or a single element, to join the ranges on@returnsAn array of elements@seeFor a lazy version, see joiner
join
("\n"));
void sparkles.base.styled_template.styledWriteln!(core.interpolation.InterpolatedLiteral!"{green wrote} {cyan ", core.interpolation.InterpolatedExpression!"outFile", string, core.interpolation.InterpolatedLiteral!"}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{green wrote} {cyan " __param_1, core.interpolation.InterpolatedExpression!"outFile" __param_2, string __param_3, core.interpolation.InterpolatedLiteral!"}" __param_4, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWriteln
(i"{green wrote} {cyan $(outFile)}");
void sparkles.base.styled_template.styledWriteln!(core.interpolation.InterpolatedLiteral!"Review the diff and commit the regenerated module.")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"Review the diff and commit the regenerated module." __param_1, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWriteln
(i"Review the diff and commit the regenerated module.");
return 0; } /// Download a UCD input for Unicode `ver` into `dest` via libcurl /// (`std.net.curl`). Mirrors `curl -fSL`: follow redirects and fail on an HTTP /// error status instead of writing the error page to `dest`. private void
void sparkles.base.tools.gen_unicode_tables.fetchUcd(string ver, string remotePath, string dest)

Download a UCD input for Unicode ver into dest via libcurl (std.net.curl). Mirrors curl -fSL: follow redirects and fail on an HTTP error status instead of writing the error page to dest.

fetchUcd
(
(alias) object.string = string
string
(parameter) string ver
ver
,
(alias) object.string = string
string
(parameter) string remotePath
remotePath
,
(alias) object.string = string
string
(parameter) string dest
dest
)
{ const
(local variable) const(string) url
url
=
(constant) string sparkles.base.tools.gen_unicode_tables.ucdBaseUrl = "https://www.unicode.org/Public"

Base URL of the Unicode Character Database.

ucdBaseUrl
~ "/" ~
(parameter) string ver
ver
~ "/ucd/" ~
(parameter) string remotePath
remotePath
;
void sparkles.base.styled_template.styledWritelnErr!(core.interpolation.InterpolatedLiteral!"{dim fetching} ", core.interpolation.InterpolatedExpression!"url", string)(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{dim fetching} " __param_1, core.interpolation.InterpolatedExpression!"url" __param_2, string __param_3, core.interpolation.InterpolationFooter footer) @system

ditto — defaults to ColorDepth.trueColor.

styledWritelnErr
(i"{dim fetching} $(url)");
auto
(local variable) std.net.curl.HTTP http
http
=
(struct) std.net.curl.HTTP

HTTP client functionality.

Example

Get with custom data receivers:

import std.net.curl, std.stdio;

auto http = HTTP("https://dlang.org");
http.onReceiveHeader =
    (in char[] key, in char[] value) { writeln(key ~ ": " ~ value); };
http.onReceive = (ubyte[] data) { /+ drop +/ return data.length; };
http.perform();

Put with data senders:

import std.net.curl, std.stdio;

auto http = HTTP("https://dlang.org");
auto msg = "Hello world";
http.contentLength = msg.length;
http.onSend = (void[] data)
{
    auto m = cast(void[]) msg;
    size_t len = m.length > data.length ? data.length : m.length;
    if (len == 0) return len;
    data[0 .. len] = m[0 .. len];
    msg = msg[len..$];
    return len;
};
http.perform();

Tracking progress:

import std.net.curl, std.stdio;

auto http = HTTP();
http.method = HTTP.Method.get;
http.url = "http://upload.wikimedia.org/wikipedia/commons/" ~
           "5/53/Wikipedia-logo-en-big.png";
http.onReceive = (ubyte[] data) { return data.length; };
http.onProgress = (size_t dltotal, size_t dlnow,
                   size_t ultotal, size_t ulnow)
{
    writeln("Progress ", dltotal, ", ", dlnow, ", ", ultotal, ", ", ulnow);
    return 0;
};
http.perform();
HTTP
();
(local variable) std.net.curl.HTTP http
http
.
std.net.curl.Curl std.net.curl.HTTP.Protocol!().handle() @property return ref

The curl handle used by this connection.

handle
.
void std.net.curl.Curl.set(etc.c.curl.CurlOption option, long value)

Set a long curl option.

@paramoption A CurlOption as found in the curl documentation@paramvalue The long
set
(
(enum) etc.c.curl.CurlOption
CurlOption
.
(enum value) etc.c.curl.CurlOption.failonerror = 45

no output on http error codes >= 300

failonerror
, 1L); // -f: 4xx/5xx → throw, no body
try
void std.net.curl.download!(std.net.curl.HTTP)(const(char)[] url, string saveToPath, std.net.curl.HTTP conn = opCall()) @system

HTTP/FTP download to local file system.

Example

import std.net.curl;
download("https://httpbin.org/get", "/tmp/downloaded-http-file");
@paramurl resource to download@paramsaveToPath path to store the downloaded content on local disk@paramconn connection to use e.g. FTP or HTTP. The default AutoProtocol will guess connection type and create a new instance for this call only.
download
(
(local variable) const(string) url
url
,
(parameter) string dest
dest
,
(local variable) std.net.curl.HTTP http
http
);
catch (
(class) std.net.curl.CurlException

Exception thrown on errors in std.net.curl functions.

CurlException
(local variable) std.net.curl.CurlException e
e
)
throw new
(class) object.Exception

The 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
(
string std.format.format!(char, string, string)(in char[] fmt, string __param_1, string __param_2) pure @safe

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

Examples

assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");

assert("Increase: %7.2f %%".format(17.4285) == "Increase:   17.43 %");
@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
("download failed for %s:\n%s",
(local variable) const(string) url
url
,
(local variable) std.net.curl.CurlException e
e
.
(field) string object.Throwable.msg

A message describing the error.

msg
));
} /// Parse a UCD property file (`code[..code] ; VALUE # comment`) collecting the /// code points whose property value is one of `wanted`.
(struct) std.uni.InversionList!(GcPolicy)
CodepointSet
std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.parseEastAsianWidth(string text, const(string)[] wanted)

Parse a UCD property file (code[..code] ; VALUE # comment) collecting the code points whose property value is one of wanted.

parseEastAsianWidth
(
(alias) object.string = string
string
(parameter) string text
text
, const(
(alias) object.string = string
string
)[]
(parameter) const(string)[] wanted
wanted
)
=>
(parameter) string text
text
.
std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.parseEastAsianWidth.ucdCodepoints!((v) => wanted.canFind(v))(string text) @system

Collect, into a CodepointSet, the leading code-point column of every data record whose value field (the column after the first ;) satisfies valueMatches. For each record: strip the trailing # comment, split on ; into whitespace-trimmed fields (comment-only and blank lines collapse to one empty field and are dropped), take the first whitespace-separated token of the code-point column, and read it as a ..-separated hex sequence — so a bare AAAA adds one code point, AAAA..BBBB adds the inclusive range, and the BASE VS form (e.g. 0023 FE0F) adds just BASE.

ucdCodepoints
!(v => wanted.canFind(v));
/// Parse emoji-variation-sequences.txt, collecting the base code points that /// have an `emoji style` (… FE0F) presentation sequence — i.e. the bases VS16 /// promotes to emoji (width 2). Lines look like: `0023 FE0F ; emoji style; # …`.
(struct) std.uni.InversionList!(GcPolicy)
CodepointSet
std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.parseEmojiVsBases(string text)

Parse emoji-variation-sequences.txt, collecting the base code points that have an emoji style (… FE0F) presentation sequence — i.e. the bases VS16 promotes to emoji (width 2). Lines look like: 0023 FE0F ; emoji style; # ….

parseEmojiVsBases
(
(alias) object.string = string
string
(parameter) string text
text
)
=>
(parameter) string text
text
.
std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.parseEmojiVsBases.ucdCodepoints!((v) => v.startsWith("emoji style"))(string text) @system

Collect, into a CodepointSet, the leading code-point column of every data record whose value field (the column after the first ;) satisfies valueMatches. For each record: strip the trailing # comment, split on ; into whitespace-trimmed fields (comment-only and blank lines collapse to one empty field and are dropped), take the first whitespace-separated token of the code-point column, and read it as a ..-separated hex sequence — so a bare AAAA adds one code point, AAAA..BBBB adds the inclusive range, and the BASE VS form (e.g. 0023 FE0F) adds just BASE.

ucdCodepoints
!(v => v.startsWith("emoji style"));
/// Collect, into a `CodepointSet`, the leading code-point column of every data /// record whose value field (the column after the first `;`) satisfies /// `valueMatches`. For each record: strip the trailing `# comment`, split on `;` /// into whitespace-trimmed fields (comment-only and blank lines collapse to one /// empty field and are dropped), take the first whitespace-separated token of the /// code-point column, and read it as a `..`-separated hex sequence — so a bare /// `AAAA` adds one code point, `AAAA..BBBB` adds the inclusive range, and the /// `BASE VS` form (e.g. `0023 FE0F`) adds just `BASE`.
(struct) std.uni.InversionList!(GcPolicy)
CodepointSet
std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.parseEmojiVsBases.ucdCodepoints!((v) => v.startsWith("emoji style"))(string text) @system

Collect, into a CodepointSet, the leading code-point column of every data record whose value field (the column after the first ;) satisfies valueMatches. For each record: strip the trailing # comment, split on ; into whitespace-trimmed fields (comment-only and blank lines collapse to one empty field and are dropped), take the first whitespace-separated token of the code-point column, and read it as a ..-separated hex sequence — so a bare AAAA adds one code point, AAAA..BBBB adds the inclusive range, and the BASE VS form (e.g. 0023 FE0F) adds just BASE.

ucdCodepoints
(alias valueMatches)(
(alias) object.string = string
string
(parameter) string text
text
)
{
(struct) std.uni.InversionList!(GcPolicy)
CodepointSet
(local variable) std.uni.InversionList!(GcPolicy) set
set
;
foreach (
(local variable) string[] fields
fields
;
(parameter) string text
text
.
std.string.LineSplitter!(Flag.no, string) std.string.lineSplitter!(Flag.no, immutable(char))(string r) pure nothrow @nogc @safe

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.

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);
@paramr array of chars, wchars, or dchars or a slicable range@paramkeepTerm whether delimiter is included or not in the results@returnsrange of slices of the input range r@seesplitLines splitter splitter
lineSplitter
.
std.algorithm.iteration.MapResult!(stripComment, LineSplitter!(Flag.no, string)) std.algorithm.iteration.map!(stripComment).map!(std.string.LineSplitter!(Flag.no, string))(std.string.LineSplitter!(Flag.no, string) r) pure nothrow @nogc @safe

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.

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" ]));
@paramfun one or more transformation functions@seeMap (higher-order function)@paramr an input range@returnsA range with each fun applied to all the elements. If there is more than one fun, the element type will be Tuple containing one element for each fun.
map
!
string sparkles.base.tools.gen_unicode_tables.stripComment(string line)

Strip a trailing # comment and surrounding whitespace from a UCD line. findSplit("#")[0] is the text before the first #, or the whole line when there is none.

stripComment
.
sparkles.base.tools.gen_unicode_tables.parseEmojiVsBases.ucdCodepoints!((v) => v.startsWith("emoji style")).MapResult!(__lambda_L194_C15, MapResult!(stripComment, LineSplitter!(Flag.no, string))) sparkles.base.tools.gen_unicode_tables.parseEmojiVsBases.ucdCodepoints!((v) => v.startsWith("emoji style")).map!(std.algorithm.iteration.MapResult!(stripComment, LineSplitter!(Flag.no, string)))(std.algorithm.iteration.MapResult!(stripComment, LineSplitter!(Flag.no, string)) r) pure nothrow @nogc @safe

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.

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" ]));
@paramfun one or more transformation functions@seeMap (higher-order function)@paramr an input range@returnsA range with each fun applied to all the elements. If there is more than one fun, the element type will be Tuple containing one element for each fun.
map
!(line => line.splitter(';').map!strip.array)
.
sparkles.base.tools.gen_unicode_tables.parseEmojiVsBases.ucdCodepoints!((v) => v.startsWith("emoji style")).FilterResult!(__lambda_L195_C18, MapResult!(__lambda_L194_C15, MapResult!(stripComment, LineSplitter!(Flag.no, string)))) sparkles.base.tools.gen_unicode_tables.parseEmojiVsBases.ucdCodepoints!((v) => v.startsWith("emoji style")).filter!(sparkles.base.tools.gen_unicode_tables.parseEmojiVsBases.ucdCodepoints!((v) => v.startsWith("emoji style")).MapResult!(__lambda_L194_C15, MapResult!(stripComment, LineSplitter!(Flag.no, string))))(sparkles.base.tools.gen_unicode_tables.parseEmojiVsBases.ucdCodepoints!((v) => v.startsWith("emoji style")).MapResult!(__lambda_L194_C15, MapResult!(stripComment, LineSplitter!(Flag.no, string))) range) pure nothrow @nogc @safe

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).

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 ]));
@parampredicate Function to apply to each element of range@returnsAn input range that contains the filtered elements. If range is at least a forward range, the return value of filter will also be a forward range.@seeFilter (higher-order function), filterBidirectional@paramrange An input range of elements@returnsA range containing only elements x in range for which predicate(x) returns true.
filter
!(rec => rec.length >= 2 && valueMatches(rec[1])))
{ auto
(local variable) string code
code
=
(local variable) string[] fields
fields
[0].
std.algorithm.iteration.SplitterResult!(isWhite, string) std.algorithm.iteration.splitter!(isWhite, string)(string r) pure @safe

Lazily splits a range r whenever a predicate isTerminator returns true for an element.

As above, two adjacent separators are considered to surround an empty element in the split range.

Examples

import std.ascii : isWhite;
import std.algorithm.comparison : equal;
import std.algorithm.iteration : splitter;

string str = "Hello World\t!";
assert(str.splitter!(isWhite).equal(["Hello", "World", "!"]));
import std.algorithm.comparison : equal;
import std.range.primitives : front;

assert(equal(splitter!(a => a == '|')("a|bc|def"), [ "a", "bc", "def" ]));
assert(equal(splitter!(a => a == ' ')("hello  world"), [ "hello", "", "world" ]));

int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
int[][] w = [ [1, 2], [], [3], [4, 5], [] ];
assert(equal(splitter!(a => a == 0)(a), w));

a = [ 0 ];
assert(equal(splitter!(a => a == 0)(a), [ (int[]).init, (int[]).init ]));

a = [ 0, 1 ];
assert(equal(splitter!(a => a == 0)(a), [ [], [1] ]));

w = [ [0], [1], [2] ];
assert(equal(splitter!(a => a.front == 1)(w), [ [[0]], [[2]] ]));
@paramr The forward range to be split.@paramisTerminator A unary predicate for deciding where to split the range.@returnsA forward range of slices of the original range split by whitespace.
splitter
!
bool std.uni.isWhite(dchar c) pure nothrow @nogc @safe

Whether or not c is a Unicode whitespace . (general Unicode category: Part of C0(tab, vertical tab, form feed, carriage return, and linefeed characters), Zs, Zl, Zp, and NEL(U+0085))

isWhite
.
string std.algorithm.iteration.SplitterResult!(isWhite, string).front() pure nothrow @property @safe
front
;
uint[]
(local variable) uint[] cps
cps
;
(local variable) string code
code
.
uint std.format.read.formattedRead!("%(%x%|..%)", string, uint[])(ref string r, ref uint[] __param_1) pure @safe

Reads an input range according to a format string and stores the read values into its arguments.

Format specifiers with format character 'd', 'u' and 'c' can take a ''* parameter for skipping values.

The second version of formattedRead takes the format string as template argument. In this case, it is checked for consistency at compile-time.

Note

For backward compatibility the arguments args can be given as pointers to that variable, but it is not recommended to do so, because this option might be removed in the future.

Examples

string object;
char cmp;
int value;

assert(formattedRead("angle < 36", "%s %c %d", object, cmp, value) == 3);
assert(object == "angle");
assert(cmp == '<');
assert(value == 36);

// reading may end early:
assert(formattedRead("length >", "%s %c %d", object, cmp, value) == 2);
assert(object == "length");
assert(cmp == '>');
// value is not changed:
assert(value == 36);

The format string can be checked at compile-time:

string a;
int b;
double c;

assert("hello!124:34.5".formattedRead!"%s!%s:%s"(a, b, c) == 3);
assert(a == "hello");
assert(b == 124);
assert(c == 34.5);

Skipping values

string item;
double amount;

assert("orange: (12%) 15.25".formattedRead("%s: (%*d%%) %f", item, amount) == 2);
assert(item == "orange");
assert(amount == 15.25);

// can also be used with tuples
import std.typecons : Tuple;

Tuple!(int, float) t;
char[] line = "1 7643 2.125".dup;
formattedRead(line, "%s %*u %s", t);
assert(t[0] == 1 && t[1] == 2.125);
@paramr an input range, where the formatted input is read from@paramfmt a format string@paramargs a variadic list of arguments where the read values are stored@paramRange the type of the input range r@paramChar the character type used for fmt@paramArgs a variadic list of types of the arguments@returnsThe number of variables filled. If the input range r ends early, this number will be less than the number of variables provided.@throwsA FormatException if reading did not succeed.
formattedRead
!"%(%x%|..%)"(
(local variable) uint[] cps
cps
);
(local variable) std.uni.InversionList!(GcPolicy) set
set
.
std.uni.InversionList!(GcPolicy) std.uni.InversionList!(std.uni.GcPolicy).add!()(uint a, uint b) pure nothrow ref @safe

Add an interval [a, b) to this set.

add
(
(local variable) uint[] cps
cps
[0],
(local variable) uint[] cps
cps
[$ - 1] + 1); // add takes a half-open [a, b) interval
} return
(local variable) std.uni.InversionList!(GcPolicy) set
set
;
} /// Strip a trailing `# comment` and surrounding whitespace from a UCD line. /// `findSplit("#")[0]` is the text before the first `#`, or the whole line when /// there is none. private
(alias) object.string = string
string
string sparkles.base.tools.gen_unicode_tables.stripComment(string line)

Strip a trailing # comment and surrounding whitespace from a UCD line. findSplit("#")[0] is the text before the first #, or the whole line when there is none.

stripComment
(
(alias) object.string = string
string
(parameter) string line
line
) =>
(parameter) string line
line
.
std.algorithm.searching.FindSplitResult!(cast(ubyte)1u, string, string, string) std.algorithm.searching.findSplit!("a == b", string, string)(string haystack, string needle) pure nothrow @nogc @safe

These functions find the first occurrence of needle in haystack and then split haystack as follows.

findSplit returns a tuple result containing three ranges.

  • result[0] is the portion of haystack before needle

  • result[1] is the portion of haystack that matches needle

  • result[2] is the portion of haystack after the match.

If needle was not found, result[0] comprehends haystack entirely and result[1] and result[2] are empty.

findSplitBefore returns a tuple result containing two ranges.

  • result[0] is the portion of haystack before needle

  • result[1] is the balance of haystack starting with the match.

If needle was not found, result[0] comprehends haystack entirely and result[1] is empty.

findSplitAfter returns a tuple result containing two ranges.

  • result[0] is the portion of haystack up to and including the match

  • result[1] is the balance of haystack starting after the match.

If needle was not found, result[0] is empty and result[1] is haystack.

In all cases, the concatenation of the returned ranges spans the entire haystack.

If haystack is a random-access range, all three components of the tuple have the same type as haystack. Otherwise, haystack must be a forward range and the type of result[0] (and result[1] for findSplit) is the same as the result of takeExactly.

For more information about pred see find.

@parampred Predicate to compare 2 elements.@paramhaystack The forward range to search.@paramneedle The forward range to look for.@returnsA sub-type of Tuple of the split portions of haystack (see above for details). This sub-type of Tuple defines opCast!bool, which returns true when the separating needle was found and false otherwise.@seefind
findSplit
("#")[0].
string std.string.strip!string(string str) pure nothrow @nogc @safe

Strips both leading and trailing whitespace (as defined by isWhite) or as specified in the second argument.

Examples

import std.uni : lineSep, paraSep;
assert(strip("     hello world     ") ==
       "hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
       "hello world");
assert(strip("hello world") ==
       "hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
       "hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
       "hello world");
@paramstr string or random access range of characters@paramchars string of characters to be stripped@paramleftChars string of leading characters to be stripped@paramrightChars string of trailing characters to be stripped@returnsslice of str stripped of leading and trailing whitespace or characters as specified in the second argument.@seeGeneric stripping on ranges: strip
strip
;
private
(alias) object.size_t = ulong
size_t
ulong sparkles.base.tools.gen_unicode_tables.countCodePoints(std.uni.InversionList!(GcPolicy) set)
countCodePoints
(
(struct) std.uni.InversionList!(GcPolicy)
CodepointSet
(parameter) std.uni.InversionList!(GcPolicy) set
set
)
{ return
(parameter) std.uni.InversionList!(GcPolicy) set
set
.
std.uni.InversionList!(GcPolicy).Intervals!(uint[]) std.uni.InversionList!(std.uni.GcPolicy).byInterval() pure @property scope @safe

Get range that spans all of the intervals in this InversionList.

byInterval
.
sparkles.base.tools.gen_unicode_tables.countCodePoints.MapResult!(__lambda_L213_C15, Intervals!(uint[])) sparkles.base.tools.gen_unicode_tables.countCodePoints.map!(std.uni.InversionList!(GcPolicy).Intervals!(uint[]))(std.uni.InversionList!(GcPolicy).Intervals!(uint[]) r) pure nothrow @nogc @safe

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.

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" ]));
@paramfun one or more transformation functions@seeMap (higher-order function)@paramr an input range@returnsA range with each fun applied to all the elements. If there is more than one fun, the element type will be Tuple containing one element for each fun.
map
!(ival => ival[1] - ival[0])
.
uint std.algorithm.iteration.sum!(sparkles.base.tools.gen_unicode_tables.countCodePoints.MapResult!(__lambda_L213_C15, Intervals!(uint[])))(sparkles.base.tools.gen_unicode_tables.countCodePoints.MapResult!(__lambda_L213_C15, Intervals!(uint[])) r) pure nothrow @nogc @safe

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.

@paramseed the initial value of the summation@paramr a finite input range@returnsThe sum of all the elements in the range r.
sum
;
} private struct
(struct) sparkles.base.tools.gen_unicode_tables.UcdRecord
UcdRecord
{
(alias) object.string = string
string
(field) string sparkles.base.tools.gen_unicode_tables.UcdRecord.category
category
;
bool
(field) bool sparkles.base.tools.gen_unicode_tables.UcdRecord.compatibility
compatibility
;
uint[]
(field) uint[] sparkles.base.tools.gen_unicode_tables.UcdRecord.decomposition
decomposition
;
} private struct
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
{ uint
(field) uint sparkles.base.tools.gen_unicode_tables.SequenceMapping.codepoint
codepoint
;
uint[]
(field) uint[] sparkles.base.tools.gen_unicode_tables.SequenceMapping.values
values
;
} private struct
(struct) sparkles.base.tools.gen_unicode_tables.ScalarMapping
ScalarMapping
{ uint
(field) uint sparkles.base.tools.gen_unicode_tables.ScalarMapping.codepoint
codepoint
;
uint
(field) uint sparkles.base.tools.gen_unicode_tables.ScalarMapping.value
value
;
} private struct
(struct) sparkles.base.tools.gen_unicode_tables.CompositionMapping
CompositionMapping
{ uint
(field) uint sparkles.base.tools.gen_unicode_tables.CompositionMapping.first
first
;
uint
(field) uint sparkles.base.tools.gen_unicode_tables.CompositionMapping.second
second
;
uint
(field) uint sparkles.base.tools.gen_unicode_tables.CompositionMapping.value
value
;
} private struct
(struct) sparkles.base.tools.gen_unicode_tables.WordBreakRange
WordBreakRange
{ uint
(field) uint sparkles.base.tools.gen_unicode_tables.WordBreakRange.first
first
;
uint
(field) uint sparkles.base.tools.gen_unicode_tables.WordBreakRange.last
last
;
(alias) object.string = string
string
(field) string sparkles.base.tools.gen_unicode_tables.WordBreakRange.property
property
;
} private struct
(struct) sparkles.base.tools.gen_unicode_tables.AnalysisTables
AnalysisTables
{
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
[]
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.canonical
canonical
;
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
[]
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.compatibility
compatibility
;
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
[]
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.fullFold
fullFold
;
(struct) sparkles.base.tools.gen_unicode_tables.ScalarMapping
ScalarMapping
[]
(field) sparkles.base.tools.gen_unicode_tables.ScalarMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.simpleFold
simpleFold
;
(struct) sparkles.base.tools.gen_unicode_tables.CompositionMapping
CompositionMapping
[]
(field) sparkles.base.tools.gen_unicode_tables.CompositionMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.compositions
compositions
;
(struct) sparkles.base.tools.gen_unicode_tables.WordBreakRange
WordBreakRange
[]
(field) sparkles.base.tools.gen_unicode_tables.WordBreakRange[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.wordBreak
wordBreak
;
(struct) std.uni.InversionList!(GcPolicy)
CodepointSet
(field) std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.AnalysisTables.marks
marks
;
(struct) std.uni.InversionList!(GcPolicy)
CodepointSet
(field) std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.AnalysisTables.uppercase
uppercase
;
(struct) sparkles.base.tools.gen_unicode_tables.ScalarMapping
ScalarMapping
[]
(field) sparkles.base.tools.gen_unicode_tables.ScalarMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.canonicalClasses
canonicalClasses
;
(alias) object.string = string
string
string sparkles.base.tools.gen_unicode_tables.AnalysisTables.toSourceCode()
toSourceCode
()
{ return [
(constant) string sparkles.base.tools.gen_unicode_tables.analysisTypesSource = "\n/// A borrowed span inside one of the generated flat Unicode mapping arrays.\nstruct UnicodeMappingSpan\n{\n uint offset;\n ubyte length;\n}\n\nprivate struct UnicodeSequenceIndex\n{\n uint codepoint;\n uint offset;\n ubyte length;\n}\n\nprivate struct UnicodeScalarIndex\n{\n uint codepoint;\n uint value;\n}\n\nprivate UnicodeMappingSpan findUnicodeSequence(scope const(UnicodeSequenceIndex)[] index,\n dchar ch) @safe pure nothrow @nogc\n{\n size_t lo;\n size_t hi = index.length;\n while (lo < hi)\n {\n const mid = lo + (hi - lo) / 2;\n if (index[mid].codepoint < ch)\n lo = mid + 1;\n else\n hi = mid;\n }\n return lo < index.length && index[lo].codepoint == ch\n ? UnicodeMappingSpan(index[lo].offset, index[lo].length)\n : UnicodeMappingSpan.init;\n}\n\nprivate dchar findUnicodeScalar(scope const(UnicodeScalarIndex)[] index,\n dchar ch) @safe pure nothrow @nogc\n{\n size_t lo;\n size_t hi = index.length;\n while (lo < hi)\n {\n const mid = lo + (hi - lo) / 2;\n if (index[mid].codepoint < ch)\n lo = mid + 1;\n else\n hi = mid;\n }\n return lo < index.length && index[lo].codepoint == ch\n ? cast(dchar) index[lo].value : ch;\n}\n\nprivate uint findUnicodeProperty(scope const(UnicodeScalarIndex)[] index,\n dchar ch) @safe pure nothrow @nogc\n{\n size_t lo;\n size_t hi = index.length;\n while (lo < hi)\n {\n const mid = lo + (hi - lo) / 2;\n if (index[mid].codepoint < ch)\n lo = mid + 1;\n else\n hi = mid;\n }\n return lo < index.length && index[lo].codepoint == ch\n ? index[lo].value : 0;\n}\n"
analysisTypesSource
,
(field) std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.AnalysisTables.marks
marks
.
string std.uni.InversionList!(std.uni.GcPolicy).toSourceCode(string funcName = "") @safe

Generates string with D source code of unary function with name of funcName taking a single dchar argument. If funcName is empty the code is adjusted to be a lambda function.

The function generated tests if the passed belongs to this set or not. The result is to be used with string mixin. The intended usage area is aggressive optimization via meta programming in parser generators and the like.

Note

Use with care for relatively small or regular sets. It could end up being slower then just using multi-staged tables.

Example

import std.stdio;

// construct set directly from [a, b$RPAREN intervals
auto set = CodepointSet(10, 12, 45, 65, 100, 200);
writeln(set);
writeln(set.toSourceCode("func"));

The above outputs something along the lines of:

bool func(dchar ch)  @safe pure nothrow @nogc
{
    if (ch < 45)
    {
        if (ch == 10 || ch == 11) return true;
        return false;
    }
    else if (ch < 65) return true;
    else
    {
        if (ch < 100) return false;
        if (ch < 200) return true;
        return false;
    }
}
toSourceCode
("isUnicodeMark"),
(field) std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.AnalysisTables.uppercase
uppercase
.
string std.uni.InversionList!(std.uni.GcPolicy).toSourceCode(string funcName = "") @safe

Generates string with D source code of unary function with name of funcName taking a single dchar argument. If funcName is empty the code is adjusted to be a lambda function.

The function generated tests if the passed belongs to this set or not. The result is to be used with string mixin. The intended usage area is aggressive optimization via meta programming in parser generators and the like.

Note

Use with care for relatively small or regular sets. It could end up being slower then just using multi-staged tables.

Example

import std.stdio;

// construct set directly from [a, b$RPAREN intervals
auto set = CodepointSet(10, 12, 45, 65, 100, 200);
writeln(set);
writeln(set.toSourceCode("func"));

The above outputs something along the lines of:

bool func(dchar ch)  @safe pure nothrow @nogc
{
    if (ch < 45)
    {
        if (ch == 10 || ch == 11) return true;
        return false;
    }
    else if (ch < 65) return true;
    else
    {
        if (ch < 100) return false;
        if (ch < 200) return true;
        return false;
    }
}
toSourceCode
("isUnicodeUppercase"),
string sparkles.base.tools.gen_unicode_tables.scalarPropertyTableSource(string name, const(sparkles.base.tools.gen_unicode_tables.ScalarMapping)[] mappings)
scalarPropertyTableSource
("canonicalCombiningClass",
(field) sparkles.base.tools.gen_unicode_tables.ScalarMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.canonicalClasses
canonicalClasses
),
string sparkles.base.tools.gen_unicode_tables.sequenceTableSource(string name, const(sparkles.base.tools.gen_unicode_tables.SequenceMapping)[] mappings)
sequenceTableSource
("canonicalDecomposition",
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.canonical
canonical
),
string sparkles.base.tools.gen_unicode_tables.sequenceTableSource(string name, const(sparkles.base.tools.gen_unicode_tables.SequenceMapping)[] mappings)
sequenceTableSource
("compatibilityDecomposition",
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.compatibility
compatibility
),
string sparkles.base.tools.gen_unicode_tables.sequenceTableSource(string name, const(sparkles.base.tools.gen_unicode_tables.SequenceMapping)[] mappings)
sequenceTableSource
("fullCaseFold",
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.fullFold
fullFold
),
string sparkles.base.tools.gen_unicode_tables.scalarTableSource(string name, const(sparkles.base.tools.gen_unicode_tables.ScalarMapping)[] mappings)
scalarTableSource
("simpleCaseFold",
(field) sparkles.base.tools.gen_unicode_tables.ScalarMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.simpleFold
simpleFold
),
string sparkles.base.tools.gen_unicode_tables.compositionTableSource(const(sparkles.base.tools.gen_unicode_tables.CompositionMapping)[] mappings)
compositionTableSource
(
(field) sparkles.base.tools.gen_unicode_tables.CompositionMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.compositions
compositions
),
string sparkles.base.tools.gen_unicode_tables.wordBreakTableSource(const(sparkles.base.tools.gen_unicode_tables.WordBreakRange)[] ranges)
wordBreakTableSource
(
(field) sparkles.base.tools.gen_unicode_tables.WordBreakRange[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.wordBreak
wordBreak
),
].
string std.array.join!(string[], string)(string[] ror, string sep) pure nothrow @safe

Eagerly concatenates all of the ranges in ror together (with the GC) into one array using sep as the separator if present.

@paramror An input range of input ranges@paramsep An input range, or a single element, to join the ranges on@returnsAn array of elements@seeFor a lazy version, see joiner
join
("\n");
} } private
(struct) sparkles.base.tools.gen_unicode_tables.AnalysisTables
AnalysisTables
sparkles.base.tools.gen_unicode_tables.AnalysisTables sparkles.base.tools.gen_unicode_tables.buildAnalysisTables(string unicodeData, string caseFolding, string normalizationProps, string wordBreak)
buildAnalysisTables
(
(alias) object.string = string
string
(parameter) string unicodeData
unicodeData
,
(alias) object.string = string
string
(parameter) string caseFolding
caseFolding
,
(alias) object.string = string
string
(parameter) string normalizationProps
normalizationProps
,
(alias) object.string = string
string
(parameter) string wordBreak
wordBreak
)
{
(struct) sparkles.base.tools.gen_unicode_tables.AnalysisTables
AnalysisTables
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
;
(struct) sparkles.base.tools.gen_unicode_tables.UcdRecord
UcdRecord
[uint]
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records
records
;
foreach (
(local variable) string line
line
;
(parameter) string unicodeData
unicodeData
.
std.string.LineSplitter!(Flag.no, string) std.string.lineSplitter!(Flag.no, immutable(char))(string r) pure nothrow @nogc @safe

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.

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);
@paramr array of chars, wchars, or dchars or a slicable range@paramkeepTerm whether delimiter is included or not in the results@returnsrange of slices of the input range r@seesplitLines splitter splitter
lineSplitter
)
{ auto
(local variable) string[] fields
fields
=
(local variable) string line
line
.
std.algorithm.iteration.splitter!("a == b", Flag.no, string, char).Result std.algorithm.iteration.splitter!("a == b", Flag.no, string, char)(string r, char s) pure nothrow @nogc @safe

Lazily splits a range using an element or range as a separator. Separator ranges can be any narrow string type or sliceable range type.

Two adjacent separators are considered to surround an empty element in the split range. Use filter!(a => !a.empty) on the result to compress empty elements.

The predicate is passed to binaryFun and accepts any callable function that can be executed via pred(element, s).

Note

If splitting a string on whitespace and token compression is desired, consider using the ``splitter(r) overload.

Constraints

The predicate pred needs to accept an element of r and the separator s.

Examples

Basic splitting with characters and numbers.

import std.algorithm.comparison : equal;

assert("a|bc|def".splitter('|').equal([ "a", "bc", "def" ]));

int[] a = [1, 0, 2, 3, 0, 4, 5, 6];
int[][] w = [ [1], [2, 3], [4, 5, 6] ];
assert(a.splitter(0).equal(w));

Basic splitting with characters and numbers and keeping sentinels.

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("a|bc|def".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "a", "|", "bc", "|", "def" ]));

int[] a = [1, 0, 2, 3, 0, 4, 5, 6];
int[][] w = [ [1], [0], [2, 3], [0], [4, 5, 6] ];
assert(a.splitter!("a == b", Yes.keepSeparators)(0).equal(w));

Adjacent separators.

import std.algorithm.comparison : equal;

assert("|ab|".splitter('|').equal([ "", "ab", "" ]));
assert("ab".splitter('|').equal([ "ab" ]));

assert("a|b||c".splitter('|').equal([ "a", "b", "", "c" ]));
assert("hello  world".splitter(' ').equal([ "hello", "", "world" ]));

auto a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
auto w = [ [1, 2], [], [3], [4, 5], [] ];
assert(a.splitter(0).equal(w));

Adjacent separators and keeping sentinels.

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("|ab|".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "ab", "|", "" ]));
assert("ab".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "ab" ]));

assert("a|b||c".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "a", "|", "b", "|", "", "|", "c" ]));
assert("hello  world".splitter!("a == b", Yes.keepSeparators)(' ')
    .equal([ "hello", " ", "", " ", "world" ]));

auto a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
auto w = [ [1, 2], [0], [], [0], [3], [0], [4, 5], [0], [] ];
assert(a.splitter!("a == b", Yes.keepSeparators)(0).equal(w));

Empty and separator-only ranges.

import std.algorithm.comparison : equal;
import std.range : empty;

assert("".splitter('|').empty);
assert("|".splitter('|').equal([ "", "" ]));
assert("||".splitter('|').equal([ "", "", "" ]));

Empty and separator-only ranges and keeping sentinels.

import std.algorithm.comparison : equal;
import std.typecons : Yes;
import std.range : empty;

assert("".splitter!("a == b", Yes.keepSeparators)('|').empty);
assert("|".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "" ]));
assert("||".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "", "|", "" ]));

Use a range for splitting

import std.algorithm.comparison : equal;

assert("a=>bc=>def".splitter("=>").equal([ "a", "bc", "def" ]));
assert("a|b||c".splitter("||").equal([ "a|b", "c" ]));
assert("hello  world".splitter("  ").equal([ "hello", "world" ]));

int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
int[][] w = [ [1, 2], [3, 0, 4, 5, 0] ];
assert(a.splitter([0, 0]).equal(w));

a = [ 0, 0 ];
assert(a.splitter([0, 0]).equal([ (int[]).init, (int[]).init ]));

a = [ 0, 0, 1 ];
assert(a.splitter([0, 0]).equal([ [], [1] ]));

Use a range for splitting

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("a=>bc=>def".splitter!("a == b", Yes.keepSeparators)("=>")
    .equal([ "a", "=>", "bc", "=>", "def" ]));
assert("a|b||c".splitter!("a == b", Yes.keepSeparators)("||")
    .equal([ "a|b", "||", "c" ]));
assert("hello  world".splitter!("a == b", Yes.keepSeparators)("  ")
    .equal([ "hello", "  ",  "world" ]));

int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
int[][] w = [ [1, 2], [0, 0], [3, 0, 4, 5, 0] ];
assert(a.splitter!("a == b", Yes.keepSeparators)([0, 0]).equal(w));

a = [ 0, 0 ];
assert(a.splitter!("a == b", Yes.keepSeparators)([0, 0])
    .equal([ (int[]).init, [0, 0], (int[]).init ]));

a = [ 0, 0, 1 ];
assert(a.splitter!("a == b", Yes.keepSeparators)([0, 0])
    .equal([ [], [0, 0], [1] ]));

Custom predicate functions.

import std.algorithm.comparison : equal;
import std.ascii : toLower;

assert("abXcdxef".splitter!"a.toLower == b"('x').equal(
             [ "ab", "cd", "ef" ]));

auto w = [ [0], [1], [2] ];
assert(w.splitter!"a.front == b"(1).equal([ [[0]], [[2]] ]));

Custom predicate functions.

import std.algorithm.comparison : equal;
import std.typecons : Yes;
import std.ascii : toLower;

assert("abXcdxef".splitter!("a.toLower == b", Yes.keepSeparators)('x')
    .equal([ "ab", "X", "cd", "x", "ef" ]));

auto w = [ [0], [1], [2] ];
assert(w.splitter!("a.front == b", Yes.keepSeparators)(1)
    .equal([ [[0]], [[1]], [[2]] ]));

Leading separators, trailing separators, or no separators.

import std.algorithm.comparison : equal;

assert("|ab|".splitter('|').equal([ "", "ab", "" ]));
assert("ab".splitter('|').equal([ "ab" ]));

Leading separators, trailing separators, or no separators.

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("|ab|".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "ab", "|", "" ]));
assert("ab".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "ab" ]));

Splitter returns bidirectional ranges if the delimiter is a single element

import std.algorithm.comparison : equal;
import std.range : retro;
assert("a|bc|def".splitter('|').retro.equal([ "def", "bc", "a" ]));

Splitter returns bidirectional ranges if the delimiter is a single element

import std.algorithm.comparison : equal;
import std.typecons : Yes;
import std.range : retro;
assert("a|bc|def".splitter!("a == b", Yes.keepSeparators)('|')
    .retro.equal([ "def", "|", "bc", "|", "a" ]));
@parampred The predicate for comparing each element with the separator, defaulting to "a == b".@paramr The input range to be split. Must support slicing and .length or be a narrow string type.@params The element (or range) to be treated as the separator between range segments to be split.@paramkeepSeparators The flag for deciding if the separators are kept@returns

An input range of the subranges of elements between separators. If r is a forward range or bidirectional range, the returned range will be likewise. When a range is used a separator, bidirectionality isn't possible.

If keepSeparators is equal to Yes.keepSeparators the output will also contain the separators.

If an empty range is given, the result is an empty range. If a range with one separator is given, the result is a range with two empty elements.

@see
  • splitter for a version that splits using a regular expression defined separator.

  • split for a version that splits eagerly.

  • splitWhen, which compares adjacent elements instead of element against separator.

splitter
(';').
string[] std.array.array!(std.algorithm.iteration.splitter!("a == b", Flag.no, string, char).Result)(std.algorithm.iteration.splitter!("a == b", Flag.no, string, char).Result r) pure @safe

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.

@paramr range (or aggregate with opApply function) whose elements are copied into the allocated array@returnsallocated and initialized array
array
;
if (
(local variable) string[] fields
fields
.
(field) ulong string[].length
length
< 15)
continue; const
(local variable) const(uint) cp
cp
=
uint sparkles.base.tools.gen_unicode_tables.parseHex(string text)
parseHex
(
(local variable) string[] fields
fields
[0]);
const
(local variable) const(string) category
category
=
(local variable) string[] fields
fields
[2];
const
(local variable) const(uint) canonicalClass
canonicalClass
=
(local variable) string[] fields
fields
[3].
uint std.conv.to!uint.to!string(string __param_0) pure @safe

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

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
!uint;
if (
(local variable) const(uint) canonicalClass
canonicalClass
!= 0)
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.ScalarMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.canonicalClasses
canonicalClasses
~=
(struct) sparkles.base.tools.gen_unicode_tables.ScalarMapping
ScalarMapping
(
(local variable) const(uint) cp
cp
,
(local variable) const(uint) canonicalClass
canonicalClass
);
if (
(local variable) const(string) category
category
== "Mn" ||
(local variable) const(string) category
category
== "Mc" ||
(local variable) const(string) category
category
== "Me")
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.AnalysisTables.marks
marks
.
std.uni.InversionList!(GcPolicy) std.uni.InversionList!(std.uni.GcPolicy).add!()(uint a, uint b) pure nothrow ref @safe

Add an interval [a, b) to this set.

add
(
(local variable) const(uint) cp
cp
,
(local variable) const(uint) cp
cp
+ 1);
if (
(local variable) const(string) category
category
== "Lu" ||
(local variable) const(string) category
category
== "Lt")
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.AnalysisTables.uppercase
uppercase
.
std.uni.InversionList!(GcPolicy) std.uni.InversionList!(std.uni.GcPolicy).add!()(uint a, uint b) pure nothrow ref @safe

Add an interval [a, b) to this set.

add
(
(local variable) const(uint) cp
cp
,
(local variable) const(uint) cp
cp
+ 1);
(struct) sparkles.base.tools.gen_unicode_tables.UcdRecord
UcdRecord
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
;
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
.
(field) string sparkles.base.tools.gen_unicode_tables.UcdRecord.category
category
=
(local variable) const(string) category
category
;
auto
(local variable) string decomp
decomp
=
(local variable) string[] fields
fields
[5].
string std.string.strip!string(string str) pure nothrow @nogc @safe

Strips both leading and trailing whitespace (as defined by isWhite) or as specified in the second argument.

Examples

import std.uni : lineSep, paraSep;
assert(strip("     hello world     ") ==
       "hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
       "hello world");
assert(strip("hello world") ==
       "hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
       "hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
       "hello world");
@paramstr string or random access range of characters@paramchars string of characters to be stripped@paramleftChars string of leading characters to be stripped@paramrightChars string of trailing characters to be stripped@returnsslice of str stripped of leading and trailing whitespace or characters as specified in the second argument.@seeGeneric stripping on ranges: strip
strip
;
if (
(local variable) string decomp
decomp
.
(field) ulong string.length
length
)
{ auto
(local variable) string[] pieces
pieces
=
(local variable) string decomp
decomp
.
std.algorithm.iteration.splitter!string.Result std.algorithm.iteration.splitter!string(string s) pure @safe

Lazily splits the character-based range s into words, using whitespace as the delimiter.

This function is character-range specific and, contrary to ``splitter!(std.uni.isWhite), runs of whitespace will be merged together (no empty tokens will be produced).

Examples

import std.algorithm.comparison : equal;
auto a = " a     bcd   ef gh ";
assert(equal(splitter(a), ["a", "bcd", "ef", "gh"][]));
@params The character-based range to be split. Must be a string, or a random-access range of character types.@returnsAn input range of slices of the original range split by whitespace.
splitter
.
string[] std.array.array!(std.algorithm.iteration.splitter!string.Result)(std.algorithm.iteration.splitter!string.Result r) pure @safe

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.

@paramr range (or aggregate with opApply function) whose elements are copied into the allocated array@returnsallocated and initialized array
array
;
(alias) object.size_t = ulong
size_t
(local variable) ulong first
first
;
if (
(local variable) string[] pieces
pieces
[0].
bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safe

Checks whether the given input range starts with (one of) the given needle(s) or, if no needles are given, if its front element fulfils predicate pred.

For more information about pred see find.

@parampred Predicate to use in comparing the elements of the haystack and the needle(s). Mandatory if no needles are given.@paramdoesThisStart The input range to check.@paramwithOneOfThese The needles against which the range is to be checked, which may be individual elements or input ranges of elements.@paramwithThis The single needle to check, which may be either a single element or an input range of elements.@returns

0 if the needle(s) do not occur at the beginning of the given range; otherwise the position of the matching needle, that is, 1 if the range starts with withOneOfThese[0], 2 if it starts with withOneOfThese[1], and so on.

In the case where doesThisStart starts with multiple of the ranges or elements in withOneOfThese, then the shortest one matches (if there are two which match which are of the same length (e.g. "a" and 'a'), then the left-most of them in the argument list matches).

In the case when no needle parameters are given, return true iff front of doesThisStart fulfils predicate pred.

startsWith
("<"))
{
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
.
(field) bool sparkles.base.tools.gen_unicode_tables.UcdRecord.compatibility
compatibility
= true;
(local variable) ulong first
first
= 1;
} foreach (
(parameter) string piece
piece
;
(local variable) string[] pieces
pieces
[
(local variable) ulong first
first
.. $])
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.UcdRecord.decomposition
decomposition
~=
uint sparkles.base.tools.gen_unicode_tables.parseHex(string text)
parseHex
(
(local variable) string piece
piece
);
} if (
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.UcdRecord.decomposition
decomposition
.
(field) ulong uint[].length
length
)
sparkles.base.tools.gen_unicode_tables.UcdRecord* core.internal.newaa._d_aaGetY!(uint, sparkles.base.tools.gen_unicode_tables.UcdRecord, sparkles.base.tools.gen_unicode_tables.UcdRecord[uint], uint, sparkles.base.tools.gen_unicode_tables.UcdRecord, const(uint))(ref scope sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] aa, ref const(uint) key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
records
[
sparkles.base.tools.gen_unicode_tables.UcdRecord* core.internal.newaa._d_aaGetY!(uint, sparkles.base.tools.gen_unicode_tables.UcdRecord, sparkles.base.tools.gen_unicode_tables.UcdRecord[uint], uint, sparkles.base.tools.gen_unicode_tables.UcdRecord, const(uint))(ref scope sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] aa, ref const(uint) key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
cp
] =
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
;
} uint[][uint]
(local variable) uint[][uint] canonicalMemo
canonicalMemo
;
uint[][uint]
(local variable) uint[][uint] compatibilityMemo
compatibilityMemo
;
foreach (
int core.internal.newaa._d_aaApply2!(uint, sparkles.base.tools.gen_unicode_tables.UcdRecord, int delegate(ref uint, ref sparkles.base.tools.gen_unicode_tables.UcdRecord) @system)(inout(sparkles.base.tools.gen_unicode_tables.UcdRecord[uint]) a, int delegate(ref uint, ref sparkles.base.tools.gen_unicode_tables.UcdRecord) @system dg) @system

foreach opApply over all key/value pairs

Note

emulated by the compiler during CTFE

cp
,
(parameter) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
;
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records
records
)
{ auto
(local variable) uint[] canonical
canonical
=
uint[] sparkles.base.tools.gen_unicode_tables.expandDecomposition(uint cp, bool compatibility, ref sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records, ref uint[][uint] memo)
expandDecomposition
(
(local variable) uint cp
cp
, false,
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records
records
,
(local variable) uint[][uint] canonicalMemo
canonicalMemo
);
if (
(local variable) uint[] canonical
canonical
.
(field) ulong uint[].length
length
!= 1 ||
(local variable) uint[] canonical
canonical
[0] !=
(local variable) uint cp
cp
)
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.canonical
canonical
~=
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
(
(local variable) uint cp
cp
,
(local variable) uint[] canonical
canonical
);
auto
(local variable) uint[] compatibility
compatibility
=
uint[] sparkles.base.tools.gen_unicode_tables.expandDecomposition(uint cp, bool compatibility, ref sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records, ref uint[][uint] memo)
expandDecomposition
(
(local variable) uint cp
cp
, true,
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records
records
,
(local variable) uint[][uint] compatibilityMemo
compatibilityMemo
);
if (
(local variable) uint[] compatibility
compatibility
.
(field) ulong uint[].length
length
!= 1 ||
(local variable) uint[] compatibility
compatibility
[0] !=
(local variable) uint cp
cp
)
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.compatibility
compatibility
~=
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
(
(local variable) uint cp
cp
,
(local variable) uint[] compatibility
compatibility
);
}
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.canonical
canonical
.
sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.SortedRange!(SequenceMapping[], __lambda_L334_C28, SortedRangeOptions.assumeSorted) sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.sort!((a, b) => a.codepoint < b.codepoint, SwapStrategy.unstable, sparkles.base.tools.gen_unicode_tables.SequenceMapping[])(sparkles.base.tools.gen_unicode_tables.SequenceMapping[] r) pure nothrow @nogc @safe

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.

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));
@paramless The predicate to sort by.@paramss The swapping strategy to use.@paramr The range to sort.@returnsThe initial range wrapped as a SortedRange with the predicate binaryFun!less.@see

assumeSorted

SortedRange

SwapStrategy

binaryFun

sort
!((a, b) => a.codepoint < b.codepoint);
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.compatibility
compatibility
.
sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.SortedRange!(SequenceMapping[], __lambda_L335_C32, SortedRangeOptions.assumeSorted) sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.sort!((a, b) => a.codepoint < b.codepoint, SwapStrategy.unstable, sparkles.base.tools.gen_unicode_tables.SequenceMapping[])(sparkles.base.tools.gen_unicode_tables.SequenceMapping[] r) pure nothrow @nogc @safe

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.

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));
@paramless The predicate to sort by.@paramss The swapping strategy to use.@paramr The range to sort.@returnsThe initial range wrapped as a SortedRange with the predicate binaryFun!less.@see

assumeSorted

SortedRange

SwapStrategy

binaryFun

sort
!((a, b) => a.codepoint < b.codepoint);
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.ScalarMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.canonicalClasses
canonicalClasses
.
sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.SortedRange!(ScalarMapping[], __lambda_L336_C35, SortedRangeOptions.assumeSorted) sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.sort!((a, b) => a.codepoint < b.codepoint, SwapStrategy.unstable, sparkles.base.tools.gen_unicode_tables.ScalarMapping[])(sparkles.base.tools.gen_unicode_tables.ScalarMapping[] r) pure nothrow @nogc @safe

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.

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));
@paramless The predicate to sort by.@paramss The swapping strategy to use.@paramr The range to sort.@returnsThe initial range wrapped as a SortedRange with the predicate binaryFun!less.@see

assumeSorted

SortedRange

SwapStrategy

binaryFun

sort
!((a, b) => a.codepoint < b.codepoint);
auto
(local variable) std.uni.InversionList!(GcPolicy) exclusions
exclusions
=
(parameter) string normalizationProps
normalizationProps
.
std.uni.InversionList!(GcPolicy) sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.ucdCodepoints!((value) => value == "Full_Composition_Exclusion")(string text) @system

Collect, into a CodepointSet, the leading code-point column of every data record whose value field (the column after the first ;) satisfies valueMatches. For each record: strip the trailing # comment, split on ; into whitespace-trimmed fields (comment-only and blank lines collapse to one empty field and are dropped), take the first whitespace-separated token of the code-point column, and read it as a ..-separated hex sequence — so a bare AAAA adds one code point, AAAA..BBBB adds the inclusive range, and the BASE VS form (e.g. 0023 FE0F) adds just BASE.

ucdCodepoints
!(
value => value == "Full_Composition_Exclusion"); foreach (
int core.internal.newaa._d_aaApply2!(uint, sparkles.base.tools.gen_unicode_tables.UcdRecord, int delegate(ref uint, ref sparkles.base.tools.gen_unicode_tables.UcdRecord) pure nothrow @safe)(inout(sparkles.base.tools.gen_unicode_tables.UcdRecord[uint]) a, int delegate(ref uint, ref sparkles.base.tools.gen_unicode_tables.UcdRecord) pure nothrow @safe dg) pure nothrow @safe

foreach opApply over all key/value pairs

Note

emulated by the compiler during CTFE

cp
,
(parameter) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
;
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records
records
)
{ if (!
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
.
(field) bool sparkles.base.tools.gen_unicode_tables.UcdRecord.compatibility
compatibility
&&
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.UcdRecord.decomposition
decomposition
.
(field) ulong uint[].length
length
== 2
&& !(
(local variable) uint cp
cp
in
(local variable) std.uni.InversionList!(GcPolicy) exclusions
exclusions
))
{
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.CompositionMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.compositions
compositions
~=
(struct) sparkles.base.tools.gen_unicode_tables.CompositionMapping
CompositionMapping
(
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.UcdRecord.decomposition
decomposition
[0],
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord rec
rec
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.UcdRecord.decomposition
decomposition
[1],
(local variable) uint cp
cp
);
} }
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.CompositionMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.compositions
compositions
.
sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.SortedRange!(CompositionMapping[], __lambda_L349_C31, SortedRangeOptions.assumeSorted) sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.sort!((a, b) { return a.first != b.first ? a.first < b.first : a.second < b.second; } , SwapStrategy.unstable, sparkles.base.tools.gen_unicode_tables.CompositionMapping[])(sparkles.base.tools.gen_unicode_tables.CompositionMapping[] r) pure nothrow @nogc @safe

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.

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));
@paramless The predicate to sort by.@paramss The swapping strategy to use.@paramr The range to sort.@returnsThe initial range wrapped as a SortedRange with the predicate binaryFun!less.@see

assumeSorted

SortedRange

SwapStrategy

binaryFun

sort
!((a, b) {
return a.first != b.first ? a.first < b.first : a.second < b.second; });
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
[uint]
(local variable) sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] simple
simple
;
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
[uint]
(local variable) sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] full
full
;
foreach (
(local variable) string rawLine
rawLine
;
(parameter) string caseFolding
caseFolding
.
std.string.LineSplitter!(Flag.no, string) std.string.lineSplitter!(Flag.no, immutable(char))(string r) pure nothrow @nogc @safe

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.

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);
@paramr array of chars, wchars, or dchars or a slicable range@paramkeepTerm whether delimiter is included or not in the results@returnsrange of slices of the input range r@seesplitLines splitter splitter
lineSplitter
)
{ auto
(local variable) string line
line
=
string sparkles.base.tools.gen_unicode_tables.stripComment(string line)

Strip a trailing # comment and surrounding whitespace from a UCD line. findSplit("#")[0] is the text before the first #, or the whole line when there is none.

stripComment
(
(local variable) string rawLine
rawLine
);
if (!
(local variable) string line
line
.
(field) ulong string.length
length
)
continue; auto
(local variable) string[] fields
fields
=
(local variable) string line
line
.
std.algorithm.iteration.splitter!("a == b", Flag.no, string, char).Result std.algorithm.iteration.splitter!("a == b", Flag.no, string, char)(string r, char s) pure nothrow @nogc @safe

Lazily splits a range using an element or range as a separator. Separator ranges can be any narrow string type or sliceable range type.

Two adjacent separators are considered to surround an empty element in the split range. Use filter!(a => !a.empty) on the result to compress empty elements.

The predicate is passed to binaryFun and accepts any callable function that can be executed via pred(element, s).

Note

If splitting a string on whitespace and token compression is desired, consider using the ``splitter(r) overload.

Constraints

The predicate pred needs to accept an element of r and the separator s.

Examples

Basic splitting with characters and numbers.

import std.algorithm.comparison : equal;

assert("a|bc|def".splitter('|').equal([ "a", "bc", "def" ]));

int[] a = [1, 0, 2, 3, 0, 4, 5, 6];
int[][] w = [ [1], [2, 3], [4, 5, 6] ];
assert(a.splitter(0).equal(w));

Basic splitting with characters and numbers and keeping sentinels.

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("a|bc|def".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "a", "|", "bc", "|", "def" ]));

int[] a = [1, 0, 2, 3, 0, 4, 5, 6];
int[][] w = [ [1], [0], [2, 3], [0], [4, 5, 6] ];
assert(a.splitter!("a == b", Yes.keepSeparators)(0).equal(w));

Adjacent separators.

import std.algorithm.comparison : equal;

assert("|ab|".splitter('|').equal([ "", "ab", "" ]));
assert("ab".splitter('|').equal([ "ab" ]));

assert("a|b||c".splitter('|').equal([ "a", "b", "", "c" ]));
assert("hello  world".splitter(' ').equal([ "hello", "", "world" ]));

auto a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
auto w = [ [1, 2], [], [3], [4, 5], [] ];
assert(a.splitter(0).equal(w));

Adjacent separators and keeping sentinels.

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("|ab|".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "ab", "|", "" ]));
assert("ab".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "ab" ]));

assert("a|b||c".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "a", "|", "b", "|", "", "|", "c" ]));
assert("hello  world".splitter!("a == b", Yes.keepSeparators)(' ')
    .equal([ "hello", " ", "", " ", "world" ]));

auto a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
auto w = [ [1, 2], [0], [], [0], [3], [0], [4, 5], [0], [] ];
assert(a.splitter!("a == b", Yes.keepSeparators)(0).equal(w));

Empty and separator-only ranges.

import std.algorithm.comparison : equal;
import std.range : empty;

assert("".splitter('|').empty);
assert("|".splitter('|').equal([ "", "" ]));
assert("||".splitter('|').equal([ "", "", "" ]));

Empty and separator-only ranges and keeping sentinels.

import std.algorithm.comparison : equal;
import std.typecons : Yes;
import std.range : empty;

assert("".splitter!("a == b", Yes.keepSeparators)('|').empty);
assert("|".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "" ]));
assert("||".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "", "|", "" ]));

Use a range for splitting

import std.algorithm.comparison : equal;

assert("a=>bc=>def".splitter("=>").equal([ "a", "bc", "def" ]));
assert("a|b||c".splitter("||").equal([ "a|b", "c" ]));
assert("hello  world".splitter("  ").equal([ "hello", "world" ]));

int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
int[][] w = [ [1, 2], [3, 0, 4, 5, 0] ];
assert(a.splitter([0, 0]).equal(w));

a = [ 0, 0 ];
assert(a.splitter([0, 0]).equal([ (int[]).init, (int[]).init ]));

a = [ 0, 0, 1 ];
assert(a.splitter([0, 0]).equal([ [], [1] ]));

Use a range for splitting

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("a=>bc=>def".splitter!("a == b", Yes.keepSeparators)("=>")
    .equal([ "a", "=>", "bc", "=>", "def" ]));
assert("a|b||c".splitter!("a == b", Yes.keepSeparators)("||")
    .equal([ "a|b", "||", "c" ]));
assert("hello  world".splitter!("a == b", Yes.keepSeparators)("  ")
    .equal([ "hello", "  ",  "world" ]));

int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
int[][] w = [ [1, 2], [0, 0], [3, 0, 4, 5, 0] ];
assert(a.splitter!("a == b", Yes.keepSeparators)([0, 0]).equal(w));

a = [ 0, 0 ];
assert(a.splitter!("a == b", Yes.keepSeparators)([0, 0])
    .equal([ (int[]).init, [0, 0], (int[]).init ]));

a = [ 0, 0, 1 ];
assert(a.splitter!("a == b", Yes.keepSeparators)([0, 0])
    .equal([ [], [0, 0], [1] ]));

Custom predicate functions.

import std.algorithm.comparison : equal;
import std.ascii : toLower;

assert("abXcdxef".splitter!"a.toLower == b"('x').equal(
             [ "ab", "cd", "ef" ]));

auto w = [ [0], [1], [2] ];
assert(w.splitter!"a.front == b"(1).equal([ [[0]], [[2]] ]));

Custom predicate functions.

import std.algorithm.comparison : equal;
import std.typecons : Yes;
import std.ascii : toLower;

assert("abXcdxef".splitter!("a.toLower == b", Yes.keepSeparators)('x')
    .equal([ "ab", "X", "cd", "x", "ef" ]));

auto w = [ [0], [1], [2] ];
assert(w.splitter!("a.front == b", Yes.keepSeparators)(1)
    .equal([ [[0]], [[1]], [[2]] ]));

Leading separators, trailing separators, or no separators.

import std.algorithm.comparison : equal;

assert("|ab|".splitter('|').equal([ "", "ab", "" ]));
assert("ab".splitter('|').equal([ "ab" ]));

Leading separators, trailing separators, or no separators.

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("|ab|".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "ab", "|", "" ]));
assert("ab".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "ab" ]));

Splitter returns bidirectional ranges if the delimiter is a single element

import std.algorithm.comparison : equal;
import std.range : retro;
assert("a|bc|def".splitter('|').retro.equal([ "def", "bc", "a" ]));

Splitter returns bidirectional ranges if the delimiter is a single element

import std.algorithm.comparison : equal;
import std.typecons : Yes;
import std.range : retro;
assert("a|bc|def".splitter!("a == b", Yes.keepSeparators)('|')
    .retro.equal([ "def", "|", "bc", "|", "a" ]));
@parampred The predicate for comparing each element with the separator, defaulting to "a == b".@paramr The input range to be split. Must support slicing and .length or be a narrow string type.@params The element (or range) to be treated as the separator between range segments to be split.@paramkeepSeparators The flag for deciding if the separators are kept@returns

An input range of the subranges of elements between separators. If r is a forward range or bidirectional range, the returned range will be likewise. When a range is used a separator, bidirectionality isn't possible.

If keepSeparators is equal to Yes.keepSeparators the output will also contain the separators.

If an empty range is given, the result is an empty range. If a range with one separator is given, the result is a range with two empty elements.

@see
  • splitter for a version that splits using a regular expression defined separator.

  • split for a version that splits eagerly.

  • splitWhen, which compares adjacent elements instead of element against separator.

splitter
(';').
std.algorithm.iteration.MapResult!(strip, Result) std.algorithm.iteration.map!(strip).map!(std.algorithm.iteration.splitter!("a == b", Flag.no, string, char).Result)(std.algorithm.iteration.splitter!("a == b", Flag.no, string, char).Result r) pure nothrow @nogc @safe

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.

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" ]));
@paramfun one or more transformation functions@seeMap (higher-order function)@paramr an input range@returnsA range with each fun applied to all the elements. If there is more than one fun, the element type will be Tuple containing one element for each fun.
map
!
(template) 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.

Examples

import std.uni : lineSep, paraSep;
assert(strip("     hello world     ") ==
       "hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
       "hello world");
assert(strip("hello world") ==
       "hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
       "hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
       "hello world");
@paramstr string or random access range of characters@paramchars string of characters to be stripped@paramleftChars string of leading characters to be stripped@paramrightChars string of trailing characters to be stripped@returnsslice of str stripped of leading and trailing whitespace or characters as specified in the second argument.@seeGeneric stripping on ranges: strip
strip
.
string[] std.array.array!(std.algorithm.iteration.MapResult!(strip, Result))(std.algorithm.iteration.MapResult!(strip, Result) r) pure @safe

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.

@paramr range (or aggregate with opApply function) whose elements are copied into the allocated array@returnsallocated and initialized array
array
;
if (
(local variable) string[] fields
fields
.
(field) ulong string[].length
length
< 3)
continue; const
(local variable) const(uint) cp
cp
=
uint sparkles.base.tools.gen_unicode_tables.parseHex(string text)
parseHex
(
(local variable) string[] fields
fields
[0]);
uint[]
(local variable) uint[] values
values
;
foreach (
(local variable) string piece
piece
;
(local variable) string[] fields
fields
[2].
std.algorithm.iteration.splitter!string.Result std.algorithm.iteration.splitter!string(string s) pure @safe

Lazily splits the character-based range s into words, using whitespace as the delimiter.

This function is character-range specific and, contrary to ``splitter!(std.uni.isWhite), runs of whitespace will be merged together (no empty tokens will be produced).

Examples

import std.algorithm.comparison : equal;
auto a = " a     bcd   ef gh ";
assert(equal(splitter(a), ["a", "bcd", "ef", "gh"][]));
@params The character-based range to be split. Must be a string, or a random-access range of character types.@returnsAn input range of slices of the original range split by whitespace.
splitter
)
(local variable) uint[] values
values
~=
uint sparkles.base.tools.gen_unicode_tables.parseHex(string text)
parseHex
(
(local variable) string piece
piece
);
switch (
(local variable) string[] fields
fields
[1])
{ case "C":
sparkles.base.tools.gen_unicode_tables.SequenceMapping* core.internal.newaa._d_aaGetY!(uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint], uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, const(uint))(ref scope sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] aa, ref const(uint) key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
simple
[
sparkles.base.tools.gen_unicode_tables.SequenceMapping* core.internal.newaa._d_aaGetY!(uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint], uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, const(uint))(ref scope sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] aa, ref const(uint) key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
cp
] =
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
(
(local variable) const(uint) cp
cp
,
(local variable) uint[] values
values
);
sparkles.base.tools.gen_unicode_tables.SequenceMapping* core.internal.newaa._d_aaGetY!(uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint], uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, const(uint))(ref scope sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] aa, ref const(uint) key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
full
[
sparkles.base.tools.gen_unicode_tables.SequenceMapping* core.internal.newaa._d_aaGetY!(uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint], uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, const(uint))(ref scope sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] aa, ref const(uint) key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
cp
] =
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
(
(local variable) const(uint) cp
cp
,
(local variable) uint[] values
values
);
break; case "S":
sparkles.base.tools.gen_unicode_tables.SequenceMapping* core.internal.newaa._d_aaGetY!(uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint], uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, const(uint))(ref scope sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] aa, ref const(uint) key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
simple
[
sparkles.base.tools.gen_unicode_tables.SequenceMapping* core.internal.newaa._d_aaGetY!(uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint], uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, const(uint))(ref scope sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] aa, ref const(uint) key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
cp
] =
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
(
(local variable) const(uint) cp
cp
,
(local variable) uint[] values
values
);
break; case "F":
sparkles.base.tools.gen_unicode_tables.SequenceMapping* core.internal.newaa._d_aaGetY!(uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint], uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, const(uint))(ref scope sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] aa, ref const(uint) key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
full
[
sparkles.base.tools.gen_unicode_tables.SequenceMapping* core.internal.newaa._d_aaGetY!(uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint], uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, const(uint))(ref scope sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] aa, ref const(uint) key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
cp
] =
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
(
(local variable) const(uint) cp
cp
,
(local variable) uint[] values
values
);
break; default: // Turkic mappings are locale-specific and live in an adapter. break; } } foreach (
int core.internal.newaa._d_aaApply2!(uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, int delegate(ref uint, ref sparkles.base.tools.gen_unicode_tables.SequenceMapping) pure nothrow @safe)(inout(sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint]) a, int delegate(ref uint, ref sparkles.base.tools.gen_unicode_tables.SequenceMapping) pure nothrow @safe dg) pure nothrow @safe

foreach opApply over all key/value pairs

Note

emulated by the compiler during CTFE

cp
,
(parameter) sparkles.base.tools.gen_unicode_tables.SequenceMapping mapping
mapping
;
(local variable) sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] simple
simple
)
{ if (
(local variable) sparkles.base.tools.gen_unicode_tables.SequenceMapping mapping
mapping
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.SequenceMapping.values
values
.
(field) ulong uint[].length
length
== 1 &&
(local variable) sparkles.base.tools.gen_unicode_tables.SequenceMapping mapping
mapping
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.SequenceMapping.values
values
[0] !=
(local variable) uint cp
cp
)
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.ScalarMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.simpleFold
simpleFold
~=
(struct) sparkles.base.tools.gen_unicode_tables.ScalarMapping
ScalarMapping
(
(local variable) uint cp
cp
,
(local variable) sparkles.base.tools.gen_unicode_tables.SequenceMapping mapping
mapping
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.SequenceMapping.values
values
[0]);
} foreach (
int core.internal.newaa._d_aaApply2!(uint, sparkles.base.tools.gen_unicode_tables.SequenceMapping, int delegate(ref uint, ref sparkles.base.tools.gen_unicode_tables.SequenceMapping) pure nothrow @safe)(inout(sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint]) a, int delegate(ref uint, ref sparkles.base.tools.gen_unicode_tables.SequenceMapping) pure nothrow @safe dg) pure nothrow @safe

foreach opApply over all key/value pairs

Note

emulated by the compiler during CTFE

cp
,
(parameter) sparkles.base.tools.gen_unicode_tables.SequenceMapping mapping
mapping
;
(local variable) sparkles.base.tools.gen_unicode_tables.SequenceMapping[uint] full
full
)
{ if (
(local variable) sparkles.base.tools.gen_unicode_tables.SequenceMapping mapping
mapping
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.SequenceMapping.values
values
.
(field) ulong uint[].length
length
!= 1 ||
(local variable) sparkles.base.tools.gen_unicode_tables.SequenceMapping mapping
mapping
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.SequenceMapping.values
values
[0] !=
(local variable) uint cp
cp
)
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.fullFold
fullFold
~=
(local variable) sparkles.base.tools.gen_unicode_tables.SequenceMapping mapping
mapping
;
}
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.ScalarMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.simpleFold
simpleFold
.
sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.SortedRange!(ScalarMapping[], __lambda_L393_C29, SortedRangeOptions.assumeSorted) sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.sort!((a, b) => a.codepoint < b.codepoint, SwapStrategy.unstable, sparkles.base.tools.gen_unicode_tables.ScalarMapping[])(sparkles.base.tools.gen_unicode_tables.ScalarMapping[] r) pure nothrow @nogc @safe

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.

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));
@paramless The predicate to sort by.@paramss The swapping strategy to use.@paramr The range to sort.@returnsThe initial range wrapped as a SortedRange with the predicate binaryFun!less.@see

assumeSorted

SortedRange

SwapStrategy

binaryFun

sort
!((a, b) => a.codepoint < b.codepoint);
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.SequenceMapping[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.fullFold
fullFold
.
sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.SortedRange!(SequenceMapping[], __lambda_L394_C27, SortedRangeOptions.assumeSorted) sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.sort!((a, b) => a.codepoint < b.codepoint, SwapStrategy.unstable, sparkles.base.tools.gen_unicode_tables.SequenceMapping[])(sparkles.base.tools.gen_unicode_tables.SequenceMapping[] r) pure nothrow @nogc @safe

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.

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));
@paramless The predicate to sort by.@paramss The swapping strategy to use.@paramr The range to sort.@returnsThe initial range wrapped as a SortedRange with the predicate binaryFun!less.@see

assumeSorted

SortedRange

SwapStrategy

binaryFun

sort
!((a, b) => a.codepoint < b.codepoint);
foreach (
(local variable) string rawLine
rawLine
;
(parameter) string wordBreak
wordBreak
.
std.string.LineSplitter!(Flag.no, string) std.string.lineSplitter!(Flag.no, immutable(char))(string r) pure nothrow @nogc @safe

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.

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);
@paramr array of chars, wchars, or dchars or a slicable range@paramkeepTerm whether delimiter is included or not in the results@returnsrange of slices of the input range r@seesplitLines splitter splitter
lineSplitter
)
{ auto
(local variable) string line
line
=
string sparkles.base.tools.gen_unicode_tables.stripComment(string line)

Strip a trailing # comment and surrounding whitespace from a UCD line. findSplit("#")[0] is the text before the first #, or the whole line when there is none.

stripComment
(
(local variable) string rawLine
rawLine
);
if (!
(local variable) string line
line
.
(field) ulong string.length
length
)
continue; auto
(local variable) string[] fields
fields
=
(local variable) string line
line
.
std.algorithm.iteration.splitter!("a == b", Flag.no, string, char).Result std.algorithm.iteration.splitter!("a == b", Flag.no, string, char)(string r, char s) pure nothrow @nogc @safe

Lazily splits a range using an element or range as a separator. Separator ranges can be any narrow string type or sliceable range type.

Two adjacent separators are considered to surround an empty element in the split range. Use filter!(a => !a.empty) on the result to compress empty elements.

The predicate is passed to binaryFun and accepts any callable function that can be executed via pred(element, s).

Note

If splitting a string on whitespace and token compression is desired, consider using the ``splitter(r) overload.

Constraints

The predicate pred needs to accept an element of r and the separator s.

Examples

Basic splitting with characters and numbers.

import std.algorithm.comparison : equal;

assert("a|bc|def".splitter('|').equal([ "a", "bc", "def" ]));

int[] a = [1, 0, 2, 3, 0, 4, 5, 6];
int[][] w = [ [1], [2, 3], [4, 5, 6] ];
assert(a.splitter(0).equal(w));

Basic splitting with characters and numbers and keeping sentinels.

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("a|bc|def".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "a", "|", "bc", "|", "def" ]));

int[] a = [1, 0, 2, 3, 0, 4, 5, 6];
int[][] w = [ [1], [0], [2, 3], [0], [4, 5, 6] ];
assert(a.splitter!("a == b", Yes.keepSeparators)(0).equal(w));

Adjacent separators.

import std.algorithm.comparison : equal;

assert("|ab|".splitter('|').equal([ "", "ab", "" ]));
assert("ab".splitter('|').equal([ "ab" ]));

assert("a|b||c".splitter('|').equal([ "a", "b", "", "c" ]));
assert("hello  world".splitter(' ').equal([ "hello", "", "world" ]));

auto a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
auto w = [ [1, 2], [], [3], [4, 5], [] ];
assert(a.splitter(0).equal(w));

Adjacent separators and keeping sentinels.

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("|ab|".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "ab", "|", "" ]));
assert("ab".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "ab" ]));

assert("a|b||c".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "a", "|", "b", "|", "", "|", "c" ]));
assert("hello  world".splitter!("a == b", Yes.keepSeparators)(' ')
    .equal([ "hello", " ", "", " ", "world" ]));

auto a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
auto w = [ [1, 2], [0], [], [0], [3], [0], [4, 5], [0], [] ];
assert(a.splitter!("a == b", Yes.keepSeparators)(0).equal(w));

Empty and separator-only ranges.

import std.algorithm.comparison : equal;
import std.range : empty;

assert("".splitter('|').empty);
assert("|".splitter('|').equal([ "", "" ]));
assert("||".splitter('|').equal([ "", "", "" ]));

Empty and separator-only ranges and keeping sentinels.

import std.algorithm.comparison : equal;
import std.typecons : Yes;
import std.range : empty;

assert("".splitter!("a == b", Yes.keepSeparators)('|').empty);
assert("|".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "" ]));
assert("||".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "", "|", "" ]));

Use a range for splitting

import std.algorithm.comparison : equal;

assert("a=>bc=>def".splitter("=>").equal([ "a", "bc", "def" ]));
assert("a|b||c".splitter("||").equal([ "a|b", "c" ]));
assert("hello  world".splitter("  ").equal([ "hello", "world" ]));

int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
int[][] w = [ [1, 2], [3, 0, 4, 5, 0] ];
assert(a.splitter([0, 0]).equal(w));

a = [ 0, 0 ];
assert(a.splitter([0, 0]).equal([ (int[]).init, (int[]).init ]));

a = [ 0, 0, 1 ];
assert(a.splitter([0, 0]).equal([ [], [1] ]));

Use a range for splitting

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("a=>bc=>def".splitter!("a == b", Yes.keepSeparators)("=>")
    .equal([ "a", "=>", "bc", "=>", "def" ]));
assert("a|b||c".splitter!("a == b", Yes.keepSeparators)("||")
    .equal([ "a|b", "||", "c" ]));
assert("hello  world".splitter!("a == b", Yes.keepSeparators)("  ")
    .equal([ "hello", "  ",  "world" ]));

int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
int[][] w = [ [1, 2], [0, 0], [3, 0, 4, 5, 0] ];
assert(a.splitter!("a == b", Yes.keepSeparators)([0, 0]).equal(w));

a = [ 0, 0 ];
assert(a.splitter!("a == b", Yes.keepSeparators)([0, 0])
    .equal([ (int[]).init, [0, 0], (int[]).init ]));

a = [ 0, 0, 1 ];
assert(a.splitter!("a == b", Yes.keepSeparators)([0, 0])
    .equal([ [], [0, 0], [1] ]));

Custom predicate functions.

import std.algorithm.comparison : equal;
import std.ascii : toLower;

assert("abXcdxef".splitter!"a.toLower == b"('x').equal(
             [ "ab", "cd", "ef" ]));

auto w = [ [0], [1], [2] ];
assert(w.splitter!"a.front == b"(1).equal([ [[0]], [[2]] ]));

Custom predicate functions.

import std.algorithm.comparison : equal;
import std.typecons : Yes;
import std.ascii : toLower;

assert("abXcdxef".splitter!("a.toLower == b", Yes.keepSeparators)('x')
    .equal([ "ab", "X", "cd", "x", "ef" ]));

auto w = [ [0], [1], [2] ];
assert(w.splitter!("a.front == b", Yes.keepSeparators)(1)
    .equal([ [[0]], [[1]], [[2]] ]));

Leading separators, trailing separators, or no separators.

import std.algorithm.comparison : equal;

assert("|ab|".splitter('|').equal([ "", "ab", "" ]));
assert("ab".splitter('|').equal([ "ab" ]));

Leading separators, trailing separators, or no separators.

import std.algorithm.comparison : equal;
import std.typecons : Yes;

assert("|ab|".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "", "|", "ab", "|", "" ]));
assert("ab".splitter!("a == b", Yes.keepSeparators)('|')
    .equal([ "ab" ]));

Splitter returns bidirectional ranges if the delimiter is a single element

import std.algorithm.comparison : equal;
import std.range : retro;
assert("a|bc|def".splitter('|').retro.equal([ "def", "bc", "a" ]));

Splitter returns bidirectional ranges if the delimiter is a single element

import std.algorithm.comparison : equal;
import std.typecons : Yes;
import std.range : retro;
assert("a|bc|def".splitter!("a == b", Yes.keepSeparators)('|')
    .retro.equal([ "def", "|", "bc", "|", "a" ]));
@parampred The predicate for comparing each element with the separator, defaulting to "a == b".@paramr The input range to be split. Must support slicing and .length or be a narrow string type.@params The element (or range) to be treated as the separator between range segments to be split.@paramkeepSeparators The flag for deciding if the separators are kept@returns

An input range of the subranges of elements between separators. If r is a forward range or bidirectional range, the returned range will be likewise. When a range is used a separator, bidirectionality isn't possible.

If keepSeparators is equal to Yes.keepSeparators the output will also contain the separators.

If an empty range is given, the result is an empty range. If a range with one separator is given, the result is a range with two empty elements.

@see
  • splitter for a version that splits using a regular expression defined separator.

  • split for a version that splits eagerly.

  • splitWhen, which compares adjacent elements instead of element against separator.

splitter
(';').
std.algorithm.iteration.MapResult!(strip, Result) std.algorithm.iteration.map!(strip).map!(std.algorithm.iteration.splitter!("a == b", Flag.no, string, char).Result)(std.algorithm.iteration.splitter!("a == b", Flag.no, string, char).Result r) pure nothrow @nogc @safe

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.

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" ]));
@paramfun one or more transformation functions@seeMap (higher-order function)@paramr an input range@returnsA range with each fun applied to all the elements. If there is more than one fun, the element type will be Tuple containing one element for each fun.
map
!
(template) 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.

Examples

import std.uni : lineSep, paraSep;
assert(strip("     hello world     ") ==
       "hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
       "hello world");
assert(strip("hello world") ==
       "hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
       "hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
       "hello world");
@paramstr string or random access range of characters@paramchars string of characters to be stripped@paramleftChars string of leading characters to be stripped@paramrightChars string of trailing characters to be stripped@returnsslice of str stripped of leading and trailing whitespace or characters as specified in the second argument.@seeGeneric stripping on ranges: strip
strip
.
string[] std.array.array!(std.algorithm.iteration.MapResult!(strip, Result))(std.algorithm.iteration.MapResult!(strip, Result) r) pure @safe

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.

@paramr range (or aggregate with opApply function) whose elements are copied into the allocated array@returnsallocated and initialized array
array
;
if (
(local variable) string[] fields
fields
.
(field) ulong string[].length
length
< 2)
continue; auto
(local variable) string[] bounds
bounds
=
(local variable) string[] fields
fields
[0].
std.algorithm.iteration.splitter!("a == b", Flag.no, string, string).Result std.algorithm.iteration.splitter!("a == b", Flag.no, string, string)(string r, string s) pure nothrow @nogc @safe

Splitter returns bidirectional ranges if the delimiter is a single element

splitter
("..").
string[] std.array.array!(std.algorithm.iteration.splitter!("a == b", Flag.no, string, string).Result)(std.algorithm.iteration.splitter!("a == b", Flag.no, string, string).Result r) pure nothrow @safe

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.

@paramr range (or aggregate with opApply function) whose elements are copied into the allocated array@returnsallocated and initialized array
array
;
const
(local variable) const(uint) first
first
=
uint sparkles.base.tools.gen_unicode_tables.parseHex(string text)
parseHex
(
(local variable) string[] bounds
bounds
[0]);
const
(local variable) const(uint) last
last
=
(local variable) string[] bounds
bounds
.
(field) ulong string[].length
length
== 2 ?
uint sparkles.base.tools.gen_unicode_tables.parseHex(string text)
parseHex
(
(local variable) string[] bounds
bounds
[1]) :
(local variable) const(uint) first
first
;
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.WordBreakRange[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.wordBreak
wordBreak
~=
(struct) sparkles.base.tools.gen_unicode_tables.WordBreakRange
WordBreakRange
(
(local variable) const(uint) first
first
,
(local variable) const(uint) last
last
,
(local variable) string[] fields
fields
[1]);
}
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
.
(field) sparkles.base.tools.gen_unicode_tables.WordBreakRange[] sparkles.base.tools.gen_unicode_tables.AnalysisTables.wordBreak
wordBreak
.
sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.SortedRange!(WordBreakRange[], __lambda_L409_C28, SortedRangeOptions.assumeSorted) sparkles.base.tools.gen_unicode_tables.buildAnalysisTables.sort!((a, b) => a.first < b.first, SwapStrategy.unstable, sparkles.base.tools.gen_unicode_tables.WordBreakRange[])(sparkles.base.tools.gen_unicode_tables.WordBreakRange[] r) pure nothrow @nogc @safe

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.

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));
@paramless The predicate to sort by.@paramss The swapping strategy to use.@paramr The range to sort.@returnsThe initial range wrapped as a SortedRange with the predicate binaryFun!less.@see

assumeSorted

SortedRange

SwapStrategy

binaryFun

sort
!((a, b) => a.first < b.first);
return
(local variable) sparkles.base.tools.gen_unicode_tables.AnalysisTables result
result
;
} private uint[]
uint[] sparkles.base.tools.gen_unicode_tables.expandDecomposition(uint cp, bool compatibility, ref sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records, ref uint[][uint] memo)
expandDecomposition
(uint
(parameter) uint cp
cp
, bool
(parameter) bool compatibility
compatibility
,
ref
(struct) sparkles.base.tools.gen_unicode_tables.UcdRecord
UcdRecord
[uint]
(parameter) sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records
records
, ref uint[][uint]
(parameter) uint[][uint] memo
memo
)
{ if (auto
(local variable) uint[]* cached
cached
=
(parameter) uint cp
cp
in
(parameter) uint[][uint] memo
memo
)
return *
(local variable) uint[]* cached
cached
;
auto
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord* record
record
=
(parameter) uint cp
cp
in
(parameter) sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records
records
;
if (
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord* record
record
is null || !
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord* record
record
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.UcdRecord.decomposition
decomposition
.
(field) ulong uint[].length
length
|| (!
(parameter) bool compatibility
compatibility
&&
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord* record
record
.
(field) bool sparkles.base.tools.gen_unicode_tables.UcdRecord.compatibility
compatibility
))
{ auto
(local variable) uint[] identity
identity
= [
(parameter) uint cp
cp
];
uint[]* core.internal.newaa._d_aaGetY!(uint, uint[], uint[][uint], uint, uint[], uint)(ref scope uint[][uint] aa, ref uint key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
memo
[
uint[]* core.internal.newaa._d_aaGetY!(uint, uint[], uint[][uint], uint, uint[], uint)(ref scope uint[][uint] aa, ref uint key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
cp
] =
(local variable) uint[] identity
identity
;
return
(local variable) uint[] identity
identity
;
} uint[]
(local variable) uint[] expanded
expanded
;
foreach (
(parameter) uint part
part
;
(local variable) sparkles.base.tools.gen_unicode_tables.UcdRecord* record
record
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.UcdRecord.decomposition
decomposition
)
(local variable) uint[] expanded
expanded
~=
uint[] sparkles.base.tools.gen_unicode_tables.expandDecomposition(uint cp, bool compatibility, ref sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records, ref uint[][uint] memo)
expandDecomposition
(
(local variable) uint part
part
,
(parameter) bool compatibility
compatibility
,
(parameter) sparkles.base.tools.gen_unicode_tables.UcdRecord[uint] records
records
,
(parameter) uint[][uint] memo
memo
);
uint[]* core.internal.newaa._d_aaGetY!(uint, uint[], uint[][uint], uint, uint[], uint)(ref scope uint[][uint] aa, ref uint key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
memo
[
uint[]* core.internal.newaa._d_aaGetY!(uint, uint[], uint[][uint], uint, uint[], uint)(ref scope uint[][uint] aa, ref uint key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
cp
] =
(local variable) uint[] expanded
expanded
;
return
(local variable) uint[] expanded
expanded
;
} private uint
uint sparkles.base.tools.gen_unicode_tables.parseHex(string text)
parseHex
(
(alias) object.string = string
string
(parameter) string text
text
)
{ uint
(local variable) uint value
value
;
(parameter) string text
text
.
uint std.format.read.formattedRead!("%x", string, uint)(ref string r, ref uint __param_1) pure @safe

Reads an input range according to a format string and stores the read values into its arguments.

Format specifiers with format character 'd', 'u' and 'c' can take a ''* parameter for skipping values.

The second version of formattedRead takes the format string as template argument. In this case, it is checked for consistency at compile-time.

Note

For backward compatibility the arguments args can be given as pointers to that variable, but it is not recommended to do so, because this option might be removed in the future.

Examples

string object;
char cmp;
int value;

assert(formattedRead("angle < 36", "%s %c %d", object, cmp, value) == 3);
assert(object == "angle");
assert(cmp == '<');
assert(value == 36);

// reading may end early:
assert(formattedRead("length >", "%s %c %d", object, cmp, value) == 2);
assert(object == "length");
assert(cmp == '>');
// value is not changed:
assert(value == 36);

The format string can be checked at compile-time:

string a;
int b;
double c;

assert("hello!124:34.5".formattedRead!"%s!%s:%s"(a, b, c) == 3);
assert(a == "hello");
assert(b == 124);
assert(c == 34.5);

Skipping values

string item;
double amount;

assert("orange: (12%) 15.25".formattedRead("%s: (%*d%%) %f", item, amount) == 2);
assert(item == "orange");
assert(amount == 15.25);

// can also be used with tuples
import std.typecons : Tuple;

Tuple!(int, float) t;
char[] line = "1 7643 2.125".dup;
formattedRead(line, "%s %*u %s", t);
assert(t[0] == 1 && t[1] == 2.125);
@paramr an input range, where the formatted input is read from@paramfmt a format string@paramargs a variadic list of arguments where the read values are stored@paramRange the type of the input range r@paramChar the character type used for fmt@paramArgs a variadic list of types of the arguments@returnsThe number of variables filled. If the input range r ends early, this number will be less than the number of variables provided.@throwsA FormatException if reading did not succeed.
formattedRead
!"%x"(
(local variable) uint value
value
);
return
(local variable) uint value
value
;
} private enum
(constant) string sparkles.base.tools.gen_unicode_tables.analysisTypesSource = "\n/// A borrowed span inside one of the generated flat Unicode mapping arrays.\nstruct UnicodeMappingSpan\n{\n uint offset;\n ubyte length;\n}\n\nprivate struct UnicodeSequenceIndex\n{\n uint codepoint;\n uint offset;\n ubyte length;\n}\n\nprivate struct UnicodeScalarIndex\n{\n uint codepoint;\n uint value;\n}\n\nprivate UnicodeMappingSpan findUnicodeSequence(scope const(UnicodeSequenceIndex)[] index,\n dchar ch) @safe pure nothrow @nogc\n{\n size_t lo;\n size_t hi = index.length;\n while (lo < hi)\n {\n const mid = lo + (hi - lo) / 2;\n if (index[mid].codepoint < ch)\n lo = mid + 1;\n else\n hi = mid;\n }\n return lo < index.length && index[lo].codepoint == ch\n ? UnicodeMappingSpan(index[lo].offset, index[lo].length)\n : UnicodeMappingSpan.init;\n}\n\nprivate dchar findUnicodeScalar(scope const(UnicodeScalarIndex)[] index,\n dchar ch) @safe pure nothrow @nogc\n{\n size_t lo;\n size_t hi = index.length;\n while (lo < hi)\n {\n const mid = lo + (hi - lo) / 2;\n if (index[mid].codepoint < ch)\n lo = mid + 1;\n else\n hi = mid;\n }\n return lo < index.length && index[lo].codepoint == ch\n ? cast(dchar) index[lo].value : ch;\n}\n\nprivate uint findUnicodeProperty(scope const(UnicodeScalarIndex)[] index,\n dchar ch) @safe pure nothrow @nogc\n{\n size_t lo;\n size_t hi = index.length;\n while (lo < hi)\n {\n const mid = lo + (hi - lo) / 2;\n if (index[mid].codepoint < ch)\n lo = mid + 1;\n else\n hi = mid;\n }\n return lo < index.length && index[lo].codepoint == ch\n ? index[lo].value : 0;\n}\n"
analysisTypesSource
= q{
/// A borrowed span inside one of the generated flat Unicode mapping arrays. struct UnicodeMappingSpan { uint offset; ubyte length; } private struct UnicodeSequenceIndex { uint codepoint; uint offset; ubyte length; } private struct UnicodeScalarIndex { uint codepoint; uint value; } private UnicodeMappingSpan findUnicodeSequence(scope const(UnicodeSequenceIndex)[] index, dchar ch) @safe pure nothrow @nogc { size_t lo; size_t hi = index.length; while (lo < hi) { const mid = lo + (hi - lo) / 2; if (index[mid].codepoint < ch) lo = mid + 1; else hi = mid; } return lo < index.length && index[lo].codepoint == ch ? UnicodeMappingSpan(index[lo].offset, index[lo].length) : UnicodeMappingSpan.init; } private dchar findUnicodeScalar(scope const(UnicodeScalarIndex)[] index, dchar ch) @safe pure nothrow @nogc { size_t lo; size_t hi = index.length; while (lo < hi) { const mid = lo + (hi - lo) / 2; if (index[mid].codepoint < ch) lo = mid + 1; else hi = mid; } return lo < index.length && index[lo].codepoint == ch ? cast(dchar) index[lo].value : ch; } private uint findUnicodeProperty(scope const(UnicodeScalarIndex)[] index, dchar ch) @safe pure nothrow @nogc { size_t lo; size_t hi = index.length; while (lo < hi) { const mid = lo + (hi - lo) / 2; if (index[mid].codepoint < ch) lo = mid + 1; else hi = mid; } return lo < index.length && index[lo].codepoint == ch ? index[lo].value : 0; } }; private
(alias) object.string = string
string
string sparkles.base.tools.gen_unicode_tables.sequenceTableSource(string name, const(sparkles.base.tools.gen_unicode_tables.SequenceMapping)[] mappings)
sequenceTableSource
(
(alias) object.string = string
string
(parameter) string name
name
,
const(
(struct) sparkles.base.tools.gen_unicode_tables.SequenceMapping
SequenceMapping
)[]
(parameter) const(sparkles.base.tools.gen_unicode_tables.SequenceMapping)[] mappings
mappings
)
{ auto
(local variable) std.array.Appender!string data
data
=
std.array.Appender!string std.array.appender!string() pure nothrow @safe

Convenience function that returns an Appender instance, optionally initialized with array.

appender
!
(alias) object.string = string
string
;
auto
(local variable) std.array.Appender!string index
index
=
std.array.Appender!string std.array.appender!string() pure nothrow @safe

Convenience function that returns an Appender instance, optionally initialized with array.

appender
!
(alias) object.string = string
string
;
uint
(local variable) uint offset
offset
;
(local variable) std.array.Appender!string data
data
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
("private immutable uint[] " ~
(parameter) string name
name
~ "Data = [\n ");
(local variable) std.array.Appender!string index
index
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
("private immutable UnicodeSequenceIndex[] " ~
(parameter) string name
name
~ "Index = [\n");
(alias) object.size_t = ulong
size_t
(local variable) ulong column
column
;
foreach (
(parameter) const(sparkles.base.tools.gen_unicode_tables.SequenceMapping) mapping
mapping
;
(parameter) const(sparkles.base.tools.gen_unicode_tables.SequenceMapping)[] mappings
mappings
)
{
(local variable) std.array.Appender!string index
index
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(
string std.format.format!(char, const(uint), uint, ulong)(in char[] fmt, const(uint) __param_1, uint __param_2, ulong __param_3) pure @safe

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

Examples

assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");

assert("Increase: %7.2f %%".format(17.4285) == "Increase:   17.43 %");
@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
(" UnicodeSequenceIndex(0x%X, %s, %s),\n",
(local variable) const(sparkles.base.tools.gen_unicode_tables.SequenceMapping) mapping
mapping
.
(field) uint sparkles.base.tools.gen_unicode_tables.SequenceMapping.codepoint
codepoint
,
(local variable) uint offset
offset
,
(local variable) const(sparkles.base.tools.gen_unicode_tables.SequenceMapping) mapping
mapping
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.SequenceMapping.values
values
.
(field) ulong const(uint[]).length
length
));
foreach (
(parameter) const(uint) value
value
;
(local variable) const(sparkles.base.tools.gen_unicode_tables.SequenceMapping) mapping
mapping
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.SequenceMapping.values
values
)
{ if (
(local variable) ulong column
column
!= 0)
(local variable) std.array.Appender!string data
data
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(
(local variable) ulong column
column
% 10 == 0 ? "\n " : " ");
(local variable) std.array.Appender!string data
data
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(
string std.format.format!(char, const(uint))(in char[] fmt, const(uint) __param_1) pure @safe

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

Examples

assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");

assert("Increase: %7.2f %%".format(17.4285) == "Increase:   17.43 %");
@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
("0x%X,",
(local variable) const(uint) value
value
));
++
(local variable) ulong column
column
;
}
(local variable) uint offset
offset
+=
(local variable) const(sparkles.base.tools.gen_unicode_tables.SequenceMapping) mapping
mapping
.
(field) uint[] sparkles.base.tools.gen_unicode_tables.SequenceMapping.values
values
.
(field) ulong const(uint[]).length
length
.
uint std.conv.to!uint.to!ulong(ulong __param_0) pure @safe

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

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
!uint;
}
(local variable) std.array.Appender!string data
data
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
("\n];\n");
(local variable) std.array.Appender!string index
index
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
("];\n");
return
(local variable) std.array.Appender!string data
data
.
string std.array.Appender!string.data() inout pure nothrow @nogc @property @safe

Use opSlice() from now on.

@returnsThe managed array.
data
~
(local variable) std.array.Appender!string index
index
.
string std.array.Appender!string.data() inout pure nothrow @nogc @property @safe

Use opSlice() from now on.

@returnsThe managed array.
data
~
string std.format.format!(char, string)(in char[] fmt, string __param_1) pure @safe

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

Examples

assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");

assert("Increase: %7.2f %%".format(17.4285) == "Increase:   17.43 %");
@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
(q{
UnicodeMappingSpan %1$s(dchar ch) @safe pure nothrow @nogc { return findUnicodeSequence(%1$sIndex, ch); } dchar %1$sValue(size_t offset) @safe pure nothrow @nogc { return cast(dchar) %1$sData[offset]; } },
(parameter) string name
name
);
} private
(alias) object.string = string
string
string sparkles.base.tools.gen_unicode_tables.scalarTableSource(string name, const(sparkles.base.tools.gen_unicode_tables.ScalarMapping)[] mappings)
scalarTableSource
(
(alias) object.string = string
string
(parameter) string name
name
, const(
(struct) sparkles.base.tools.gen_unicode_tables.ScalarMapping
ScalarMapping
)[]
(parameter) const(sparkles.base.tools.gen_unicode_tables.ScalarMapping)[] mappings
mappings
)
{ auto
(local variable) std.array.Appender!string source
source
=
std.array.Appender!string std.array.appender!string() pure nothrow @safe

Convenience function that returns an Appender instance, optionally initialized with array.

appender
!
(alias) object.string = string
string
;
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
("private immutable UnicodeScalarIndex[] " ~
(parameter) string name
name
~ "Index = [\n");
foreach (
(parameter) const(sparkles.base.tools.gen_unicode_tables.ScalarMapping) mapping
mapping
;
(parameter) const(sparkles.base.tools.gen_unicode_tables.ScalarMapping)[] mappings
mappings
)
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(
string std.format.format!(char, const(uint), const(uint))(in char[] fmt, const(uint) __param_1, const(uint) __param_2) pure @safe

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

Examples

assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");

assert("Increase: %7.2f %%".format(17.4285) == "Increase:   17.43 %");
@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
(" UnicodeScalarIndex(0x%X, 0x%X),\n",
(local variable) const(sparkles.base.tools.gen_unicode_tables.ScalarMapping) mapping
mapping
.
(field) uint sparkles.base.tools.gen_unicode_tables.ScalarMapping.codepoint
codepoint
,
(local variable) const(sparkles.base.tools.gen_unicode_tables.ScalarMapping) mapping
mapping
.
(field) uint sparkles.base.tools.gen_unicode_tables.ScalarMapping.value
value
));
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
("];\n");
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(
string std.format.format!(char, string)(in char[] fmt, string __param_1) pure @safe

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

Examples

assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");

assert("Increase: %7.2f %%".format(17.4285) == "Increase:   17.43 %");
@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
(q{
dchar %1$s(dchar ch) @safe pure nothrow @nogc { return findUnicodeScalar(%1$sIndex, ch); } },
(parameter) string name
name
));
return
(local variable) std.array.Appender!string source
source
.
string std.array.Appender!string.data() inout pure nothrow @nogc @property @safe

Use opSlice() from now on.

@returnsThe managed array.
data
;
} private
(alias) object.string = string
string
string sparkles.base.tools.gen_unicode_tables.scalarPropertyTableSource(string name, const(sparkles.base.tools.gen_unicode_tables.ScalarMapping)[] mappings)
scalarPropertyTableSource
(
(alias) object.string = string
string
(parameter) string name
name
,
const(
(struct) sparkles.base.tools.gen_unicode_tables.ScalarMapping
ScalarMapping
)[]
(parameter) const(sparkles.base.tools.gen_unicode_tables.ScalarMapping)[] mappings
mappings
)
{ auto
(local variable) std.array.Appender!string source
source
=
std.array.Appender!string std.array.appender!string() pure nothrow @safe

Convenience function that returns an Appender instance, optionally initialized with array.

appender
!
(alias) object.string = string
string
;
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
("private immutable UnicodeScalarIndex[] " ~
(parameter) string name
name
~ "Index = [\n"); foreach (
(parameter) const(sparkles.base.tools.gen_unicode_tables.ScalarMapping) mapping
mapping
;
(parameter) const(sparkles.base.tools.gen_unicode_tables.ScalarMapping)[] mappings
mappings
)
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(
string std.format.format!(char, const(uint), const(uint))(in char[] fmt, const(uint) __param_1, const(uint) __param_2) pure @safe

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

Examples

assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");

assert("Increase: %7.2f %%".format(17.4285) == "Increase:   17.43 %");
@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
(" UnicodeScalarIndex(0x%X, 0x%X),\n",
(local variable) const(sparkles.base.tools.gen_unicode_tables.ScalarMapping) mapping
mapping
.
(field) uint sparkles.base.tools.gen_unicode_tables.ScalarMapping.codepoint
codepoint
,
(local variable) const(sparkles.base.tools.gen_unicode_tables.ScalarMapping) mapping
mapping
.
(field) uint sparkles.base.tools.gen_unicode_tables.ScalarMapping.value
value
));
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
("];\n");
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(
string std.format.format!(char, string)(in char[] fmt, string __param_1) pure @safe

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

Examples

assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");

assert("Increase: %7.2f %%".format(17.4285) == "Increase:   17.43 %");
@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
(q{
ubyte %1$s(dchar ch) @safe pure nothrow @nogc { return cast(ubyte) findUnicodeProperty(%1$sIndex, ch); } },
(parameter) string name
name
));
return
(local variable) std.array.Appender!string source
source
.
string std.array.Appender!string.data() inout pure nothrow @nogc @property @safe

Use opSlice() from now on.

@returnsThe managed array.
data
;
} private
(alias) object.string = string
string
string sparkles.base.tools.gen_unicode_tables.compositionTableSource(const(sparkles.base.tools.gen_unicode_tables.CompositionMapping)[] mappings)
compositionTableSource
(const(
(struct) sparkles.base.tools.gen_unicode_tables.CompositionMapping
CompositionMapping
)[]
(parameter) const(sparkles.base.tools.gen_unicode_tables.CompositionMapping)[] mappings
mappings
)
{ auto
(local variable) std.array.Appender!string source
source
=
std.array.Appender!string std.array.appender!string() pure nothrow @safe

Convenience function that returns an Appender instance, optionally initialized with array.

appender
!
(alias) object.string = string
string
;
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(q{
private struct UnicodeComposition { ulong key; uint value; } private immutable UnicodeComposition[] unicodeCompositions = [ }); foreach (
(parameter) const(sparkles.base.tools.gen_unicode_tables.CompositionMapping) mapping
mapping
;
(parameter) const(sparkles.base.tools.gen_unicode_tables.CompositionMapping)[] mappings
mappings
)
{ const
(local variable) const(ulong) key
key
= (cast(ulong)
(local variable) const(sparkles.base.tools.gen_unicode_tables.CompositionMapping) mapping
mapping
.
(field) uint sparkles.base.tools.gen_unicode_tables.CompositionMapping.first
first
<< 21) |
(local variable) const(sparkles.base.tools.gen_unicode_tables.CompositionMapping) mapping
mapping
.
(field) uint sparkles.base.tools.gen_unicode_tables.CompositionMapping.second
second
;
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(
string std.format.format!(char, const(ulong), const(uint))(in char[] fmt, const(ulong) __param_1, const(uint) __param_2) pure @safe

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

Examples

assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");

assert("Increase: %7.2f %%".format(17.4285) == "Increase:   17.43 %");
@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
(" UnicodeComposition(0x%X, 0x%X),\n",
(local variable) const(ulong) key
key
,
(local variable) const(sparkles.base.tools.gen_unicode_tables.CompositionMapping) mapping
mapping
.
(field) uint sparkles.base.tools.gen_unicode_tables.CompositionMapping.value
value
));
}
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(q{];
dchar canonicalComposition(dchar first, dchar second) @safe pure nothrow @nogc { const key = (cast(ulong) first << 21) | cast(uint) second; size_t lo; size_t hi = unicodeCompositions.length; while (lo < hi) { const mid = lo + (hi - lo) / 2; if (unicodeCompositions[mid].key < key) lo = mid + 1; else hi = mid; } return lo < unicodeCompositions.length && unicodeCompositions[lo].key == key ? cast(dchar) unicodeCompositions[lo].value : dchar.init; } }); return
(local variable) std.array.Appender!string source
source
.
string std.array.Appender!string.data() inout pure nothrow @nogc @property @safe

Use opSlice() from now on.

@returnsThe managed array.
data
;
} private
(alias) object.string = string
string
string sparkles.base.tools.gen_unicode_tables.wordBreakMember(string property)
wordBreakMember
(
(alias) object.string = string
string
(parameter) string property
property
)
{ switch (
(parameter) string property
property
)
{ case "CR": return "cr"; case "LF": return "lf"; case "Newline": return "newline"; case "Extend": return "extend"; case "ZWJ": return "zwj"; case "Regional_Indicator": return "regionalIndicator"; case "Format": return "format"; case "Katakana": return "katakana"; case "Hebrew_Letter": return "hebrewLetter"; case "ALetter": return "aLetter"; case "Single_Quote": return "singleQuote"; case "Double_Quote": return "doubleQuote"; case "MidNumLet": return "midNumLet"; case "MidLetter": return "midLetter"; case "MidNum": return "midNum"; case "Numeric": return "numeric"; case "ExtendNumLet": return "extendNumLet"; case "WSegSpace": return "wSegSpace"; default: return "other"; } } private
(alias) object.string = string
string
string sparkles.base.tools.gen_unicode_tables.wordBreakTableSource(const(sparkles.base.tools.gen_unicode_tables.WordBreakRange)[] ranges)
wordBreakTableSource
(const(
(struct) sparkles.base.tools.gen_unicode_tables.WordBreakRange
WordBreakRange
)[]
(parameter) const(sparkles.base.tools.gen_unicode_tables.WordBreakRange)[] ranges
ranges
)
{ auto
(local variable) std.array.Appender!string source
source
=
std.array.Appender!string std.array.appender!string() pure nothrow @safe

Convenience function that returns an Appender instance, optionally initialized with array.

appender
!
(alias) object.string = string
string
;
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(q{
enum WordBreakClass : ubyte { other, cr, lf, newline, extend, zwj, regionalIndicator, format, katakana, hebrewLetter, aLetter, singleQuote, doubleQuote, midNumLet, midLetter, midNum, numeric, extendNumLet, wSegSpace, } private struct WordBreakRange { uint first; uint last; WordBreakClass kind; } private immutable WordBreakRange[] wordBreakRanges = [ }); foreach (
(parameter) const(sparkles.base.tools.gen_unicode_tables.WordBreakRange) range
range
;
(parameter) const(sparkles.base.tools.gen_unicode_tables.WordBreakRange)[] ranges
ranges
)
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(
string std.format.format!(char, const(uint), const(uint), string)(in char[] fmt, const(uint) __param_1, const(uint) __param_2, string __param_3) pure @safe

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

Examples

assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");

assert("Increase: %7.2f %%".format(17.4285) == "Increase:   17.43 %");
@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
(" WordBreakRange(0x%X, 0x%X, WordBreakClass.%s),\n",
(local variable) const(sparkles.base.tools.gen_unicode_tables.WordBreakRange) range
range
.
(field) uint sparkles.base.tools.gen_unicode_tables.WordBreakRange.first
first
,
(local variable) const(sparkles.base.tools.gen_unicode_tables.WordBreakRange) range
range
.
(field) uint sparkles.base.tools.gen_unicode_tables.WordBreakRange.last
last
,
string sparkles.base.tools.gen_unicode_tables.wordBreakMember(string property)
wordBreakMember
(
(local variable) const(sparkles.base.tools.gen_unicode_tables.WordBreakRange) range
range
.
(field) string sparkles.base.tools.gen_unicode_tables.WordBreakRange.property
property
)));
(local variable) std.array.Appender!string source
source
.
void std.array.Appender!string.put!string(string items) pure nothrow @safe

Appends an entire range to the managed array. Performs encoding for char elements if A is a differently typed char array.

@paramitems the range of items to append
put
(q{];
WordBreakClass wordBreakClass(dchar ch) @safe pure nothrow @nogc { size_t lo; size_t hi = wordBreakRanges.length; while (lo < hi) { const mid = lo + (hi - lo) / 2; if (wordBreakRanges[mid].last < ch) lo = mid + 1; else hi = mid; } return lo < wordBreakRanges.length && wordBreakRanges[lo].first <= ch ? wordBreakRanges[lo].kind : WordBreakClass.other; } }); return
(local variable) std.array.Appender!string source
source
.
string std.array.Appender!string.data() inout pure nothrow @nogc @property @safe

Use opSlice() from now on.

@returnsThe managed array.
data
;
} private
(alias) object.string = string
string
string sparkles.base.tools.gen_unicode_tables.header(string ver)
header
(
(alias) object.string = string
string
(parameter) string ver
ver
)
{ return
string std.format.format!(char, string)(in char[] fmt, string __param_1) pure @safe

Converts its arguments according to a format string into a string.

The second version of format takes the format string as template argument. In this case, it is checked for consistency at compile-time and produces slightly faster code, because the length of the output buffer can be estimated in advance.

Examples

assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");

assert("Increase: %7.2f %%".format(17.4285) == "Increase:   17.43 %");
@paramfmt a format string@paramargs a variadic list of arguments to be formatted@paramChar character type of fmt@paramArgs a variadic list of types of the arguments@returnsThe formatted string.@throwsA FormatException if formatting did not succeed.@seesformat for a variant, that tries to avoid garbage collection.
format
(`
// Generated by libs/base/tools/gen_unicode_tables.d — DO NOT EDIT. // // Unicode %s width, emoji, normalization, folding, combining-class, // and word-break properties used by sparkles' text primitives. // Regenerate by running ./libs/base/tools/gen_unicode_tables.d. module sparkles.base.text.unicode_tables; `.
string std.string.outdent!string(string str) pure @safe

Removes one level of indentation from a multi-line string.

This uniformly outdents the text as much as possible. Whitespace-only lines are always converted to blank lines.

Does not allocate memory if it does not throw.

Examples

    enum pretty = q{
       import std.stdio;
       void main() {
           writeln("Hello");
       }
    }.outdent();

    enum ugly = q{
import std.stdio;
void main() {
    writeln("Hello");
}
};

    assert(pretty == ugly);
@paramstr multi-line string@returnsoutdented string@throwsStringException if indentation is done with different sequences of whitespace characters.
outdent
[1 .. $],
(parameter) string ver
ver
);
}