phobos 0.114

This commit is contained in:
Brad Roberts 2007-09-10 04:31:54 +00:00
parent bc412e7c3f
commit f5e542b7da
19 changed files with 2849 additions and 649 deletions

View file

@ -1,13 +1,33 @@
//_ adi.d
// Copyright (c) 2000-2003 by Digital Mars
// All Rights Reserved
// www.digitalmars.com
// Written by Walter Bright
/*
* Copyright (C) 2000-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
// Dynamic array property support routines
//debug=adi; // uncomment to turn on debugging printf's
import std.stdio;
import std.c.stdio;
import std.c.stdlib;
import std.string;
@ -20,6 +40,178 @@ struct Array
void *ptr;
}
/**********************************************
* Reverse array of chars.
* Handled separately because embedded multibyte encodings should not be
* reversed.
*/
extern (C) long _adReverseChar(char[] a)
{
if (a.length > 1)
{
char[6] tmp;
char* lo = a.ptr;
char* hi = &a[length - 1];
while (lo < hi)
{ char clo = *lo;
char chi = *hi;
if (clo <= 0x7F && chi <= 0x7F)
{
*lo = chi;
*hi = clo;
lo++;
hi--;
continue;
}
int stridelo = std.utf.UTF8stride[clo];
int stridehi = 1;
while ((chi & 0xC0) == 0x80)
{
chi = *--hi;
stridehi++;
assert(hi >= lo);
}
if (lo == hi)
break;
if (stridelo == stridehi)
{
memcpy(tmp, lo, stridelo);
memcpy(lo, hi, stridelo);
memcpy(hi, tmp, stridelo);
lo += stridelo;
hi -= stridehi;
continue;
}
/* Shift the whole array. This is woefully inefficient
*/
//writefln("stridelo = %d, stridehi = %d", stridelo, stridehi);
memcpy(tmp, hi, stridehi);
memcpy(hi + stridehi - stridelo, lo, stridelo);
memmove(lo + stridehi, lo + stridelo , hi - (lo + stridelo));
memcpy(lo, tmp, stridehi);
lo += stridehi;
hi -= stridelo;
}
}
return *cast(long*)(&a);
}
unittest
{
char[] a = "abcd";
char[] r;
r = a.dup.reverse;
//writefln(r);
assert(r == "dcba");
a = "a\u1235\u1234c";
//writefln(a);
r = a.dup.reverse;
//writefln(r);
assert(r == "c\u1234\u1235a");
a = "ab\u1234c";
//writefln(a);
r = a.dup.reverse;
//writefln(r);
assert(r == "c\u1234ba");
}
/**********************************************
* Reverse array of wchars.
* Handled separately because embedded multiword encodings should not be
* reversed.
*/
extern (C) long _adReverseWchar(wchar[] a)
{
if (a.length > 1)
{
wchar[2] tmp;
wchar* lo = a.ptr;
wchar* hi = &a[length - 1];
while (lo < hi)
{ wchar clo = *lo;
wchar chi = *hi;
if ((clo < 0xD800 || clo > 0xDFFF) &&
(chi < 0xD800 || chi > 0xDFFF))
{
*lo = chi;
*hi = clo;
lo++;
hi--;
continue;
}
int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
int stridehi = 1;
if (chi >= 0xDC00 && chi <= 0xDFFF)
{
chi = *--hi;
stridehi++;
assert(hi >= lo);
}
if (lo == hi)
break;
if (stridelo == stridehi)
{ int tmp;
assert(stridelo == 2);
assert(tmp.sizeof == 2 * (*lo).sizeof);
tmp = *cast(int*)lo;
*cast(int*)lo = *cast(int*)hi;
*cast(int*)hi = tmp;
lo += stridelo;
hi -= stridehi;
continue;
}
/* Shift the whole array. This is woefully inefficient
*/
memcpy(tmp, hi, stridehi * wchar.sizeof);
memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
memcpy(lo, tmp, stridehi * wchar.sizeof);
lo += stridehi;
hi -= stridelo;
}
}
return *cast(long*)(&a);
}
unittest
{
wchar[] a = "abcd";
wchar[] r;
r = a.dup.reverse;
assert(r == "dcba");
a = "a\U00012356\U00012346c";
r = a.dup.reverse;
assert(r == "c\U00012346\U00012356a");
a = "ab\U00012345c";
r = a.dup.reverse;
assert(r == "c\U00012345ba");
}
/**********************************************
* Support for array.reverse property.

View file

@ -14,6 +14,9 @@ else
DATAGRP EQU DGROUP
endif
public __nullext
__nullext equ 0
extrn __moduleinfo_array:near
; These segments bracket FM, which contains the list of ModuleInfo pointers

View file

@ -305,3 +305,4 @@ class Error : Exception
}
}
//extern (C) int nullext = 0;

68
internal/qsort2.d Normal file
View file

@ -0,0 +1,68 @@
/*
* Placed into Public Domain
* written by Walter Bright
* www.digitalmars.com
*
* This is a public domain version of qsort.d.
* All it does is call C's qsort(), but runs a little slower since
* it needs to synchronize a global variable.
*/
//debug=qsort;
import std.c.stdlib;
struct Array
{
size_t length;
void *ptr;
}
private TypeInfo tiglobal;
extern (C) int cmp(void* p1, void* p2)
{
return tiglobal.compare(p1, p2);
}
extern (C) long _adSort(Array a, TypeInfo ti)
{
synchronized
{
tiglobal = ti;
std.c.stdlib.qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp);
}
return *cast(long*)(&a);
}
unittest
{
debug(qsort) printf("array.sort.unittest()\n");
int a[] = new int[10];
a[0] = 23;
a[1] = 1;
a[2] = 64;
a[3] = 5;
a[4] = 6;
a[5] = 5;
a[6] = 17;
a[7] = 3;
a[8] = 0;
a[9] = -1;
a.sort;
for (int i = 0; i < a.length - 1; i++)
{
//printf("i = %d", i);
//printf(" %d %d\n", a[i], a[i + 1]);
assert(a[i] <= a[i + 1]);
}
}

View file

@ -37,7 +37,7 @@ test.o : test.d
$(DMD) -c test -g
test : test.o libphobos.a
$(CC) -o $@ test.o libphobos.a -lpthread -g
$(CC) -o $@ test.o libphobos.a -lpthread -lm -g
unittest : unittest.o libphobos.a
$(CC) -o $@ unittest.o libphobos.a -lpthread -lm -g
@ -52,7 +52,7 @@ OBJS= asserterror.o deh2.o switch.o complex.o gcstats.o \
cast.o path.o string.o memset.o math.o mmfile.o \
outbuffer.o ctype.o regexp.o random.o linux.o \
stream.o switcherr.o array.o gc.o \
qsort.o qsort2.o thread.o obj.o utf.o uri.o \
qsort.o thread.o obj.o utf.o uri.o \
crc32.o conv.o arraycast.o errno.o alloca.o cmath2.o \
process.o syserror.o \
socket.o socketstream.o stdarg.o stdio.o format.o \
@ -128,12 +128,13 @@ SRC_INT= \
internal/memset.d internal/arraycast.d internal/aaA.d internal/adi.d \
internal/dmain2.d internal/cast.d internal/qsort.d internal/deh2.d \
internal/cmath2.d internal/obj.d internal/mars.h internal/aApply.d \
internal/object.d internal/trace.d
internal/object.d internal/trace.d internal/qsort2.d
SRC_STD_WIN= std/windows/registry.d \
std/windows/iunknown.d
SRC_STD_C_WIN= std/c/windows/windows.d std/c/windows/com.d
SRC_STD_C_WIN= std/c/windows/windows.d std/c/windows/com.d \
std/c/windows/winsock.d
SRC_STD_C_LINUX= std/c/linux/linux.d std/c/linux/linuxextern.d

View file

