Helper functions for working with C strings.

This module is intended to provide fast, safe and garbage free way to work with C strings.


import core.stdc.stdlib: free;
import core.sys.posix.unistd: getcwd;
import core.sys.posix.stdlib: getenv, setenv;
import std.exception: enforce;

@property string cwd()
{ return enforce(getcwd(null, 0).moveToString!free()); }

string getEnvironment(in char[] name)
{ return enforce(getenv(name.tempCString()).toString()); }

void setEnvironment(in char[] name, in char[] value)
{ enforce(setenv(name.tempCString(), value.tempCString(), 1) != -1); }

import core.sys.windows.windows: SetEnvironmentVariableW;
import std.exception: enforce;

void setEnvironment(in char[] name, in char[] value)
{ enforce(SetEnvironmentVariableW(name.tempCString!wchar(), value.tempCString!wchar())); }
Boost License 1.0.
Denis Shelomovskij

pure nothrow size_t  length(C)(in C* cstr) if (isSomeChar!C);

Returns C string  length. If cstr is null returns 0.

pure nothrow int  cmpCStrings(C)(in C* cstr1, in C* cstr2) if (isSomeChar!C);

Compare C strings lexicographically.

cstr1 != null && cstr2 != null
assert(cmpCStrings("ab".ptr, "ab".ptr) == 0);
assert(cmpCStrings("ab".ptr, "abc".ptr) < 0);
assert(cmpCStrings("abc".ptr, "ab".ptr) > 0);

pure nothrow bool  equalCStrings(C)(in C* cstr1, in C* cstr2) if (isSomeChar!C);

Returns whether two C strings are equal.

cstr1 != null && cstr2 != null
assert( equalCStrings("ab".ptr, "ab".ptr));
assert(!equalCStrings("ab".ptr, "abc".ptr));
assert( equalCStrings("ab".ptr, "ab\0cd".ptr));

pure nothrow inout(C)[]  asArray(C)(inout C* cstr) if (isSomeChar!C);

Returns array representing C string where '\0' character is placed after the end of the array. If cstr is null returns null.

pure string  toString(C)(in C* cstr) if (isSomeChar!C);

Creates GC-allocated string with copy of C string text. If cstr is null returns null, otherwise if cstr is empty returns "".

To*  toCString(alias tryAllocate, To = char, From)(in From[] str) if (isSomeChar!To && isSomeChar!From);

Creates C string allocated using tryAllocate with copy of str. If str is null returns null.

tryAllocate is assumed to return properly aligned for To memory or null if allocation fails.

If allocation fails  toCString will call core.exception.onOutOfMemoryError which is expected to throw an core.exception.OutOfMemoryError.

import core.stdc.stdlib;
import core.stdc.string;

string str = "abc";

char* cstr = str.toCString!malloc();
scope(exit) free(cstr);
assert(strlen(cstr) == 3);

string  moveToString(alias release, C)(C* cstr) if (isSomeChar!C);

Returns same as toString but also if cstr is not null releases its memory calling release(cast(void*) cstr).

auto  tempCString(To = char, From)(in From[] str) if (isSomeChar!To && isSomeChar!From);

Creates temporary C string with copy of passed text.

Returned object is implicitly convertible to const To* and has two properties: ptr to access C string as const To* and buffPtr to access it as To*.

The temporary C string is valid unless returned object is destroyed. Thus if returned object is assigned to a variable the temporary is valid unless the variable goes out of scope. If returned object isn't assigned to a variable it will be destroyed at the end of creating primary expression.

Implementation note:
For small strings  tempCString will use stack allocated buffer, for large strings (approximately 1000 characters and more) it will allocate temporary one from unstd.memory.allocation.threadHeap.
This function is intended to be used in function call expression (like strlen(str. tempCString())). Incorrect usage of this function may lead to memory corruption. See WARNING in Examples section.
See Also
import core.stdc.string;

string str = "abc";

// Intended usage
assert(strlen(str.tempCString()) == 3);

// Correct usage
auto tmp = str.tempCString();
assert(strlen(tmp) == 3); // or `tmp.ptr`, or `tmp.buffPtr`

// $(RED WARNING): $(RED Incorrect usage)
auto pInvalid1 = str.tempCString().ptr;
const char* pInvalid2 = str.tempCString();
// Both pointers refer to invalid memory here as
// returned values aren't assigned to a variable and
// both primary expressions are ended.