view dwt/dwthelper/utils.d @ 183:c4643827733c

Added toStringzValidPtr to sync with dwt-linux
author Frank Benoit <benoit@tionex.de>
date Mon, 10 Mar 2008 16:48:51 +0100
parents 772f75da6a52
children bcdc37794717
line wrap: on
line source

/**
 * Authors: Frank Benoit <keinfarbton@googlemail.com>
 */
module dwt.dwthelper.utils;

public import dwt.dwthelper.System;
public import Math = tango.math.Math;

public import tango.core.Exception : IllegalArgumentException, IOException;

import tango.io.Stdout;
import tango.stdc.stringz;
import tango.text.Util;
import tango.text.Unicode;
import tango.text.convert.Utf;
import tango.core.Exception;
import tango.stdc.stdlib : exit;

import tango.util.log.Trace;

void implMissing( char[] file, uint line ){
    Stderr.formatln( "implementation missing in file {} line {}", file, line );
    Stderr.formatln( "exiting ..." );
    exit(1);
}

abstract class ArrayWrapper{
}
abstract class ValueWrapper{
}

class ArrayWrapperT(T) : ArrayWrapper {
    public T[] array;
    public this( T[] data ){
        array = data;
    }
}

class ValueWrapperT(T) : ValueWrapper {
    public T value;
    public this( T data ){
        value = data;
    }
}

alias ValueWrapperT!(bool)    ValueWrapperBool;
alias ValueWrapperT!(int)     ValueWrapperInt;
alias ArrayWrapperT!(byte)    ArrayWrapperByte;
alias ArrayWrapperT!(int)     ArrayWrapperInt;
alias ArrayWrapperT!(Object)  ArrayWrapperObject;
alias ArrayWrapperT!(char)    ArrayWrapperString;
alias ArrayWrapperT!(char[])  ArrayWrapperString2;

int codepointIndexToIndex( char[] str, int cpIndex ){
    int cps = cpIndex;
    int res = 0;
    while( cps > 0 ){
        cps--;
        if( str[res] < 0x80 ){
            res+=1;
        }
        else if( str[res] < 0xE0 ){
            res+=2;
        }
        else if( str[res] & 0xF0 ){
            res+=3;
        }
        else{
            res+=4;
        }
    }
    return res;
}
int indexToCodepointIndex( char[] str, int index ){
    int i = 0;
    int res = 0;
    while( i < index ){
        if( str[i] < 0x80 ){
            i+=1;
        }
        else if( str[i] < 0xE0 ){
            i+=2;
        }
        else if( str[i] & 0xF0 ){
            i+=3;
        }
        else{
            i+=4;
        }
        res++;
    }
    return res;
}

char[] firstCodePointStr( char[] str, out int consumed ){
    dchar[1] buf;
    uint ate;
    dchar[] res = str.toString32( buf, &ate );
    consumed = ate;
    return str[ 0 .. ate ];
}

dchar firstCodePoint( char[] str ){
    int dummy;
    return firstCodePoint( str, dummy );
}
dchar firstCodePoint( char[] str, out int consumed ){
    dchar[1] buf;
    uint ate;
    dchar[] res = str.toString32( buf, &ate );
    consumed = ate;
    if( ate is 0 || res.length is 0 ){
        Trace.formatln( "dwthelper.utils {}: str.length={} str={:X2}", __LINE__, str.length, cast(ubyte[])str );
    }
    assert( ate > 0 );
    assert( res.length is 1 );
    return res[0];
}

char[] dcharToString( dchar key ){
    dchar[1] buf;
    buf[0] = key;
    return tango.text.convert.Utf.toString( buf );
}

int codepointCount( char[] str ){
    scope dchar[] buf = new dchar[]( str.length );
    uint ate;
    dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate );
    assert( ate is str.length );
    return res.length;
}

alias tango.text.convert.Utf.toString16 toString16;
alias tango.text.convert.Utf.toString toString;

int getRelativeCodePointOffset( char[] str, int startIndex, int searchRelCp ){
    int ignore;
    int i = startIndex;
    if( searchRelCp > 0 ){
        while( searchRelCp !is 0 ){

            if( ( i < str.length )
                && ( str[i] & 0x80 ) is 0x00 )
            {
                i+=1;
            }
            else if( ( i+1 < str.length )
                && (( str[i+1] & 0xC0 ) is 0x80 )
                && (( str[i  ] & 0xE0 ) is 0xC0 ))
            {
                i+=2;
            }
            else if( ( i+2 < str.length )
                && (( str[i+2] & 0xC0 ) is 0x80 )
                && (( str[i+1] & 0xC0 ) is 0x80 )
                && (( str[i  ] & 0xF0 ) is 0xE0 ))
            {
                i+=3;
            }
            else if(( i+3 < str.length )
                && (( str[i+3] & 0xC0 ) is 0x80 )
                && (( str[i+2] & 0xC0 ) is 0x80 )
                && (( str[i+1] & 0xC0 ) is 0x80 )
                && (( str[i  ] & 0xF8 ) is 0xF0 ))
            {
                i+=4;
            }
            else{
                tango.text.convert.Utf.onUnicodeError( "invalid utf8 input", i );
            }
            searchRelCp--;
        }
    }
    else if( searchRelCp < 0 ){
        while( searchRelCp !is 0 ){
            do{
                i--;
                if( i < 0 ){
                    Trace.formatln( "dwthelper.utils getRelativeCodePointOffset {}: str={}, startIndex={}, searchRelCp={}", __LINE__, str, startIndex, searchRelCp );
                    tango.text.convert.Utf.onUnicodeError( "invalid utf8 input", i );
                }
            } while(( str[i] & 0xC0 ) is 0x80 );
            searchRelCp++;
        }
    }
    return i - startIndex;
}
dchar getRelativeCodePoint( char[] str, int startIndex, int searchRelCp, out int relIndex ){
    relIndex = getRelativeCodePointOffset( str, startIndex, searchRelCp );
    int ignore;
    return firstCodePoint( str[ startIndex+relIndex .. $ ], ignore );
}

