Commit b0cfc9f9 authored by Matthias Klumpp's avatar Matthias Klumpp

New upstream version 1.0.7

parent 299ed6fa
......@@ -31,3 +31,10 @@
*.i*86
*.x86_64
*.hex
# Extra dirs/build files
bin
obj
.dub
.vs
undead.sln
language: d
install:
- DMD_VER=2.066.1
- DUB_VER=0.9.22
- curl -fsSL http://downloads.dlang.org/releases/2014/dmd.${DMD_VER}.linux.zip > dmd.zip
- unzip -q -d ~ dmd.zip
- curl -fsSL http://code.dlang.org/files/dub-${DUB_VER}-linux-x86_64.tar.gz | tar -C ~/dmd2/linux/bin64 -xzf -
- export PATH="${HOME}/dmd2/linux/bin64:${PATH}"
- export LD_LIBRARY_PATH="${HOME}/dmd2/linux/lib64:${LD_LIBRARY_PATH}"
os:
- linux
- osx
script:
- dub test
d:
- dmd
- ldc
sudo: false
[![Build Status](https://travis-ci.org/dlang/undeaD.svg?branch=master)](https://travis-ci.org/dlang/undeaD)
undeaD
======
......@@ -11,3 +13,8 @@ Current modules included:
* std.dateparse
* std.regexp
* std.stream and friends
Some individual functions have been moved here rather than full Phobos modules. They are
* undead.doformat: Contains the `doFormat` function from std.format
* undead.string: Contains regex style pattern matching functions from std.string
......@@ -2,7 +2,7 @@
"name": "undead",
"description": "Obsolete Phobos modules, back from the dead",
"authors": ["various"],
"homepage": "https://github.com/DigitalMars/undead",
"homepage": "https://github.com/dlang/undeaD",
"license": "BSL-1.0",
"targetType": "library",
"targetPath": "bin",
......
......@@ -20,7 +20,8 @@ LFLAGS=-L/map/co
$(DMD) -c $(DFLAGS) $*
SRC= $S/bitarray.d $S/regexp.d $S/datebase.d $S/date.d $S/dateparse.d \
$S/cstream.d $S/stream.d $S/socketstream.d $S/doformat.d
$S/cstream.d $S/stream.d $S/socketstream.d $S/doformat.d $S/string.d \
$S/internal/file.d
SOURCE= $(SRC) win32.mak posix.mak LICENSE README.md dub.json
......
......@@ -149,7 +149,7 @@ class CFile : Stream {
// run a few tests
unittest {
import undead.internal.file : deleteme;
import undead.internal.file;
import std.internal.cstring : tempCString;
auto stream_file = (undead.internal.file.deleteme ~ "-stream.txt").tempCString();
......
......@@ -821,7 +821,7 @@ d_time parse(string s)
auto result = makeDate(day,time);
return timeClip(result);
}
catch
catch (Exception e)
{
return d_time_nan; // erroneous date string
}
......@@ -832,7 +832,7 @@ extern(C) void std_date_static_this()
localTZA = getLocalTZA();
}
version (Win32)
version (Windows)
{
private import core.sys.windows.windows;
//import c.time;
......
......@@ -403,7 +403,7 @@ void main()
*/
void doFormat()(scope void delegate(dchar) putc, TypeInfo[] arguments, va_list ap)
{
import std.utf : toUCSindex, isValidDchar, UTFException, toUTF8;
import std.utf : encode, toUCSindex, isValidDchar, UTFException, toUTF8;
import core.stdc.string : strlen;
import core.stdc.stdlib : alloca, malloc, realloc, free;
import core.stdc.stdio : snprintf;
......@@ -762,7 +762,7 @@ void doFormat()(scope void delegate(dchar) putc, TypeInfo[] arguments, va_list a
{ if (!isValidDchar(vdchar))
throw new UTFException("invalid dchar in format");
char[4] vbuf;
putstr(toUTF8(vbuf, vdchar));
putstr(vbuf[0 .. encode(vbuf, vdchar)]);
}
return;
......@@ -1311,310 +1311,19 @@ private bool needToSwapEndianess(Char)(ref FormatSpec!Char f)
|| endian == Endian.bigEndian && f.flDash;
}
/* ======================== Unit Tests ====================================== */
unittest
{
import std.conv : octal;
int i;
string s;
debug(format) printf("std.format.format.unittest\n");
s = format("hello world! %s %s %s%s%s", true, 57, 1_000_000_000, 'x', " foo");
assert(s == "hello world! true 57 1000000000x foo");
s = format("%s %A %s", 1.67, -1.28, float.nan);
/* The host C library is used to format floats.
* C99 doesn't specify what the hex digit before the decimal point
* is for %A.
*/
//version (linux)
// assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan");
//else version (OSX)
// assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan", s);
//else
version (MinGW)
assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan", s);
else version (CRuntime_Microsoft)
assert(s == "1.67 -0X1.47AE14P+0 nan"
|| s == "1.67 -0X1.47AE147AE147BP+0 nan", s); // MSVCRT 14+ (VS 2015)
else
assert(s == "1.67 -0X1.47AE147AE147BP+0 nan", s);
s = format("%x %X", 0x1234AF, 0xAFAFAFAF);
assert(s == "1234af AFAFAFAF");
s = format("%b %o", 0x1234AF, 0xAFAFAFAF);
assert(s == "100100011010010101111 25753727657");
s = format("%d %s", 0x1234AF, 0xAFAFAFAF);
assert(s == "1193135 2947526575");
//version(X86_64)
//{
// pragma(msg, "several format tests disabled on x86_64 due to bug 5625");
//}
//else
//{
s = format("%s", 1.2 + 3.4i);
assert(s == "1.2+3.4i", s);
//s = format("%x %X", 1.32, 6.78f);
//assert(s == "3ff51eb851eb851f 40D8F5C3");
//}
s = format("%#06.*f",2,12.345);
assert(s == "012.35");
s = format("%#0*.*f",6,2,12.345);
assert(s == "012.35");
s = format("%7.4g:", 12.678);
assert(s == " 12.68:");
s = format("%7.4g:", 12.678L);
assert(s == " 12.68:");
s = format("%04f|%05d|%#05x|%#5x",-4.0,-10,1,1);
assert(s == "-4.000000|-0010|0x001| 0x1");
i = -10;
s = format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
assert(s == "-10|-10|-10|-10|-10.0000");
i = -5;
s = format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
assert(s == "-5| -5|-05|-5|-5.0000");
i = 0;
s = format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
assert(s == "0| 0|000|0|0.0000");
i = 5;
s = format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
assert(s == "5| 5|005|5|5.0000");
i = 10;
s = format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
assert(s == "10| 10|010|10|10.0000");
s = format("%.0d", 0);
assert(s == "");
s = format("%.g", .34);
assert(s == "0.3");
s = format("%.0g", .34);
assert(s == "0.3");
s = format("%.2g", .34);
assert(s == "0.34");
s = format("%0.0008f", 1e-08);
assert(s == "0.00000001");
s = format("%0.0008f", 1e-05);
assert(s == "0.00001000");
s = "helloworld";
string r;
r = format("%.2s", s[0..5]);
assert(r == "he");
r = format("%.20s", s[0..5]);
assert(r == "hello");
r = format("%8s", s[0..5]);
assert(r == " hello");
byte[] arrbyte = new byte[4];
arrbyte[0] = 100;
arrbyte[1] = -99;
arrbyte[3] = 0;
r = format("%s", arrbyte);
assert(r == "[100, -99, 0, 0]");
ubyte[] arrubyte = new ubyte[4];
arrubyte[0] = 100;
arrubyte[1] = 200;
arrubyte[3] = 0;
r = format("%s", arrubyte);
assert(r == "[100, 200, 0, 0]");
short[] arrshort = new short[4];
arrshort[0] = 100;
arrshort[1] = -999;
arrshort[3] = 0;
r = format("%s", arrshort);
assert(r == "[100, -999, 0, 0]");
ushort[] arrushort = new ushort[4];
arrushort[0] = 100;
arrushort[1] = 20_000;
arrushort[3] = 0;
r = format("%s", arrushort);
assert(r == "[100, 20000, 0, 0]");
int[] arrint = new int[4];
arrint[0] = 100;
arrint[1] = -999;
arrint[3] = 0;
r = format("%s", arrint);
assert(r == "[100, -999, 0, 0]");
long[] arrlong = new long[4];
arrlong[0] = 100;
arrlong[1] = -999;
arrlong[3] = 0;
r = format("%s", arrlong);
assert(r == "[100, -999, 0, 0]");
ulong[] arrulong = new ulong[4];
arrulong[0] = 100;
arrulong[1] = 999;
arrulong[3] = 0;
r = format("%s", arrulong);
assert(r == "[100, 999, 0, 0]");
string[] arr2 = new string[4];
arr2[0] = "hello";
arr2[1] = "world";
arr2[3] = "foo";
r = format("%s", arr2);
assert(r == `["hello", "world", "", "foo"]`);
r = format("%.8d", 7);
assert(r == "00000007");
r = format("%.8x", 10);
assert(r == "0000000a");
r = format("%-3d", 7);
assert(r == "7 ");
r = format("%*d", -3, 7);
assert(r == "7 ");
r = format("%.*d", -3, 7);
assert(r == "7");
r = format("abc"c);
assert(r == "abc");
//format() returns the same type as inputted.
wstring wr;
wr = format("def"w);
assert(wr == "def"w);
dstring dr;
dr = format("ghi"d);
assert(dr == "ghi"d);
void* p = cast(void*)0xDEADBEEF;
r = format("%s", p);
assert(r == "DEADBEEF");
r = format("%#x", 0xabcd);
assert(r == "0xabcd");
r = format("%#X", 0xABCD);
assert(r == "0XABCD");
r = format("%#o", octal!12345);
assert(r == "012345");
r = format("%o", 9);
assert(r == "11");
r = format("%#o", 0); // issue 15663
assert(r == "0");
r = format("%+d", 123);
assert(r == "+123");
r = format("%+d", -123);
assert(r == "-123");
r = format("% d", 123);
assert(r == " 123");
r = format("% d", -123);
assert(r == "-123");
r = format("%%");
assert(r == "%");
r = format("%d", true);
assert(r == "1");
r = format("%d", false);
assert(r == "0");
r = format("%d", 'a');
assert(r == "97");
wchar wc = 'a';
r = format("%d", wc);
assert(r == "97");
dchar dc = 'a';
r = format("%d", dc);
assert(r == "97");
byte b = byte.max;
r = format("%x", b);
assert(r == "7f");
r = format("%x", ++b);
assert(r == "80");
r = format("%x", ++b);
assert(r == "81");
short sh = short.max;
r = format("%x", sh);
assert(r == "7fff");
r = format("%x", ++sh);
assert(r == "8000");
r = format("%x", ++sh);
assert(r == "8001");
i = int.max;
r = format("%x", i);
assert(r == "7fffffff");
r = format("%x", ++i);
assert(r == "80000000");
r = format("%x", ++i);
assert(r == "80000001");
r = format("%x", 10);
assert(r == "a");
r = format("%X", 10);
assert(r == "A");
r = format("%x", 15);
assert(r == "f");
r = format("%X", 15);
assert(r == "F");
Object c = null;
r = format("%s", c);
assert(r == "null");
enum TestEnum
string res;
void putc(dchar c)
{
Value1, Value2
res ~= c;
}
r = format("%s", TestEnum.Value2);
assert(r == "Value2");
immutable(char[5])[int] aa = ([3:"hello", 4:"betty"]);
r = format("%s", aa.values);
assert(r == `["hello", "betty"]` || r == `["betty", "hello"]`);
r = format("%s", aa);
assert(r == `[3:"hello", 4:"betty"]` || r == `[4:"betty", 3:"hello"]`);
static const dchar[] ds = ['a','b'];
for (int j = 0; j < ds.length; ++j)
void myPrint(...)
{
r = format(" %d", ds[j]);
if (j == 0)
assert(r == " 97");
else
assert(r == " 98");
undead.doformat.doFormat(&putc, _arguments, _argptr);
}
r = format(">%14d<, %s", 15, [1,2,3]);
assert(r == "> 15<, [1, 2, 3]");
assert(format("%8s", "bar") == " bar");
assert(format("%8s", "b\u00e9ll\u00f4") == " b\u00e9ll\u00f4");
myPrint("The answer is %s:", 27, 6);
assert(res == "The answer is 27:6");
}
......@@ -83,7 +83,7 @@ private {
import std.utf;
import core.bitop; // for bswap
import core.vararg;
import std.file;
static import std.file;
import undead.internal.file;
import undead.doformat;
}
......@@ -1433,11 +1433,11 @@ class Stream : InputStream, OutputStream {
unittest { // unit test for Issue 3363
import std.stdio;
immutable fileName = undead.internal.file.deleteme ~ "-issue3363.txt";
auto w = File(fileName, "w");
scope (exit) remove(fileName.ptr);
auto w = std.stdio.File(fileName, "w");
scope (exit) std.file.remove(fileName);
w.write("one two three");
w.close();
auto r = File(fileName, "r");
auto r = std.stdio.File(fileName, "r");
const(char)[] constChar;
string str;
char[] chars;
......@@ -1979,7 +1979,7 @@ class File: Stream {
readable = cast(bool)(mode & FileMode.In);
writeable = cast(bool)(mode & FileMode.Out);
version (Windows) {
hFile = CreateFileW(filename.tempCStringW(), access, share,
hFile = CreateFileW(filename.tempCString!wchar(), access, share,
null, createMode, 0, null);
isopen = hFile != INVALID_HANDLE_VALUE;
}
......@@ -2136,8 +2136,6 @@ class File: Stream {
// run a few tests
unittest {
import std.internal.cstring : tempCString;
File file = new File;
int i = 666;
auto stream_file = undead.internal.file.deleteme ~ "-stream.$$$";
......@@ -2208,7 +2206,7 @@ class File: Stream {
assert( lines[2] == "");
assert( lines[3] == "That was blank");
file.close();
remove(stream_file.tempCString());
std.file.remove(stream_file);
}
}
......@@ -2256,8 +2254,6 @@ class BufferedFile: BufferedStream {
// run a few tests same as File
unittest {
import std.internal.cstring : tempCString;
BufferedFile file = new BufferedFile;
int i = 666;
auto stream_file = undead.internal.file.deleteme ~ "-stream.$$$";
......@@ -2303,7 +2299,7 @@ class BufferedFile: BufferedStream {
// we must be at the end of file
assert(file.eof);
file.close();
remove(stream_file.tempCString());
std.file.remove(stream_file);
}
}
......
/**
* Contains the obsolete pattern matching functions from Phobos'
* `std.string`.
*/
module undead.string;
import std.traits;
/***********************************************
* See if character c is in the pattern.
* Patterns:
*
* A $(I pattern) is an array of characters much like a $(I character
* class) in regular expressions. A sequence of characters
* can be given, such as "abcde". The '-' can represent a range
* of characters, as "a-e" represents the same pattern as "abcde".
* "a-fA-F0-9" represents all the hex characters.
* If the first character of a pattern is '^', then the pattern
* is negated, i.e. "^0-9" means any character except a digit.
* The functions inPattern, $(B countchars), $(B removeschars),
* and $(B squeeze) use patterns.
*
* Note: In the future, the pattern syntax may be improved
* to be more like regular expression character classes.
*/
bool inPattern(S)(dchar c, in S pattern) @safe pure @nogc
if (isSomeString!S)
{
bool result = false;
int range = 0;
dchar lastc;
foreach (size_t i, dchar p; pattern)
{
if (p == '^' && i == 0)
{
result = true;
if (i + 1 == pattern.length)
return (c == p); // or should this be an error?
}
else if (range)
{
range = 0;
if (lastc <= c && c <= p || c == p)
return !result;
}
else if (p == '-' && i > result && i + 1 < pattern.length)
{
range = 1;
continue;
}
else if (c == p)
return !result;
lastc = p;
}
return result;
}
@safe pure @nogc unittest
{
assertCTFEable!(
{
assert(inPattern('x', "x") == 1);
assert(inPattern('x', "y") == 0);
assert(inPattern('x', string.init) == 0);
assert(inPattern('x', "^y") == 1);
assert(inPattern('x', "yxxy") == 1);
assert(inPattern('x', "^yxxy") == 0);
assert(inPattern('x', "^abcd") == 1);
assert(inPattern('^', "^^") == 0);
assert(inPattern('^', "^") == 1);
assert(inPattern('^', "a^") == 1);
assert(inPattern('x', "a-z") == 1);
assert(inPattern('x', "A-Z") == 0);
assert(inPattern('x', "^a-z") == 0);
assert(inPattern('x', "^A-Z") == 1);
assert(inPattern('-', "a-") == 1);
assert(inPattern('-', "^A-") == 0);
assert(inPattern('a', "z-a") == 1);
assert(inPattern('z', "z-a") == 1);
assert(inPattern('x', "z-a") == 0);
});
}
/**
* See if character c is in the intersection of the patterns.
*/
bool inPattern(S)(dchar c, S[] patterns) @safe pure @nogc
if (isSomeString!S)
{
foreach (string pattern; patterns)
{
if (!inPattern(c, pattern))
{
return false;
}
}
return true;
}
/**
* Count characters in s that match pattern.
*/
size_t countchars(S, S1)(S s, in S1 pattern) @safe pure @nogc
if (isSomeString!S && isSomeString!S1)
{
size_t count;
foreach (dchar c; s)
{
count += inPattern(c, pattern);
}
return count;
}
@safe pure @nogc unittest
{
assertCTFEable!(
{
assert(countchars("abc", "a-c") == 3);
assert(countchars("hello world", "or") == 3);
});
}
/**
* Return string that is s with all characters removed that match pattern.
*/
S removechars(S)(S s, in S pattern) @safe pure
if (isSomeString!S)
{
import std.utf : encode;
Unqual!(typeof(s[0]))[] r;
bool changed = false;
foreach (size_t i, dchar c; s)
{
if (inPattern(c, pattern))
{
if (!changed)
{
changed = true;
r = s[0 .. i].dup;
}
continue;
}
if (changed)
{
encode(r, c);
}
}
if (changed)
return r;
else
return s;
}
@safe pure unittest
{
assertCTFEable!(
{
assert(removechars("abc", "a-c").length == 0);
assert(removechars("hello world", "or") == "hell wld");
assert(removechars("hello world", "d") == "hello worl");
assert(removechars("hah", "h") == "a");
});
}
@safe pure unittest
{
assert(removechars("abc", "x") == "abc");
}
/***************************************************
* Return string where sequences of a character in s[] from pattern[]
* are replaced with a single instance of that character.
* If pattern is null, it defaults to all characters.
*/
S squeeze(S)(S s, in S pattern = null)
{
import std.utf : encode, stride;
Unqual!(typeof(s[0]))[] r;
dchar lastc;
size_t lasti;
int run;
bool changed;
foreach (size_t i, dchar c; s)
{
if (run && lastc == c)
{
changed = true;
}
else if (pattern is null || inPattern(c, pattern))
{
run = 1;
if (changed)
{
if (r is null)
r = s[0 .. lasti].dup;
encode(r, c);
}
else
lasti = i + stride(s, i);
lastc = c;
}
else
{
run = 0;
if (changed)
{
if (r is null)
r = s[0 .. lasti].dup;
encode(r, c);
}
}
}
return changed ? ((r is null) ? s[0 .. lasti] : cast(S) r) : s;
}
@system pure unittest
{
assertCTFEable!(
{
string s;
assert(squeeze("hello") == "helo");
s = "abcd";