# HG changeset patch # User Frank Benoit # Date 1207819226 -7200 # Node ID be4ce760802ae5ed235c57057a20ae369ceaa509 # Parent 184ab53b7785617a83c56d6187acc02f9c498c27 Add: missing files diff -r 184ab53b7785 -r be4ce760802a dwt/dwthelper/WeakHashMap.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dwthelper/WeakHashMap.d Thu Apr 10 11:20:26 2008 +0200 @@ -0,0 +1,33 @@ +module dwt.dwthelper.WeakHashMap; + + +/+ + Is not yet 'weak' ++/ +class WeakHashMap { + + static class Ref { + size_t ptr; + this(Object k){ + ptr = cast(size_t)cast(void*)k; + } + } + + Object[ Ref ] data; + + public void add (Object key, Object element){ + auto k = new Ref(key); + data[ k ] = element; + } + public void removeKey (Object key){ + scope k = new Ref(key); + data.remove( k ); + } + public Object get(Object key){ + scope k = new Ref(key); + if( auto p = k in data ){ + return *p; + } + return null; + } +} diff -r 184ab53b7785 -r be4ce760802a dwt/dwthelper/WeakRef.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dwthelper/WeakRef.d Thu Apr 10 11:20:26 2008 +0200 @@ -0,0 +1,88 @@ +/*========================================================================== + * weakref.d + * Written in the D Programming Language (http://www.digitalmars.com/d) + */ +/*************************************************************************** + * Creates a weak reference to a class instance. + * + * A weak reference lets you hold onto a pointer to an object without + * preventing the garbage collector from collecting it. + * If the garbage collector collects the object then the weak pointer will + * become 'null'. Thus one should always check a weak pointer for null + * before doing anything that depends upon it having a value. + * + * Tested with: + * DMD 1.025 / Phobos 1.025 + * DMD 1.025 / Tango 0.99.4 + * + * Usage example: +--- + class Something {} + + auto a = new Something(); + auto wa = new WeakRef!(Something)(a); + std.gc.fullCollect(); + + // Reference 'a' prevents collection so wa.ptr is non-null + assert(wa.ptr is a); + + delete a; + + // 'a' is gone now, so wa.ptr magically becomes null + assert(wa.ptr is null); +--- + * + * + * Author: William V. Baxter III + * Contributors: + * Date: 21 Jan 2008 + * Copyright: (C) 2008 William Baxter + * License: Public Domain where allowed by law, ZLIB/PNG otherwise. + */ +//=========================================================================== + +module dwt.dwthelper.WeakRef; + +private { + alias void delegate(Object) DisposeEvt; + extern (C) void rt_attachDisposeEvent( Object obj, DisposeEvt evt ); + extern (C) void rt_detachDisposeEvent( Object obj, DisposeEvt evt ); +} + +class WeakRef(T : Object) { +private: + size_t cast_ptr_; + void unhook(Object o) { + if (cast(size_t)cast(void*)o == cast_ptr_) { + rt_detachDisposeEvent(o, &unhook); + cast_ptr_ = 0; + } + } +public: + + this(T tptr) { + cast_ptr_ = cast(size_t)cast(void*)tptr; + rt_attachDisposeEvent(tptr, &unhook); + } + ~this() { + T p = ptr(); + if (p) { + rt_detachDisposeEvent(p, &unhook); + } + } + T ptr() { + return cast(T)cast(void*)cast_ptr_; + } + WeakRef dup() { + return new WeakRef(ptr()); + } + int opEquals( Object o ){ + if( auto other = cast( WeakRef!(T) )o ){ + return other.cast_ptr_ is cast_ptr_; + } + return false; + } + hash_t toHash(){ + return cast_ptr_; + } +} diff -r 184ab53b7785 -r be4ce760802a dwt/dwthelper/XmlTranscode.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dwthelper/XmlTranscode.d Thu Apr 10 11:20:26 2008 +0200 @@ -0,0 +1,181 @@ +module dwt.dwthelper.XmlTranscode; + +import dwt.dwthelper.utils; +import tango.core.Exception; + +/++ + + Decode XML entities into UTF8 string. + + Eg. "&" -> "&", "&" -> "&", "&" -> "&" + + Throws TextException on failure + + The given string is modified. + +/ +char[] xmlUnescape( char[] str ){ + + void error(){ + throw new TextException( "xmlUnescape" ); + } + // < ... + // Ӓ + // ኯ + char[] src = str; + char[] trg = str; + while( src.length ){ + if( src[0] !is '&' ){ + trg[0] = src[0]; + trg = trg[1..$]; + src = src[1..$]; + } + else{ + src = src[1..$]; // go past '&' + if( src.length < 2 ) error(); + + // search semi + int len = Math.min( src.length, 10 ); // limit semi search to possible longest entityname + int semi = tango.text.Util.locate( src[0 .. len ], ';' ); + if( semi is len ) error(); // no semi found + + char[] entityName = src[ 0 .. semi ]; // name without semi + dchar entityValue = 0; + switch( entityName ){ + case "lt": entityValue = '<'; break; + case "gt": entityValue = '>'; break; + case "amp": entityValue = '&'; break; + case "quot": entityValue = '\"'; break; + case "apos": entityValue = '\''; break; + default: + if( entityName[0] is 'x' ){ + if( semi < 2 ) error(); + if( semi > 9 ) error(); + foreach( hex; entityName[1..$] ){ + entityValue <<= 4; + if( hex >= '0' && hex <= '9' ){ + entityValue |= ( hex - '0' ); + } + else if( hex >= 'a' && hex <= 'f' ){ + entityValue |= ( hex - 'a' ); + } + else if( hex >= 'A' && hex <= 'F' ){ + entityValue |= ( hex - 'A' ); + } + else{ + error(); + } + } + } + else{ + if( semi < 1 ) error(); + if( semi > 9 ) error(); + foreach( dec; entityName[1..$] ){ + if( dec >= '0' && dec <= '9' ){ + entityValue *= 10; + entityValue += ( dec - '0' ); + } + else{ + error(); + } + } + } + } + dchar[1] arr; + arr[0] = entityValue; + uint ate = 0; + char[] res = tango.text.convert.Utf.toString( arr, trg, &ate ); + trg = trg[ res.length .. $ ]; + src = src[ semi +1 .. $ ]; // go past semi + } + } + return str[ 0 .. trg.ptr-str.ptr ]; +} + + +/++ + + Encode XML entities into UTF8 string. + + First checks if processing is needed. + + If not, the original string is returned. + + If processing is needed, a new string is allocated. + +/ +char[] xmlEscape( char[] xml ){ + bool needsReplacement( dchar c ){ + switch( c ){ + case '<': + case '>': + case '&': + case '\"': + case '\'': + case '\r': + case '\n': + case '\u0009': + return true; + default: + return c > 0x7F; + } + } + + // Check if processing is needed + foreach( char c; xml ){ + if( needsReplacement( c )){ + goto Lprocess; + } + } + return xml; +Lprocess: + + // yes, do a new string, start with +20 chars + char[] res = new char[ xml.length + 20 ]; + res.length = 0; + + foreach( dchar c; xml ){ + + if( !needsReplacement( c )){ + res ~= c; + } + else{ + res ~= '&'; + switch( c ){ + case '<': res ~= "lt"; break; + case '>': res ~= "gt"; break; + case '&': res ~= "amp"; break; + case '\"': res ~= "quot"; break; + case '\'': res ~= "apos"; break; + case '\r': case '\n': case '\u0009': + default: + char toHexDigit( int i ){ + if( i < 10 ) return '0'+i; + return 'A'+i-10; + } + res ~= "#x"; + if( c <= 0xFF ){ + res ~= toHexDigit(( c >> 4 ) & 0x0F ); + res ~= toHexDigit(( c >> 0 ) & 0x0F ); + } + else if( c <= 0xFFFF ){ + res ~= toHexDigit(( c >> 12 ) & 0x0F ); + res ~= toHexDigit(( c >> 8 ) & 0x0F ); + res ~= toHexDigit(( c >> 4 ) & 0x0F ); + res ~= toHexDigit(( c >> 0 ) & 0x0F ); + } + else if( c <= 0xFFFFFF ){ + res ~= toHexDigit(( c >> 20 ) & 0x0F ); + res ~= toHexDigit(( c >> 16 ) & 0x0F ); + res ~= toHexDigit(( c >> 12 ) & 0x0F ); + res ~= toHexDigit(( c >> 8 ) & 0x0F ); + res ~= toHexDigit(( c >> 4 ) & 0x0F ); + res ~= toHexDigit(( c >> 0 ) & 0x0F ); + } + else { + res ~= toHexDigit(( c >> 28 ) & 0x0F ); + res ~= toHexDigit(( c >> 24 ) & 0x0F ); + res ~= toHexDigit(( c >> 20 ) & 0x0F ); + res ~= toHexDigit(( c >> 16 ) & 0x0F ); + res ~= toHexDigit(( c >> 12 ) & 0x0F ); + res ~= toHexDigit(( c >> 8 ) & 0x0F ); + res ~= toHexDigit(( c >> 4 ) & 0x0F ); + res ~= toHexDigit(( c >> 0 ) & 0x0F ); + } + break; + } + res ~= ';'; + } + } +} +