@ -2,7 +2,7 @@ Unless otherwise marked within the file, each file in the source
to the Phobos library is under the following license:
/*
* Copyright (C) 2004 by Digital Mars, www.digitalmars.com
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied

View file

@ -251,3 +251,74 @@ extern(C)
void seekdir(DIR* dir, off_t offset);
}
extern(C)
{
private import std.intrinsic;
char* strerror(int errnum);
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, timeval* timeout);
int fcntl(int s, int f, ...);
enum
{
EINTR = 4,
EINPROGRESS = 115,
}
const uint FD_SETSIZE = 1024;
//const uint NFDBITS = 8 * int.sizeof; // DMD 0.110: 8 * (int).sizeof is not an expression
const int NFDBITS = 32;
struct fd_set
{
int[FD_SETSIZE / NFDBITS] fds_bits;
alias fds_bits __fds_bits;
}
int FDELT(int d)
{
return d / NFDBITS;
}
int FDMASK(int d)
{
return 1 << (d % NFDBITS);
}
// Removes.
void FD_CLR(int fd, fd_set* set)
{
btr(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS));
}
// Tests.
int FD_ISSET(int fd, fd_set* set)
{
return bt(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS));
}
// Adds.
void FD_SET(int fd, fd_set* set)
{
bts(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS));
}
// Resets to zero.
void FD_ZERO(fd_set* set)
{
set.fds_bits[] = 0;
}
}

382
std/c/linux/socket.d Normal file
View file

@ -0,0 +1,382 @@
/*
Written by Christopher E. Miller
Placed into public domain.
*/
module std.c.linux.socket;
private import std.stdint;
extern(C):
alias int socklen_t;
const int F_GETFL = 3;
const int F_SETFL = 4;
const int O_NONBLOCK = 0x800;
int socket(int af, int type, int protocol);
int bind(int s, sockaddr* name, int namelen);
int connect(int s, sockaddr* name, int namelen);
int listen(int s, int backlog);
int accept(int s, sockaddr* addr, int* addrlen);
int shutdown(int s, int how);
int getpeername(int s, sockaddr* name, int* namelen);
int getsockname(int s, sockaddr* name, int* namelen);
int send(int s, void* buf, int len, int flags);
int sendto(int s, void* buf, int len, int flags, sockaddr* to, int tolen);
int recv(int s, void* buf, int len, int flags);
int recvfrom(int s, void* buf, int len, int flags, sockaddr* from, int* fromlen);
int getsockopt(int s, int level, int optname, void* optval, int* optlen);
int setsockopt(int s, int level, int optname, void* optval, int optlen);
uint inet_addr(char* cp);
char* inet_ntoa(in_addr ina);
hostent* gethostbyname(char* name);
hostent* gethostbyaddr(void* addr, int len, int type);
protoent* getprotobyname(char* name);
protoent* getprotobynumber(int number);
servent* getservbyname(char* name, char* proto);
servent* getservbyport(int port, char* proto);
int gethostname(char* name, int namelen);
int getaddrinfo(char* nodename, char* servname, addrinfo* hints, addrinfo** res);
void freeaddrinfo(addrinfo* ai);
int getnameinfo(sockaddr* sa, socklen_t salen, char* node, socklen_t nodelen, char* service, socklen_t servicelen, int flags);
enum: int
{
AF_UNSPEC = 0,
AF_UNIX = 1,
AF_INET = 2,
AF_IPX = 4,
AF_APPLETALK = 5,
AF_INET6 = 10,
// ...
PF_UNSPEC = AF_UNSPEC,
PF_UNIX = AF_UNIX,
PF_INET = AF_INET,
PF_IPX = AF_IPX,
PF_APPLETALK = AF_APPLETALK,
PF_INET6 = AF_INET6,
}
version(X86)
{
enum: int
{
SOL_SOCKET = 1,
}
}
else
{
// Different values on other platforms.
static assert(0);
}
enum: int
{
SO_DEBUG = 1,
SO_BROADCAST = 6,
SO_REUSEADDR = 2,
SO_LINGER = 13,
SO_DONTLINGER = ~SO_LINGER,
SO_OOBINLINE = 10,
SO_SNDBUF = 7,
SO_RCVBUF = 8,
SO_ACCEPTCONN = 30,
SO_DONTROUTE = 5,
SO_TYPE = 3,
TCP_NODELAY = 1,
IP_MULTICAST_LOOP = 34,
IP_ADD_MEMBERSHIP = 35,
IP_DROP_MEMBERSHIP = 36,
// ...
IPV6_ADDRFORM = 1,
IPV6_PKTINFO = 2,
IPV6_HOPOPTS = 3,
IPV6_DSTOPTS = 4,
IPV6_RTHDR = 5,
IPV6_PKTOPTIONS = 6,
IPV6_CHECKSUM = 7,
IPV6_HOPLIMIT = 8,
IPV6_NEXTHOP = 9,
IPV6_AUTHHDR = 10,
IPV6_UNICAST_HOPS = 16,
IPV6_MULTICAST_IF = 17,
IPV6_MULTICAST_HOPS = 18,
IPV6_MULTICAST_LOOP = 19,
IPV6_JOIN_GROUP = 20,
IPV6_LEAVE_GROUP = 21,
IPV6_ROUTER_ALERT = 22,
IPV6_MTU_DISCOVER = 23,
IPV6_MTU = 24,
IPV6_RECVERR = 25,
IPV6_V6ONLY = 26,
IPV6_JOIN_ANYCAST = 27,
IPV6_LEAVE_ANYCAST = 28,
IPV6_IPSEC_POLICY = 34,
IPV6_XFRM_POLICY = 35,
}
struct linger
{
int32_t l_onoff;
int32_t l_linger;
}
struct protoent
{
char* p_name;
char** p_aliases;
int32_t p_proto;
}
struct servent
{
char* s_name;
char** s_aliases;
int32_t s_port;
char* s_proto;
}
version(BigEndian)
{
uint16_t htons(uint16_t x)
{
return x;
}
uint32_t htonl(uint32_t x)
{
return x;
}
}
else version(LittleEndian)
{
private import std.intrinsic;
uint16_t htons(uint16_t x)
{
return (x >> 8) | (x << 8);
}
uint32_t htonl(uint32_t x)
{
return bswap(x);
}
}
else
{
static assert(0);
}
uint16_t ntohs(uint16_t x)
{
return htons(x);
}
uint32_t ntohl(uint32_t x)
{
return htonl(x);
}
enum: int
{
SOCK_STREAM = 1,
SOCK_DGRAM = 2,
SOCK_RAW = 3,
SOCK_RDM = 4,
SOCK_SEQPACKET = 5,
}
enum: int
{
IPPROTO_IP = 0,
IPPROTO_ICMP = 1,
IPPROTO_IGMP = 2,
IPPROTO_GGP = 3,
IPPROTO_TCP = 6,
IPPROTO_PUP = 12,
IPPROTO_UDP = 17,
IPPROTO_IDP = 22,
IPPROTO_IPV6 = 41,
IPPROTO_ND = 77,
IPPROTO_RAW = 255,
IPPROTO_MAX = 256,
}
enum: int
{
MSG_OOB = 0x1,
MSG_PEEK = 0x2,
MSG_DONTROUTE = 0x4,
}
enum: int
{
SD_RECEIVE = 0,
SD_SEND = 1,
SD_BOTH = 2,
}
enum: uint
{
INADDR_ANY = 0,
INADDR_LOOPBACK = 0x7F000001,
INADDR_BROADCAST = 0xFFFFFFFF,
INADDR_NONE = 0xFFFFFFFF,
ADDR_ANY = INADDR_ANY,
}
enum: int
{
AI_PASSIVE = 0x1,
AI_CANONNAME = 0x2,
AI_NUMERICHOST = 0x4,
}
union in_addr
{
private union _S_un_t
{
private struct _S_un_b_t
{
uint8_t s_b1, s_b2, s_b3, s_b4;
}
_S_un_b_t S_un_b;
private struct _S_un_w_t
{
uint16_t s_w1, s_w2;
}
_S_un_w_t S_un_w;
uint32_t S_addr;
}
_S_un_t S_un;
uint32_t s_addr;
struct
{
uint8_t s_net, s_host;
union
{
uint16_t s_imp;
struct
{
uint8_t s_lh, s_impno;
}
}
}
}
union in6_addr
{
private union _in6_u_t
{
uint8_t[16] u6_addr8;
uint16_t[8] u6_addr16;
uint32_t[4] u6_addr32;
}
_in6_u_t in6_u;
uint8_t[16] s6_addr8;
uint16_t[8] s6_addr16;
uint32_t[4] s6_addr32;
}
const in6_addr IN6ADDR_ANY = { s6_addr8: [0] };
const in6_addr IN6ADDR_LOOPBACK = { s6_addr8: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] };
//alias IN6ADDR_ANY IN6ADDR_ANY_INIT;
//alias IN6ADDR_LOOPBACK IN6ADDR_LOOPBACK_INIT;
const uint INET_ADDRSTRLEN = 16;
const uint INET6_ADDRSTRLEN = 46;
struct sockaddr
{
int16_t sa_family;
ubyte[14] sa_data;
}
struct sockaddr_in
{
int16_t sin_family = AF_INET;
uint16_t sin_port;
in_addr sin_addr;
ubyte[8] sin_zero;
}
struct sockaddr_in6
{
int16_t sin6_family = AF_INET6;
uint16_t sin6_port;
uint32_t sin6_flowinfo;
in6_addr sin6_addr;
uint32_t sin6_scope_id;
}
struct addrinfo
{
int32_t ai_flags;
int32_t ai_family;
int32_t ai_socktype;
int32_t ai_protocol;
size_t ai_addrlen;
char* ai_canonname;
sockaddr* ai_addr;
addrinfo* ai_next;
}
struct hostent
{
char* h_name;
char** h_aliases;
int32_t h_addrtype;
int32_t h_length;
char** h_addr_list;
char* h_addr()
{
return h_addr_list[0];
}
}

