diff --git a/moo/kernel/Apex.moo b/moo/kernel/Apex.moo index 9d1e728..aef1bc3 100644 --- a/moo/kernel/Apex.moo +++ b/moo/kernel/Apex.moo @@ -100,6 +100,9 @@ extend Apex method(#dual,#primitive) basicAt: index. method(#dual,#primitive) basicAt: index put: value. + + ##method(#dual,#primitive) basicMoveFrom: sindex length: length to: dindex. + ##method(#dual,#primitive) basicCopyFrom: sindex length: length to: dindex. (* ------------------------------------------------------------------ * FINALIZATION SUPPORT diff --git a/moo/kernel/Magnitu.moo b/moo/kernel/Magnitu.moo index 6c27a5c..351b6bd 100644 --- a/moo/kernel/Magnitu.moo +++ b/moo/kernel/Magnitu.moo @@ -75,6 +75,32 @@ class(#limited) Character(Magnitude) method(#primitive) > char. method(#primitive) <= char. method(#primitive) >= char. + + method digitValue: anInteger + { + ^'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' at: anInteger + } + + method digitValue + { + ## + + if (self >= $0 and: [self <= $9]) + { + ^self asInteger - $0 asInteger + } + elsif (self >= $A and: [self <= $Z]) + { + ^self asInteger - $A asInteger + 10 + } + elsif (self >= $a and: [self <= $z]) + { + ^self asInteger - $a asInteger + 10 + }. + + ##Exception signal: 'not a digit character'. + ^-1 + } } class(#limited) Number(Magnitude) diff --git a/moo/kernel/Socket.moo b/moo/kernel/Socket.moo index fb9c446..5916654 100644 --- a/moo/kernel/Socket.moo +++ b/moo/kernel/Socket.moo @@ -31,7 +31,7 @@ class(#byte) IP4Address(IPAddress) pos := 0. size := str size. - + acc := 0. digits := 0. dots := 0. @@ -92,10 +92,111 @@ class(#byte) IP6Address(IPAddress) { ^self basicNew: 16. } - + method(#class) fromString: str { + ^self new fromString: str. + } + + method __fromString: str + { + | pos size ch tgpos v1 val curtok saw_xdigit colonpos | + + pos := 0. + size := str size. + + ## handle leading :: specially + if (size > 0 and: [ (str at: pos) == $: ]) + { + pos := pos + 1. + if (pos >= size or: [ (str at: pos) ~~ $:]) { ^Error.Code.EINVAL }. + }. + + tgpos := 0. + curtok := pos. + val := 0. + saw_xdigit := false. + colonpos := -1. + + while (pos < size) + { + ch := str at: pos. + pos := pos + 1. + + v1 := ch digitValue. + if (v1 >= 0 and: [v1 <= 15]) + { + val := (val bitShift: 4) bitOr: v1. + if (val > 16rFFFF) { ^Error.Code.EINVAL }. + saw_xdigit := true. + continue. + }. + + if (ch == $:) + { + curtok := pos. + if (saw_xdigit not) + { + ## no multiple double colons are allowed + if (colonpos >= 0) { ^Error.Code.EINVAL }. + + ## capture the target position when the double colons + ## are encountered. + colonpos := tgpos. + continue. + } + elsif (pos >= size) + { + ## a colon can't be the last character + ^Error.Code.EINVAL + }. + + self basicAt: tgpos put: ((val bitShift: -8) bitAnd: 16rFF). + tgpos := tgpos + 1. + self basicAt: tgpos put: (val bitAnd: 16rFF). + tgpos := tgpos + 1. + + saw_xdigit := false. + val := 0. + continue. + }. + + (*if (ch == $. and: []) + { + saw_xdigit := true. + break. + }.*) + + + ## invalid character in the address + ^Error.Code.EINVAL. + }. + + if (saw_xdigit) + { + self basicAt: tgpos put: ((val bitShift: -8) bitAnd: 16rFF). + tgpos := tgpos + 1. + self basicAt: tgpos put: (val bitAnd: 16rFF). + tgpos := tgpos + 1. + }. + + if (colonpos >= 0) + { + /* double colon position */ + self basicMoveFrom: colonpos length: 5 to: ((self basicSize) - colonpos). + }. + +tgpos dump. +self basicSize dump. + if (tgpos ~~ (self basicSize)) { 'DDDDDDDDDDDd' dump. ^Error.Code.EINVAL }. + } + method fromString: str + { + if ((self __fromString: str) isError) + { + Exception signal: ('invalid IPv6 address ' & str). + } } } @@ -267,6 +368,10 @@ class MyObject(Object) s := IP4Address fromString: '192.168.123.232'. s dump. s basicSize dump. + +s := IP6Address fromString: 'fe80::c225:e9ff:fe47:b1b6'. +s dump. +s basicSize dump. ##s := IP6Address new. ##s dump. ##s := IP4SocketAddress new. diff --git a/moo/lib/pf-basic.c b/moo/lib/pf-basic.c index 2fc3e74..4ea260e 100644 --- a/moo/lib/pf-basic.c +++ b/moo/lib/pf-basic.c @@ -299,7 +299,7 @@ moo_pfrc_t moo_pf_basic_at (moo_t* moo, moo_ooi_t nargs) if (idx >= MOO_OBJ_GET_SIZE(rcv)) { /* index out of range */ - moo_seterrbfmt (moo, MOO_ERANGE, "position out of bound - %O", pos); + moo_seterrbfmt (moo, MOO_ERANGE, "position out of bound - %zu", idx); return MOO_PF_FAILURE; } @@ -353,7 +353,6 @@ moo_pfrc_t moo_pf_basic_at_put (moo_t* moo, moo_ooi_t nargs) if (MOO_OBJ_GET_FLAGS_RDONLY(rcv)) { -/* TODO: better error handling */ moo_seterrbfmt (moo, MOO_EPERM, "now allowed to change a read-only object - %O", rcv); return MOO_PF_FAILURE; } @@ -370,7 +369,7 @@ moo_pfrc_t moo_pf_basic_at_put (moo_t* moo, moo_ooi_t nargs) if (idx >= MOO_OBJ_GET_SIZE(rcv)) { /* index out of range */ - moo_seterrbfmt (moo, MOO_ERANGE, "position out of bound - %O", pos); + moo_seterrbfmt (moo, MOO_ERANGE, "position out of bound - %zu", idx); return MOO_PF_FAILURE; } @@ -435,6 +434,106 @@ moo_pfrc_t moo_pf_basic_at_put (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } +moo_pfrc_t moo_pf_basic_move (moo_t* moo, moo_ooi_t nargs) +{ + moo_oop_t rcv, spos, slen, dpos; + moo_oow_t sidx, ssz, didx; + + MOO_ASSERT (moo, nargs == 3); + + rcv = MOO_STACK_GETRCV(moo, nargs); + if (!MOO_OOP_IS_POINTER(rcv)) + { + /* the receiver is a special numeric object, not a normal pointer */ + moo_seterrbfmt (moo, MOO_EMSGRCV, "receiver not indexable - %O", rcv); + return MOO_PF_FAILURE; + } + + if (MOO_OBJ_GET_FLAGS_RDONLY(rcv)) + { + moo_seterrbfmt (moo, MOO_EPERM, "now allowed to change a read-only object - %O", rcv); + return MOO_PF_FAILURE; + } + + spos = MOO_STACK_GETARG(moo, nargs, 0); + slen = MOO_STACK_GETARG(moo, nargs, 1); + dpos = MOO_STACK_GETARG(moo, nargs, 2); + + if (moo_inttooow(moo, spos, &sidx) <= 0) + { + /* negative integer or not integer */ + moo_seterrbfmt (moo, MOO_EINVAL, "invalid source position - %O", spos); + return MOO_PF_FAILURE; + } + if (sidx >= MOO_OBJ_GET_SIZE(rcv)) + { + /* index out of range */ + moo_seterrbfmt (moo, MOO_ERANGE, "source position out of bound - %zu", sidx); + return MOO_PF_FAILURE; + } + + if (moo_inttooow(moo, slen, &ssz) <= 0) + { + /* negative integer or not integer */ + moo_seterrbfmt (moo, MOO_EINVAL, "invalid source length - %O", slen); + return MOO_PF_FAILURE; + } + + /* TODO: adjust ssz */ + + if (moo_inttooow(moo, dpos, &didx) <= 0) + { + /* negative integer or not integer */ + moo_seterrbfmt (moo, MOO_EINVAL, "invalid destination position - %O", dpos); + return MOO_PF_FAILURE; + } + if (didx >= MOO_OBJ_GET_SIZE(rcv)) + { + /* index out of range */ + moo_seterrbfmt (moo, MOO_ERANGE, "destination position out of bound - %zu", didx); + return MOO_PF_FAILURE; + } + + switch (MOO_OBJ_GET_FLAGS_TYPE(rcv)) + { + case MOO_OBJ_TYPE_BYTE: + MOO_MEMMOVE (&((moo_oop_byte_t)rcv)->slot[didx], + &((moo_oop_byte_t)rcv)->slot[sidx], + ssz * MOO_SIZEOF(((moo_oop_byte_t)rcv)->slot[0])); + break; + + case MOO_OBJ_TYPE_CHAR: + MOO_MEMMOVE (&((moo_oop_char_t)rcv)->slot[didx], + &((moo_oop_char_t)rcv)->slot[sidx], + ssz * MOO_SIZEOF(((moo_oop_char_t)rcv)->slot[0])); + break; + + case MOO_OBJ_TYPE_HALFWORD: + MOO_MEMMOVE (&((moo_oop_halfword_t)rcv)->slot[didx], + &((moo_oop_halfword_t)rcv)->slot[sidx], + ssz * MOO_SIZEOF(((moo_oop_halfword_t)rcv)->slot[0])); + break; + + case MOO_OBJ_TYPE_WORD: + MOO_MEMMOVE (&((moo_oop_word_t)rcv)->slot[didx], + &((moo_oop_word_t)rcv)->slot[sidx], + ssz * MOO_SIZEOF(((moo_oop_word_t)rcv)->slot[0])); + break; + + case MOO_OBJ_TYPE_OOP: + MOO_MEMMOVE (&((moo_oop_oop_t)rcv)->slot[didx], + &((moo_oop_oop_t)rcv)->slot[sidx], + ssz * MOO_SIZEOF(((moo_oop_oop_t)rcv)->slot[0])); + break; + + default: + moo_seterrnum (moo, MOO_EINTERN); + return MOO_PF_HARD_FAILURE; + } + + MOO_STACK_SETRETTORCV (moo, nargs); + return MOO_PF_SUCCESS; +} /* -------------------------------------------------------------------------------- * BASIC QUERY