int utf8AdjustOffset( char[] str, int offset ){
    if( str.length <= offset || offset <= 0 ){
        return offset;
    }
    while(( str[offset] & 0xC0 ) is 0x80 ){
        offset--;
    }
    return offset;
}

dchar CharacterFirstToLower( char[] str ){
    int consumed;
    return CharacterFirstToLower( str, consumed );
}
dchar CharacterFirstToLower( char[] str, out int consumed ){
    dchar[1] buf;
    buf[0] = firstCodePoint( str, consumed );
    dchar[] r = tango.text.Unicode.toLower( buf );
    return r[0];
}

dchar CharacterToLower( dchar c ){
    dchar[] r = tango.text.Unicode.toLower( [c] );
    return r[0];
}
dchar CharacterToUpper( dchar c ){
    dchar[] r = tango.text.Unicode.toUpper( [c] );
    return r[0];
}
bool CharacterIsWhitespace( dchar c ){
    return tango.text.Unicode.isWhitespace( c );
}
bool CharacterIsDigit( dchar c ){
    return tango.text.Unicode.isDigit( c );
}

public int indexOf( char[] str, char searched ){
    int res = tango.text.Util.locate( str, searched );
    if( res is str.length ) res = -1;
    return res;
}

public int indexOf( char[] str, char searched, int startpos ){
    int res = tango.text.Util.locate( str, searched, startpos );
    if( res is str.length ) res = -1;
    return res;
}

public int indexOf(char[] str, char[] ch){
    return indexOf( str, ch, 0 );
}

public int indexOf(char[] str, char[] ch, int start){
    int res = tango.text.Util.locatePattern( str, ch, start );
    if( res is str.length ) res = -1;
    return res;
}

public int lastIndexOf(char[] str, char ch){
    return lastIndexOf( str, ch, str.length );
}
public int lastIndexOf(char[] str, char ch, int formIndex){
    int res = tango.text.Util.locatePrior( str, ch, formIndex );
    if( res is str.length ) res = -1;
    return res;
}

public char[] replace( char[] str, char from, char to ){
    return tango.text.Util.replace( str.dup, from, to );
}

public char[] substring( char[] str, int start ){
    return str[ start .. $ ].dup;
}

public char[] substring( char[] str, int start, int end ){
    return str[ start .. end ].dup;
}

public wchar[] substring( wchar[] str, int start ){
    return str[ start .. $ ].dup;
}

public wchar[] substring( wchar[] str, int start, int end ){
    return str[ start .. end ].dup;
}

public char charAt( char[] str, int pos ){
    return str[ pos ];
}

public void getChars( char[] src, int srcBegin, int srcEnd, char[] dst, int dstBegin){
    dst[ dstBegin .. dstBegin + srcEnd - srcBegin ] = src[ srcBegin .. srcEnd ];
}

public wchar[] toCharArray( char[] str ){
    return toString16( str );
}

public bool endsWith( char[] src, char[] pattern ){
    if( src.length < pattern.length ){
        return false;
    }
    return src[ $-pattern.length .. $ ] == pattern;
}

public bool equals( char[] src, char[] other ){
    return src == other;
}

public bool equalsIgnoreCase( char[] src, char[] other ){
    return tango.text.Unicode.toFold(src) == tango.text.Unicode.toFold(other);
}

public bool startsWith( char[] src, char[] pattern ){
    if( src.length < pattern.length ){
        return false;
    }
    return src[ 0 .. pattern.length ] == pattern;
}
public char[] toLowerCase( char[] src ){
    return tango.text.Unicode.toLower( src );
}

public hash_t toHash( char[] src ){
    return typeid(char[]).getHash(&src);
}

static char[] toHex(uint value, bool prefix = true, int radix = 8){
    return tango.text.convert.Integer.toString(
            value,
            radix is 10 ? tango.text.convert.Integer.Style.Signed :
            radix is  8 ? tango.text.convert.Integer.Style.Octal  :
            radix is 16 ? tango.text.convert.Integer.Style.Hex    :
                          tango.text.convert.Integer.Style.Signed,
            prefix ? tango.text.convert.Integer.Flags.Prefix : tango.text.convert.Integer.Flags.None
            );
}

class NumberFormatException : IllegalArgumentException {
    this( char[] e ){
        super(e);
    }
    this( Exception e ){
        super(e.toString);
    }
}

private struct GCStats {
    size_t poolsize;        // total size of pool
    size_t usedsize;        // bytes allocated
    size_t freeblocks;      // number of blocks marked FREE
    size_t freelistsize;    // total of memory on free lists
    size_t pageblocks;      // number of blocks marked PAGE
}
private extern(C) GCStats gc_stats();

size_t RuntimeTotalMemory(){
    GCStats s = gc_stats();
    return s.poolsize;
}