539
std/c/windows/winsock.d Normal file
View file

@ -0,0 +1,539 @@
/*
Written by Christopher E. Miller
Placed into public domain.
*/
module std.c.windows.winsock;
private import std.stdint;
private import std.c.windows.windows;
extern(Windows):
alias UINT SOCKET;
alias int socklen_t;
const SOCKET INVALID_SOCKET = cast(SOCKET)~0;
const int SOCKET_ERROR = -1;
const int WSADESCRIPTION_LEN = 256;
const int WSASYS_STATUS_LEN = 128;
struct WSADATA
{
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN + 1];
char szSystemStatus[WSASYS_STATUS_LEN + 1];
USHORT iMaxSockets;
USHORT iMaxUdpDg;
char* lpVendorInfo;
}
alias WSADATA* LPWSADATA;
const int IOCPARM_MASK = 0x7F;
const int IOC_IN = cast(int)0x80000000;
const int FIONBIO = cast(int)(IOC_IN | ((UINT.sizeof & IOCPARM_MASK) << 16) | (102 << 8) | 126);
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
int WSACleanup();
SOCKET socket(int af, int type, int protocol);
int ioctlsocket(SOCKET s, int cmd, uint* argp);
int bind(SOCKET s, sockaddr* name, int namelen);
int connect(SOCKET s, sockaddr* name, int namelen);
int listen(SOCKET s, int backlog);
SOCKET accept(SOCKET s, sockaddr* addr, int* addrlen);
int closesocket(SOCKET s);
int shutdown(SOCKET s, int how);
int getpeername(SOCKET s, sockaddr* name, int* namelen);
int getsockname(SOCKET s, sockaddr* name, int* namelen);
int send(SOCKET s, void* buf, int len, int flags);
int sendto(SOCKET s, void* buf, int len, int flags, sockaddr* to, int tolen);
int recv(SOCKET s, void* buf, int len, int flags);
int recvfrom(SOCKET s, void* buf, int len, int flags, sockaddr* from, int* fromlen);
int getsockopt(SOCKET s, int level, int optname, void* optval, int* optlen);
int setsockopt(SOCKET s, int level, int optname, void* optval, int optlen);
uint inet_addr(char* cp);
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, timeval* timeout);
char* inet_ntoa(in_addr ina);
hostent* gethostbyname(char* name);
hostent* gethostbyaddr(void* addr, int len, int type);
protoent* getprotobyname(char* name);
protoent* getprotobynumber(int number);
servent* getservbyname(char* name, char* proto);
servent* getservbyport(int port, char* proto);
int gethostname(char* name, int namelen);
int getaddrinfo(char* nodename, char* servname, addrinfo* hints, addrinfo** res);
void freeaddrinfo(addrinfo* ai);
int getnameinfo(sockaddr* sa, socklen_t salen, char* host, DWORD hostlen, char* serv, DWORD servlen, int flags);
enum: int
{
WSAEWOULDBLOCK = 10035,
WSAEINTR = 10004,
WSAHOST_NOT_FOUND = 11001,
}
int WSAGetLastError();
enum: int
{
AF_UNSPEC = 0,
AF_UNIX = 1,
AF_INET = 2,
AF_IMPLINK = 3,
AF_PUP = 4,
AF_CHAOS = 5,
AF_NS = 6,
AF_IPX = AF_NS,
AF_ISO = 7,
AF_OSI = AF_ISO,
AF_ECMA = 8,
AF_DATAKIT = 9,
AF_CCITT = 10,
AF_SNA = 11,
AF_DECnet = 12,
AF_DLI = 13,
AF_LAT = 14,
AF_HYLINK = 15,
AF_APPLETALK = 16,
AF_NETBIOS = 17,
AF_VOICEVIEW = 18,
AF_FIREFOX = 19,
AF_UNKNOWN1 = 20,
AF_BAN = 21,
AF_ATM = 22,
AF_INET6 = 23,
AF_CLUSTER = 24,
AF_12844 = 25,
AF_IRDA = 26,
AF_NETDES = 28,
AF_MAX = 29,
PF_UNSPEC = AF_UNSPEC,
PF_UNIX = AF_UNIX,
PF_INET = AF_INET,
PF_IMPLINK = AF_IMPLINK,
PF_PUP = AF_PUP,
PF_CHAOS = AF_CHAOS,
PF_NS = AF_NS,
PF_IPX = AF_IPX,
PF_ISO = AF_ISO,
PF_OSI = AF_OSI,
PF_ECMA = AF_ECMA,
PF_DATAKIT = AF_DATAKIT,
PF_CCITT = AF_CCITT,
PF_SNA = AF_SNA,
PF_DECnet = AF_DECnet,
PF_DLI = AF_DLI,
PF_LAT = AF_LAT,
PF_HYLINK = AF_HYLINK,
PF_APPLETALK = AF_APPLETALK,
PF_VOICEVIEW = AF_VOICEVIEW,
PF_FIREFOX = AF_FIREFOX,
PF_UNKNOWN1 = AF_UNKNOWN1,
PF_BAN = AF_BAN,
PF_INET6 = AF_INET6,
PF_MAX = AF_MAX,
}
enum: int
{
SOL_SOCKET = 0xFFFF,
}
enum: int
{
SO_DEBUG = 0x0001,
SO_ACCEPTCONN = 0x0002,
SO_REUSEADDR = 0x0004,
SO_KEEPALIVE = 0x0008,
SO_DONTROUTE = 0x0010,
SO_BROADCAST = 0x0020,
SO_USELOOPBACK = 0x0040,
SO_LINGER = 0x0080,
SO_DONTLINGER = ~SO_LINGER,
SO_OOBINLINE = 0x0100,
SO_SNDBUF = 0x1001,
SO_RCVBUF = 0x1002,
SO_SNDLOWAT = 0x1003,
SO_RCVLOWAT = 0x1004,
SO_SNDTIMEO = 0x1005,
SO_RCVTIMEO = 0x1006,
SO_ERROR = 0x1007,
SO_TYPE = 0x1008,
SO_EXCLUSIVEADDRUSE = ~SO_REUSEADDR,
TCP_NODELAY = 1,
IP_MULTICAST_LOOP = 0x4,
IP_ADD_MEMBERSHIP = 0x5,
IP_DROP_MEMBERSHIP = 0x6,
IPV6_UNICAST_HOPS = 4,
IPV6_MULTICAST_IF = 9,
IPV6_MULTICAST_HOPS = 10,
IPV6_MULTICAST_LOOP = 11,
IPV6_ADD_MEMBERSHIP = 12,
IPV6_DROP_MEMBERSHIP = 13,
IPV6_JOIN_GROUP = IPV6_ADD_MEMBERSHIP,
IPV6_LEAVE_GROUP = IPV6_DROP_MEMBERSHIP,
}
const uint FD_SETSIZE = 64;
struct fd_set
{
UINT fd_count;
SOCKET[FD_SETSIZE] fd_array;
}
// Removes.
void FD_CLR(SOCKET fd, fd_set* set)
{
uint c = set.fd_count;
SOCKET* start = set.fd_array.ptr;
SOCKET* stop = start + c;
for(; start != stop; start++)
{
if(*start == fd)
goto found;
}
return; //not found
found:
for(++start; start != stop; start++)
{
*(start - 1) = *start;
}
set.fd_count = c - 1;
}
// Tests.
int FD_ISSET(SOCKET fd, fd_set* set)
{
SOCKET* start = set.fd_array.ptr;
SOCKET* stop = start + set.fd_count;
for(; start != stop; start++)
{
if(*start == fd)
return true;
}
return false;
}
// Adds.
void FD_SET(SOCKET fd, fd_set* set)
{
uint c = set.fd_count;
set.fd_array.ptr[c] = fd;
set.fd_count = c + 1;
}
// Resets to zero.
void FD_ZERO(fd_set* set)
{
set.fd_count = 0;
}
struct linger
{
USHORT l_onoff;
USHORT l_linger;
}
struct protoent
{
char* p_name;
char** p_aliases;
SHORT p_proto;
}
struct servent
{
char* s_name;
char** s_aliases;
SHORT s_port;
char* s_proto;
}
/+
union in6_addr
{
private union _u_t
{
BYTE[16] Byte;
WORD[8] Word;
}
_u_t u;
}
struct in_addr6
{
BYTE[16] s6_addr;
}
+/
version(BigEndian)
{
uint16_t htons(uint16_t x)
{
return x;
}
uint32_t htonl(uint32_t x)
{
return x;
}
}
else version(LittleEndian)
{
private import std.intrinsic;
uint16_t htons(uint16_t x)
{
return (x >> 8) | (x << 8);
}
uint32_t htonl(uint32_t x)
{
return bswap(x);
}
}
else
{
static assert(0);
}
uint16_t ntohs(uint16_t x)
{
return htons(x);
}
uint32_t ntohl(uint32_t x)
{
return htonl(x);
}
enum: int
{
SOCK_STREAM = 1,
SOCK_DGRAM = 2,
SOCK_RAW = 3,
SOCK_RDM = 4,
SOCK_SEQPACKET = 5,
}
enum: int
{
IPPROTO_IP = 0,
IPPROTO_ICMP = 1,
IPPROTO_IGMP = 2,
IPPROTO_GGP = 3,
IPPROTO_TCP = 6,
IPPROTO_PUP = 12,
IPPROTO_UDP = 17,
IPPROTO_IDP = 22,
IPPROTO_IPV6 = 41,
IPPROTO_ND = 77,
IPPROTO_RAW = 255,
IPPROTO_MAX = 256,
}
enum: int
{
MSG_OOB = 0x1,
MSG_PEEK = 0x2,
MSG_DONTROUTE = 0x4,
}
enum: int
{
SD_RECEIVE = 0,
SD_SEND = 1,
SD_BOTH = 2,
}
enum: uint
{
INADDR_ANY = 0,
INADDR_LOOPBACK = 0x7F000001,
INADDR_BROADCAST = 0xFFFFFFFF,
INADDR_NONE = 0xFFFFFFFF,
ADDR_ANY = INADDR_ANY,
}
enum: int
{
AI_PASSIVE = 0x1,
AI_CANONNAME = 0x2,
AI_NUMERICHOST = 0x4,
}
struct timeval
{
int32_t tv_sec;
int32_t tv_usec;
}
union in_addr
{
private union _S_un_t
{
private struct _S_un_b_t
{
uint8_t s_b1, s_b2, s_b3, s_b4;
}
_S_un_b_t S_un_b;
private struct _S_un_w_t
{
uint16_t s_w1, s_w2;
}
_S_un_w_t S_un_w;
uint32_t S_addr;
}
_S_un_t S_un;
uint32_t s_addr;
struct
{
uint8_t s_net, s_host;
union
{
uint16_t s_imp;
struct
{
uint8_t s_lh, s_impno;
}
}
}
}
union in6_addr
{
private union _in6_u_t
{
uint8_t[16] u6_addr8;
uint16_t[8] u6_addr16;
uint32_t[4] u6_addr32;
}
_in6_u_t in6_u;
uint8_t[16] s6_addr8;
uint16_t[8] s6_addr16;
uint32_t[4] s6_addr32;
alias s6_addr8 s6_addr;
}
const in6_addr IN6ADDR_ANY = { s6_addr8: [0] };
const in6_addr IN6ADDR_LOOPBACK = { s6_addr8: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] };
//alias IN6ADDR_ANY IN6ADDR_ANY_INIT;
//alias IN6ADDR_LOOPBACK IN6ADDR_LOOPBACK_INIT;
const uint INET_ADDRSTRLEN = 16;
const uint INET6_ADDRSTRLEN = 46;
struct sockaddr
{
int16_t sa_family;
ubyte[14] sa_data;
}
struct sockaddr_in
{
int16_t sin_family = AF_INET;
uint16_t sin_port;
in_addr sin_addr;
ubyte[8] sin_zero;
}
struct sockaddr_in6
{
int16_t sin6_family = AF_INET6;
uint16_t sin6_port;
uint32_t sin6_flowinfo;
in6_addr sin6_addr;
uint32_t sin6_scope_id;
}
struct addrinfo
{
int32_t ai_flags;
int32_t ai_family;
int32_t ai_socktype;
int32_t ai_protocol;
size_t ai_addrlen;
char* ai_canonname;
sockaddr* ai_addr;
addrinfo* ai_next;
}
struct hostent
{
char* h_name;
char** h_aliases;
int16_t h_addrtype;
int16_t h_length;
char** h_addr_list;
char* h_addr()
{
return h_addr_list[0];
}
}

View file

@ -1,8 +1,26 @@
// Written by Walter Bright
// Copyright (c) 2001-2004 Digital Mars
// All Rights Reserved
// www.digitalmars.com
/*
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
// Simple ASCII char classification functions

View file

@ -731,7 +731,14 @@ unittest
assert(s == "hello world! true 57 1000000000x foo");
s = std.string.format(1.67, " %A ", -1.28, float.nan);
assert(s == "1.67 -0X1.47AE147AE147BP+0 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
assert(s == "1.67 -0X1.47AE147AE147BP+0 nan");
s = std.string.format("%x %X", 0x1234AF, 0xAFAFAFAF);
assert(s == "1234af AFAFAFAF");

View file

@ -102,7 +102,8 @@ void _moduleCtor2(ModuleInfo[] mi, int skip)
ModuleInfo m = mi[i];
debug printf("\tmodule[%d] = '%p'\n", i, m);
if (!m) continue;
if (!m)
continue;
debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
if (m.flags & MIctordone)
continue;
@ -171,6 +172,9 @@ extern (C) void _moduleUnitTests()
{
ModuleInfo m = _moduleinfo_array[i];
if (!m)
continue;
debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
if (m.unitTest)
{

View file

@ -2,7 +2,7 @@
// Regular Expressions
/*
* Copyright (C) 2000-2004 by Digital Mars, www.digitalmars.com
* Copyright (C) 2000-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
@ -117,9 +117,9 @@ class RegExp
private:
uint src; // current source index in input[]
uint src_start; // starting index for match in input[]
uint p; // position of parser in pattern[]
size_t src; // current source index in input[]
size_t src_start; // starting index for match in input[]
size_t p; // position of parser in pattern[]
regmatch_t gmatch; // match for the entire regular expression
// (serves as storage for pmatch[0])
@ -138,8 +138,8 @@ enum : ubyte
REend, // end of program
REchar, // single character
REichar, // single character, case insensitive
REwchar, // single wide character
REiwchar, // single wide character, case insensitive
REdchar, // single UCS character
REidchar, // single wide character, case insensitive
REanychar, // any character
REanystar, // ".*"
REstring, // string of characters
@ -172,7 +172,7 @@ enum : ubyte
};
// BUG: should this include '$'?
private int isword(rchar c) { return isalnum(c) || c == '_'; }
private int isword(dchar c) { return isalnum(c) || c == '_'; }
private uint inf = ~0u;
@ -185,10 +185,10 @@ public void compile(rchar[] pattern, rchar[] attributes)
//printf("RegExp.compile('%.*s', '%.*s')\n", pattern, attributes);
this.attributes = 0;
for (uint i = 0; i < attributes.length; i++)
foreach (rchar c; attributes)
{ REA att;
switch (attributes[i])
switch (c)
{
case 'g': att = REA.global; break;
case 'i': att = REA.ignoreCase; break;
@ -236,7 +236,8 @@ public void compile(rchar[] pattern, rchar[] attributes)
}
/********************************************
* Split string[] into an array of strings, using the regular expression as the separator.
* Split string[] into an array of strings, using the regular
* expression as the separator.
* Returns:
* array of slices into string[]
*/
@ -341,7 +342,7 @@ unittest
* -1 no match
*/
public int search(rchar[] string)
public int find(rchar[] string)
{
int i;
@ -353,15 +354,17 @@ public int search(rchar[] string)
return i;
}
deprecated alias find search;
unittest
{
debug(regexp) printf("regexp.search.unittest()\n");
debug(regexp) printf("regexp.find.unittest()\n");
int i;
RegExp r = new RegExp("abc", null);
i = r.search("xabcy");
i = r.find("xabcy");
assert(i == 1);
i = r.search("cba");
i = r.find("cba");
assert(i == -1);
}
@ -553,7 +556,7 @@ public int test()
public int test(char[] string, int startindex)
{
rchar firstc;
char firstc;
uint si;
input = string;
@ -564,7 +567,7 @@ public int test(char[] string, int startindex)
{
return 0; // fail
}
debug(regexp) printProgram(program);
//debug(regexp) printProgram(program);
// First character optimization
firstc = 0;
@ -598,7 +601,7 @@ public int test(char[] string, int startindex)
{
pmatch[0].rm_so = si;
pmatch[0].rm_eo = src;
debug(regexp) printf("start = %d, end = %d\n", gmatch.rm_so, gmatch.rm_eo);
//debug(regexp) printf("start = %d, end = %d\n", gmatch.rm_so, gmatch.rm_eo);
return 1;
}
// If possible match must start at beginning, we are done
@ -615,7 +618,7 @@ public int test(char[] string, int startindex)
}
if (si == input.length)
break;
debug(regexp) printf("Starting new try: '%.*s'\n", input[si + 1 .. input.length]);
//debug(regexp) printf("Starting new try: '%.*s'\n", input[si + 1 .. input.length]);
}
return 0; // no match
}
@ -633,7 +636,7 @@ int chr(inout uint si, rchar c)
void printProgram(ubyte[] prog)
{
debug(regexp)
//debug(regexp)
{
uint pc;
uint len;
@ -660,14 +663,14 @@ void printProgram(ubyte[] prog)
pc += 1 + char.sizeof;
break;
case REwchar:
printf("\tREwchar '%c'\n", *cast(wchar *)&prog[pc + 1]);
pc += 1 + wchar.sizeof;
case REdchar:
printf("\tREdchar '%c'\n", *cast(dchar *)&prog[pc + 1]);
pc += 1 + dchar.sizeof;
break;
case REiwchar:
printf("\tREiwchar '%c'\n", *cast(wchar *)&prog[pc + 1]);
pc += 1 + wchar.sizeof;
case REidchar:
printf("\tREidchar '%c'\n", *cast(dchar *)&prog[pc + 1]);
pc += 1 + dchar.sizeof;
break;
case REanychar:
@ -898,21 +901,21 @@ int trymatch(int pc, int pcend)
pc += 1 + char.sizeof;
break;
case REwchar:
debug(regexp) printf("\tREwchar '%c', src = '%c'\n", *(cast(wchar *)&program[pc + 1]), input[src]);
case REdchar:
debug(regexp) printf("\tREdchar '%c', src = '%c'\n", *(cast(dchar *)&program[pc + 1]), input[src]);
if (src == input.length)
goto Lnomatch;
if (*(cast(wchar *)&program[pc + 1]) != input[src])
if (*(cast(dchar *)&program[pc + 1]) != input[src])
goto Lnomatch;
src++;
pc += 1 + wchar.sizeof;
pc += 1 + dchar.sizeof;
break;
case REiwchar:
debug(regexp) printf("\tREiwchar '%c', src = '%c'\n", *(cast(wchar *)&program[pc + 1]), input[src]);
case REidchar:
debug(regexp) printf("\tREidchar '%c', src = '%c'\n", *(cast(dchar *)&program[pc + 1]), input[src]);
if (src == input.length)
goto Lnomatch;
c1 = *(cast(wchar *)&program[pc + 1]);
c1 = *(cast(dchar *)&program[pc + 1]);
c2 = input[src];
if (c1 != c2)
{
@ -924,7 +927,7 @@ int trymatch(int pc, int pcend)
goto Lnomatch;
}
src++;
pc += 1 + wchar.sizeof;
pc += 1 + dchar.sizeof;
break;
case REanychar:
@ -1479,7 +1482,7 @@ int parsePiece()
p++;
if (p == plength)
goto Lerr;
if (pattern[p] == '}') // {n,}
if (pattern[p] == /*{*/ '}') // {n,}
{ m = inf;
goto Lnm;
}
@ -1494,7 +1497,7 @@ int parsePiece()
if (p == plength)
goto Lerr;
} while (isdigit(pattern[p]));
if (pattern[p] != '}')
if (pattern[p] != /*{*/ '}')
goto Lerr;
goto Lnm;
@ -1694,10 +1697,10 @@ int parseAtom()
break;
}
}
if (c & ~0xFF)
if (c >= 0x80)
{
// Convert to wchar opcode
op = (op == REchar) ? REwchar : REiwchar;
// Convert to dchar opcode
op = (op == REchar) ? REdchar : REidchar;
buf.write(op);
buf.write(c);
}
@ -1927,7 +1930,7 @@ int parseRange()
(cast(ushort *)&buf.data[offset])[1] = cast(ushort)r.maxb;
if (attributes & REA.ignoreCase)
{
// BUG: what about wchar?
// BUG: what about dchar?
r.setbitmax(0x7F);
for (c = 'a'; c <= 'z'; c++)
{
@ -1981,7 +1984,7 @@ body
if (p == pattern.length)
goto Lretc;
c = pattern[p];
// Note: we are deliberately not allowing wchar letters
// Note: we are deliberately not allowing dchar letters
if (!(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')))
{
Lcerr:
@ -2095,8 +2098,8 @@ void optimize()
case REeol:
case REchar:
case REichar:
case REwchar:
case REiwchar:
case REdchar:
case REidchar:
case REstring:
case REistring:
case REtestbit:
@ -2184,8 +2187,8 @@ int starrchars(Range r, ubyte[] prog)
}
return 1;
case REwchar:
case REiwchar:
case REdchar:
case REidchar:
return 1;
case REanychar:
@ -2503,3 +2506,196 @@ private static rchar[] replace3(rchar[] format, rchar[] input, regmatch_t[] pmat
}
/****************************************************
* Search str for regular expression pattern.
* If match, return a RegExp for the match.
* If no match, return null.
*/
RegExp search(char[] str, char[] pattern, char[] attributes = null)
{
RegExp r = new RegExp(pattern, attributes);
if (r.test(str))
{
}
else
{ delete r;
r = null;
}
return r;
}
/******************************************************
* Search str for pattern, replace occurrences with format.
*/
char[] sub(char[] str, char[] pattern, char[] format, char[] attributes = null)
{
RegExp r = new RegExp(pattern, attributes);
char[] result = r.replace(str, format);
delete r;
return result;
}
unittest
{
debug(regexp) printf("regexp.sub.unittest\n");
char[] r = sub("hello", "ll", "ss");
assert(r == "hesso");
}
/*******************************************************
* Search str for pattern, replace occurrences with string
* returned from dg.
*/
char[] sub(char[] str, char[] pattern, char[] delegate(RegExp) dg, char[] attributes = null)
{
RegExp r = new RegExp(pattern, attributes);
rchar[] result;
int lastindex;
int offset;
result = str;
lastindex = 0;
offset = 0;
while (r.test(str, lastindex))
{
int so = r.pmatch[0].rm_so;
int eo = r.pmatch[0].rm_eo;
rchar[] replacement = dg(r);
result = replaceSlice(result, result[offset + so .. offset + eo], replacement);
if (r.attributes & RegExp.REA.global)
{
offset += replacement.length - (eo - so);
if (lastindex == eo)
lastindex++; // always consume some source
else
lastindex = eo;
}
else
break;
}
delete r;
return result;
}
unittest
{
debug(regexp) printf("regexp.sub.unittest\n");
char[] foo(RegExp r) { return "ss"; }
char[] r = sub("hello", "ll", delegate char[](RegExp r) { return "ss"; });
assert(r == "hesso");
}
/*************************************************
* Search string[] for match with pattern[].
* Returns:
* >=0 index of match
* -1 no match
*/
int find(rchar[] string, char[] pattern, char[] attributes = null)
{
int i = -1;
RegExp r = new RegExp(pattern, attributes);
if (r.test(string))
{
i = r.pmatch[0].rm_so;
}
delete r;
return i;
}
unittest
{
debug(regexp) printf("regexp.find.unittest\n");
int i;
i = find("xabcy", "abc");
assert(i == 1);
i = find("cba", "abc");
assert(i == -1);
}
/*************************************************
* Search string[] for last match with pattern[].
* Returns:
* >=0 index of match
* -1 no match
*/
int rfind(rchar[] string, char[] pattern, char[] attributes = null)
{
int i = -1;
int lastindex = 0;
RegExp r = new RegExp(pattern, attributes);
while (r.test(string, lastindex))
{ int eo = r.pmatch[0].rm_eo;
i = r.pmatch[0].rm_so;
if (lastindex == eo)
lastindex++; // always consume some source
else
lastindex = eo;
}
delete r;
return i;
}
unittest
{
int i;
debug(regexp) printf("regexp.rfind.unittest\n");
i = rfind("abcdefcdef", "c");
assert(i == 6);
i = rfind("abcdefcdef", "cd");
assert(i == 6);
i = rfind("abcdefcdef", "x");
assert(i == -1);
i = rfind("abcdefcdef", "xy");
assert(i == -1);
i = rfind("abcdefcdef", "");
assert(i == 10);
}
/********************************************
* Split string[] into an array of strings, using the regular
* expression as the separator.
* Returns:
* array of slices into string[]
*/
char[][] split(char[] string, char[] pattern, char[] attributes = null)
{
RegExp r = new RegExp(pattern, attributes);
char[][] result = r.split(string);
delete r;
return result;
}
unittest
{
debug(regexp) printf("regexp.split.unittest()\n");
char[][] result;
result = split("ab", "a*");
assert(result.length == 2);
assert(result[0] == "");
assert(result[1] == "b");
}

File diff suppressed because it is too large Load diff

View file

@ -893,33 +893,66 @@ unittest
/********************************************
* Capitalize first character of string.
* Capitalize first character of string, convert rest of string
* to lower case.
*/
char[] capitalize(char[] s)
{
if (s.length)
{
char c = s[0];
if ('a' <= c && c <= 'z')
{ char[] r = new char[s.length];
r[] = s;
s = r;
s[0] = c - (cast(char)'a' - 'A');
int changed;
int i;
char[] r = s;
changed = 0;
foreach (size_t i, dchar c; s)
{ dchar c2;
if (i == 0)
{
c2 = std.uni.toUniUpper(c);
if (c != c2)
{
changed = 1;
r = null;
}
}
else
{
c2 = std.uni.toUniLower(c);
if (c != c2)
{
if (!changed)
{ changed = 1;
r = s[0 .. i].dup;
}
}
}
if (changed)
std.utf.encode(r, c2);
}
return s;
return r;
}
unittest
{
debug(string) printf("string.capitalize.unittest\n");
debug(string) printf("string.toupper.capitalize\n");
char[] s1 = "foL";
char[] s1 = "FoL";
char[] s2;
s2 = capitalize(s1);
assert(cmp(s2, "FoL") == 0);
assert(cmp(s2, "Fol") == 0);
assert(s2 !== s1);
s2 = capitalize(s1[0 .. 2]);
assert(cmp(s2, "Fo") == 0);
assert(s2.ptr == s1.ptr);
s1 = "fOl";
s2 = capitalize(s1);
assert(cmp(s2, "Fol") == 0);
assert(s2 !== s1);
}
@ -951,7 +984,7 @@ char[] capwords(char[] s)
case '\v':
if (inword)
{
r ~= s[istart .. i];
r ~= capitalize(s[istart .. i]);
inword = 0;
}
break;
@ -969,35 +1002,7 @@ char[] capwords(char[] s)
}
if (inword)
{
r ~= s[istart .. i];
}
// Go back through r and capitalize the words
inword = 0;
for (i = 0; i < r.length; i++)
{
char c = r[i];
if (c >= 'A' && c <= 'Z')
{
if (inword == 1)
{
c += cast(char)'a' - 'A';
r[i] = c;
}
inword = 1;
}
else if (c >= 'a' && c <= 'z')
{
if (inword == 0)
{
c -= cast(char)'a' - 'A';
r[i] = c;
}
inword = 1;
}
else
inword = 0;
r ~= capitalize(s[istart .. i]);
}
return r;
@ -1012,8 +1017,51 @@ unittest
char[] s2;
s2 = capwords(s1);
//printf("s2 = '%.*s'\n", s2);
assert(cmp(s2, "Foo Abc(Ad)* (Q Ptt") == 0);
//writefln("s2 = '%s'", s2);
assert(cmp(s2, "Foo Abc(ad)* (q Ptt") == 0);
}
/********************************************
* Return a string that consists of s[] repeated n times.
*/
char[] repeat(char[] s, size_t n)
{
if (n == 0)
return null;
if (n == 1)
return s;
char[] r = new char[n * s.length];
if (s.length == 1)
r[] = s[0];
else
{ size_t len = s.length;
for (size_t i = 0; i < n * len; i += len)
{
r[i .. i + len] = s[];
}
}
return r;
}
unittest
{
debug(string) printf("string.repeat.unittest\n");
char[] s;
s = repeat("1234", 0);
assert(s is null);
s = repeat("1234", 1);
assert(cmp(s, "1234") == 0);
s = repeat("1234", 2);
assert(cmp(s, "12341234") == 0);
s = repeat("1", 4);
assert(cmp(s, "1111") == 0);
s = repeat(null, 4);
assert(s is null);
}
@ -1433,6 +1481,7 @@ char[] strip(char[] s)
unittest
{
debug(string) printf("string.strip.unittest\n");
char[] s;
int i;
@ -1441,6 +1490,117 @@ unittest
assert(i == 0);
}
/*******************************************
* Returns s[] sans trailing delimiter[], if any.
* If delimiter[] is null, removes trailing CR, LF, or CRLF, if any.
*/
char[] chomp(char[] s, char[] delimiter = null)
{
if (delimiter is null)
{ size_t len = s.length;
if (len)
{ char c = s[len - 1];
if (c == '\r') // if ends in CR
len--;
else if (c == '\n') // if ends in LF
{
len--;
if (len && s[len - 1] == '\r')
len--; // remove CR-LF
}
}
return s[0 .. len];
}
else if (s.length >= delimiter.length)
{
if (s[length - delimiter.length .. length] == delimiter)
return s[0 .. length - delimiter.length];
}
return s;
}
unittest
{
debug(string) printf("string.chomp.unittest\n");
char[] s;
s = chomp(null);
assert(s is null);
s = chomp("hello");
assert(s == "hello");
s = chomp("hello\n");
assert(s == "hello");
s = chomp("hello\r");
assert(s == "hello");
s = chomp("hello\r\n");
assert(s == "hello");
s = chomp("hello\n\r");
assert(s == "hello\n");
s = chomp("hello\n\n");
assert(s == "hello\n");
s = chomp("hello\r\r");
assert(s == "hello\r");
s = chomp("hello\nxxx\n");
assert(s == "hello\nxxx");
s = chomp(null, null);
assert(s is null);
s = chomp("hello", "o");
assert(s == "hell");
s = chomp("hello", "p");
assert(s == "hello");
s = chomp("hello", null);
assert(s == "hello");
s = chomp("hello", "llo");
assert(s == "he");
}
/***********************************************
* Returns s[] sans trailing character, if there is one.
* If last two characters are CR-LF, then both are removed.
*/
char[] chop(char[] s)
{ size_t len = s.length;
if (len)
{
if (len >= 2 && s[len - 1] == '\n' && s[len - 2] == '\r')
return s[0 .. len - 2];
// If we're in a tail of a UTF-8 sequence, back up
while ((s[len - 1] & 0xC0) == 0x80)
{
len--;
if (len == 0)
throw new std.utf.UtfError("invalid UTF sequence", 0);
}
return s[0 .. len - 1];
}
return s;
}
unittest
{
debug(string) printf("string.chop.unittest\n");
char[] s;
s = chop(null);
assert(s is null);
s = chop("hello");
assert(s == "hell");
s = chop("hello\r\n");
assert(s == "hello");
s = chop("hello\n\r");
assert(s == "hello\n");
}
/*******************************************
* Left justify, right justify, or center string
@ -1658,9 +1818,9 @@ unittest
* Count up all instances of sub[] in s[].
*/
int count(char[] s, char[] sub)
size_t count(char[] s, char[] sub)
{
int i;
size_t i;
int j;
int count = 0;
@ -1748,19 +1908,29 @@ unittest
/************************************
* Construct translation table for translate().
* BUG: only works with ASCII
*/
char[] maketrans(char[] from, char[] to)
in
{
assert(from.length == to.length);
assert(from.length <= 128);
foreach (char c; from)
{
assert(c <= 0x7F);
}
foreach (char c; to)
{
assert(c <= 0x7F);
}
}
body
{
char[] t = new char[256];
int i;
for (i = 0; i < 256; i++)
for (i = 0; i < t.length; i++)
t[i] = cast(char)i;
for (i = 0; i < from.length; i++)
@ -1772,6 +1942,7 @@ char[] maketrans(char[] from, char[] to)
/******************************************
* Translate characters in s[] using table created by maketrans().
* Delete chars in delchars[].
* BUG: only works with ASCII
*/
char[] translate(char[] s, char[] transtab, char[] delchars)
@ -1782,29 +1953,27 @@ char[] translate(char[] s, char[] transtab, char[] delchars)
body
{
char[] r;
int i;
int count;
bit[256] deltab;
deltab[] = false;
for (i = 0; i < delchars.length; i++)
foreach (char c; delchars)
{
deltab[delchars[i]] = true;
deltab[c] = true;
}
count = 0;
for (i = 0; i < s.length; i++)
foreach (char c; s)
{
if (!deltab[s[i]])
if (!deltab[c])
count++;
//printf("s[%d] = '%c', count = %d\n", i, s[i], count);
}
r = new char[count];
count = 0;
for (i = 0; i < s.length; i++)
{ char c = s[i];
foreach (char c; s)
{
if (!deltab[c])
{
r[count] = transtab[c];
@ -2294,3 +2463,477 @@ unittest
assert(i == 0);
}
/***********************************************
* See if character c is in the pattern.
*/
int inPattern(dchar c, char[] pattern)
{
int result = 0;
int range = 0;
dchar lastc;
foreach (size_t i, dchar p; pattern)
{
if (p == '^' && i == 0)
{ result = 1;
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 ^ 1;
}
else if (p == '-' && i > result && i + 1 < pattern.length)
{
range = 1;
continue;
}
else if (c == p)
return result ^ 1;
lastc = p;
}
return result;
}
unittest
{
debug(string) printf("std.string.inPattern.unittest\n");
int i;
i = inPattern('x', "x");
assert(i == 1);
i = inPattern('x', "y");
assert(i == 0);
i = inPattern('x', cast(char[])null);
assert(i == 0);
i = inPattern('x', "^y");
assert(i == 1);
i = inPattern('x', "yxxy");
assert(i == 1);
i = inPattern('x', "^yxxy");
assert(i == 0);
i = inPattern('x', "^abcd");
assert(i == 1);
i = inPattern('^', "^^");
assert(i == 0);
i = inPattern('^', "^");
assert(i == 1);
i = inPattern('^', "a^");
assert(i == 1);
i = inPattern('x', "a-z");
assert(i == 1);
i = inPattern('x', "A-Z");
assert(i == 0);
i = inPattern('x', "^a-z");
assert(i == 0);
i = inPattern('x', "^A-Z");
assert(i == 1);
i = inPattern('-', "a-");
assert(i == 1);
i = inPattern('-', "^A-");
assert(i == 0);
i = inPattern('a', "z-a");
assert(i == 1);
i = inPattern('z', "z-a");
assert(i == 1);
i = inPattern('x', "z-a");
assert(i == 0);
}
/***********************************************
* See if character c is in the intersection of the patterns.
*/
int inPattern(dchar c, char[][] patterns)
{ int result;
foreach (char[] pattern; patterns)
{
if (!inPattern(c, pattern))
{ result = 0;
break;
}
result = 1;
}
return result;
}
/********************************************
* Count characters in s that match pattern.
*/
size_t countchars(char[] s, char[] pattern)
{
size_t count;
foreach (dchar c; s)
{
count += inPattern(c, pattern);
}
return count;
}
unittest
{
debug(string) printf("std.string.count.unittest\n");
size_t c;
c = countchars("abc", "a-c");
assert(c == 3);
c = countchars("hello world", "or");
assert(c == 3);
}
/********************************************
* Return string that is s with all characters removed that match pattern.
*/
char[] removechars(char[] s, char[] pattern)
{
char[] r = s;
int changed;
size_t j;
foreach (size_t i, dchar c; s)
{
if (!inPattern(c, pattern))
{
if (changed)
{
if (r is s)
r = s[0 .. j].dup;
std.utf.encode(r, c);
}
}
else if (!changed)
{ changed = 1;
j = i;
}
}
if (changed && r is s)
r = s[0 .. j].dup;
return r;
}
unittest
{
debug(string) printf("std.string.remove.unittest\n");
char[] r;
r = removechars("abc", "a-c");
assert(r is null);
r = removechars("hello world", "or");
assert(r == "hell wld");
r = removechars("hello world", "d");
assert(r == "hello worl");
}
/***************************************************
* Return string where sequences of a character from pattern
* are replaced with a single instance of that character.
* If pattern is null, it defaults to all characters.
*/
char[] squeeze(char[] s, char[] pattern = null)
{
char[] r = s;
dchar lastc;
size_t lasti;
int run;
int changed;
foreach (size_t i, dchar c; s)
{
if (run && lastc == c)
{
changed = 1;
}
else if (pattern is null || inPattern(c, pattern))
{
run = 1;
if (changed)
{ if (r is s)
r = s[0 .. lasti].dup;
std.utf.encode(r, c);
}
else
lasti = i + std.utf.stride(s, i);
lastc = c;
}
else
{
run = 0;
if (changed)
{ if (r is s)
r = s[0 .. lasti].dup;
std.utf.encode(r, c);
}
}
}
if (changed)
{
if (r is s)
r = s[0 .. lasti];
}
return r;
}
unittest
{
debug(string) printf("std.string.squeeze.unittest\n");
char[] s,r;
r = squeeze("hello");
//writefln("r = '%s'", r);
assert(r == "helo");
s = "abcd";
r = squeeze(s);
assert(r is s);
s = "xyzz";
r = squeeze(s);
assert(r.ptr == s.ptr); // should just be a slice
r = squeeze("hello goodbyee", "oe");
assert(r == "hello godbye");
}
/**********************************************
* Return string that is the 'successor' to s.
* If the rightmost character is a-zA-Z0-9, it is incremented within
* its case or digits. If it generates a carry, the process is
* repeated with the one to its immediate left.
*/
char[] succ(char[] s)
{
if (s.length && isalnum(s[length - 1]))
{
char[] r = s.dup;
size_t i = r.length - 1;
while (1)
{ dchar c = s[i];
dchar carry;
switch (c)
{
case '9':
c = '0';
carry = '1';
goto Lcarry;
case 'z':
case 'Z':
c -= 'Z' - 'A';
carry = c;
Lcarry:
r[i] = c;
if (i == 0)
{
char[] t = new char[r.length + 1];
t[0] = carry;
t[1 .. length] = r[];
return t;
}
i--;
break;
default:
if (std.ctype.isalnum(c))
r[i]++;
return r;
}
}
}
return s;
}
unittest
{
debug(string) printf("std.string.succ.unittest\n");
char[] r;
r = succ(null);
assert(r is null);
r = succ("!@#$%");
assert(r == "!@#$%");
r = succ("1");
assert(r == "2");
r = succ("9");
assert(r == "10");
r = succ("999");
assert(r == "1000");
r = succ("zz99");
assert(r == "aaa00");
}
/***********************************************
* Translate characters in from[] to characters in to[].
*/
char[] tr(char[] str, char[] from, char[] to, char[] modifiers = null)
{
int mod_c;
int mod_d;
int mod_s;
foreach (char c; modifiers)
{
switch (c)
{
case 'c': mod_c = 1; break; // complement
case 'd': mod_d = 1; break; // delete unreplaced chars
case 's': mod_s = 1; break; // squeeze duplicated replaced chars
}
}
if (to is null && !mod_d)
to = from;
char[] result = new char[str.length];
result.length = 0;
int m;
dchar lastc;
foreach (dchar c; str)
{ dchar lastf;
dchar lastt;
dchar newc;
int n = 0;
for (size_t i = 0; i < from.length; )
{
dchar f = std.utf.decode(from, i);
//writefln("\tf = '%s', c = '%s', lastf = '%x', '%x', i = %d, %d", f, c, lastf, dchar.init, i, from.length);
if (f == '-' && lastf != dchar.init && i < from.length)
{
dchar nextf = std.utf.decode(from, i);
//writefln("\tlastf = '%s', c = '%s', nextf = '%s'", lastf, c, nextf);
if (lastf <= c && c <= nextf)
{
n += c - lastf - 1;
if (mod_c)
goto Lnotfound;
goto Lfound;
}
n += nextf - lastf;
lastf = lastf.init;
continue;
}
if (c == f)
{ if (mod_c)
goto Lnotfound;
goto Lfound;
}
lastf = f;
n++;
}
if (!mod_c)
goto Lnotfound;
n = 0; // consider it 'found' at position 0
Lfound:
// Find the nth character in to[]
//writefln("\tc = '%s', n = %d", c, n);
dchar nextt;
for (size_t i = 0; i < to.length; )
{ dchar t = std.utf.decode(to, i);
if (t == '-' && lastt != dchar.init && i < to.length)
{
nextt = std.utf.decode(to, i);
//writefln("\tlastt = '%s', c = '%s', nextt = '%s', n = %d", lastt, c, nextt, n);
n -= nextt - lastt;
if (n < 0)
{
newc = nextt + n + 1;
goto Lnewc;
}
lastt = dchar.init;
continue;
}
if (n == 0)
{ newc = t;
goto Lnewc;
}
lastt = t;
nextt = t;
n--;
}
if (mod_d)
continue;
newc = nextt;
Lnewc:
if (mod_s && m && newc == lastc)
continue;
std.utf.encode(result, newc);
m = 1;
lastc = newc;
continue;
Lnotfound:
std.utf.encode(result, c);
lastc = c;
m = 0;
}
return result;
}
unittest
{
debug(string) printf("std.string.tr.unittest\n");
char[] r;
//writefln("r = '%s'", r);
r = tr("abcdef", "cd", "CD");
assert(r == "abCDef");
r = tr("abcdef", "b-d", "B-D");
assert(r == "aBCDef");
r = tr("abcdefgh", "b-dh", "B-Dx");
assert(r == "aBCDefgx");
r = tr("abcdefgh", "b-dh", "B-CDx");
assert(r == "aBCDefgx");
r = tr("abcdefgh", "b-dh", "B-BCDx");
assert(r == "aBCDefgx");
r = tr("abcdef", "ef", "*", "c");
assert(r == "****ef");
r = tr("abcdef", "ef", "", "d");
assert(r == "abcd");
r = tr("hello goodbye", "lo", null, "s");
assert(r == "helo godbye");
r = tr("hello goodbye", "lo", "x", "s");
assert(r == "hex gxdbye");
r = tr("14-Jul-87", "a-zA-Z", " ", "cs");
assert(r == " Jul ");
r = tr("Abc", "AAA", "XYZ");
assert(r == "Xbc");
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2000-2004 by Digital Mars, www.digitalmars.com
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
@ -8,7 +8,8 @@
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
@ -20,7 +21,6 @@
* distribution.
*/
module std.uri;
//debug=uri; // uncomment to turn on debugging printf's

View file

@ -327,6 +327,7 @@ unittest
catch (UtfError u)
{
i = 23;
delete u;
}
assert(i == 23);
}

View file

@ -1,8 +1,26 @@
// Copyright (c) 1999-2003 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
/*
* Copyright (C) 1999-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
// This test program pulls in all the library modules in order
// to run the unit tests on them.

View file

@ -60,7 +60,7 @@ OBJS= asserterror.obj deh.obj switch.obj complex.obj gcstats.obj \
cast.obj syserror.obj path.obj string.obj memset.obj math.obj \
outbuffer.obj ctype.obj regexp.obj random.obj windows.obj \
stream.obj switcherr.obj com.obj array.obj gc.obj mmfile.obj \
qsort.obj qsort.2.d math2.obj date.obj dateparse.obj thread.obj obj.obj \
qsort.obj math2.obj date.obj dateparse.obj thread.obj obj.obj \
iunknown.obj crc32.obj conv.obj arraycast.obj utf.obj uri.obj \
Czlib.obj Dzlib.obj zip.obj process.obj registry.obj recls.obj \
socket.obj socketstream.obj loader.obj stdarg.obj format.obj stdio.obj \
@ -119,14 +119,16 @@ SRC_INT= \
internal\memset.d internal\arraycast.d internal\aaA.d internal\adi.d \
internal\dmain2.d internal\cast.d internal\qsort.d internal\deh2.d \
internal\cmath2.d internal\obj.d internal\mars.h internal\aApply.d \
internal\object.d internal\trace.d
internal\object.d internal\trace.d internal\qsort2.d
SRC_STD_WIN= std\windows\registry.d \
std\windows\iunknown.d
SRC_STD_C_WIN= std\c\windows\windows.d std\c\windows\com.d
SRC_STD_C_WIN= std\c\windows\windows.d std\c\windows\com.d \
std\c\windows\winsock.d
SRC_STD_C_LINUX= std\c\linux\linux.d std\c\linux\linuxextern.d
SRC_STD_C_LINUX= std\c\linux\linux.d std\c\linux\linuxextern.d \
std\c\linux\socket.d
SRC_ETC=