void st_multimethods_ptr(void) { useclass(Counter); usegeneric((gaddTo1)gaddTo1_s, (gaddTo2)gaddTo2_s, (gaddTo3)gaddTo3_s, (gaddTo4)gaddTo4_s); OBJ cnt = gnew(Counter); OBJ one = gincr(gnew(Counter)); OBJ ret; U32 cid = cos_object_id(cnt); U32 oid = cos_object_id(one); IMP2 gaddTo1_p = cos_method_lookup2((SEL)gaddTo1_s, cid, oid); IMP3 gaddTo2_p = cos_method_lookup3((SEL)gaddTo2_s, cid, oid, oid); IMP4 gaddTo3_p = cos_method_lookup4((SEL)gaddTo3_s, cid, oid, oid, oid); IMP5 gaddTo4_p = cos_method_lookup5((SEL)gaddTo4_s, cid, oid, oid, oid, oid); STEST( "multimethod pointer (rank 2)", N, gaddTo1_p((SEL)gaddTo1_s,cnt,one,0,&ret) ); STEST( "multimethod pointer (rank 3)", N, gaddTo2_p((SEL)gaddTo2_s,cnt,one,one,0,&ret) ); STEST( "multimethod pointer (rank 4)", N, gaddTo3_p((SEL)gaddTo3_s,cnt,one,one,one,0,&ret) ); STEST( "multimethod pointer (rank 5)", N, gaddTo4_p((SEL)gaddTo4_s,cnt,one,one,one,one,0,&ret) ); test_assert( gint(cnt) == N+2*N+3*N+4*N ); grelease(cnt); grelease(one); }
void st_methods_ptr(void) { useclass(Counter); usegeneric((gincr)gincr_s, (gincrBy1)gincrBy1_s, (gincrBy2)gincrBy2_s, (gincrBy3)gincrBy3_s, (gincrBy4)gincrBy4_s, (gincrBy5)gincrBy5_s); OBJ cnt = gnew(Counter); OBJ ret; IMP1 gincr_p = cos_method_lookup1((SEL)gincr_s , cos_object_id(cnt)); IMP1 gincrBy1_p = cos_method_lookup1((SEL)gincrBy1_s, cos_object_id(cnt)); IMP1 gincrBy2_p = cos_method_lookup1((SEL)gincrBy2_s, cos_object_id(cnt)); IMP1 gincrBy3_p = cos_method_lookup1((SEL)gincrBy3_s, cos_object_id(cnt)); IMP1 gincrBy4_p = cos_method_lookup1((SEL)gincrBy4_s, cos_object_id(cnt)); IMP1 gincrBy5_p = cos_method_lookup1((SEL)gincrBy5_s, cos_object_id(cnt)); gincrBy1_arg_t arg1 = { 1 }; gincrBy2_arg_t arg2 = { 1,1 }; gincrBy3_arg_t arg3 = { 1,1,1 }; gincrBy4_arg_t arg4 = { 1,1,1,1 }; gincrBy5_arg_t arg5 = { 1,1,1,1,1 }; STEST( "method pointer (0 argument )", N, gincr_p ((SEL)gincr_s ,cnt,0 ,&ret) ); STEST( "method pointer (1 argument )", N, gincrBy1_p((SEL)gincrBy1_s,cnt,&arg1,&ret) ); STEST( "method pointer (2 arguments)", N, gincrBy2_p((SEL)gincrBy2_s,cnt,&arg2,&ret) ); STEST( "method pointer (3 arguments)", N, gincrBy3_p((SEL)gincrBy3_s,cnt,&arg3,&ret) ); STEST( "method pointer (4 arguments)", N, gincrBy4_p((SEL)gincrBy4_s,cnt,&arg4,&ret) ); STEST( "method pointer (5 arguments)", N, gincrBy5_p((SEL)gincrBy5_s,cnt,&arg5,&ret) ); test_assert( gint(cnt) == N+N+2*N+3*N+4*N+5*N ); grelease(cnt); }
U32 // integer: [+-]?[0-9]+ Stream_parseI32(OBJ strm, I32 *val, BOOL skipSpc) { ensure( val, "invalid argument" ); U32 cnt = 0; // char counter I32 chr; // character I32 sgn = 0; // sign char I32 cur = 0, prv = -1; // value SEL sel = genericref(ggetChr); IMP1 get = cos_method_fastLookup1(sel, cos_object_id(strm)); // skip white spaces (nothing else) if (skipSpc) while (get(sel, strm, 0, &chr), chr == ' ') ; // sign (optional) if (chr == '-' || chr == '+') { sgn = chr, cnt++; get(sel, strm, 0, &cnt); } // significant digits while (cur > prv && isdigit(chr)) { prv = cur, cur = cur * 10 + ((U32)chr - '0'), cnt++; get(sel, strm, 0, &chr); } // extra digits (discarded) while (isdigit(chr)) get(sel, strm, 0, &chr), cnt++; // restore lookahead if (chr != EndOfStream) gungetChr(strm, chr); if (cnt == 1 && sgn) gungetChr(strm, sgn), cnt--; // may fail // store result if (cur > prv) *val = sgn == '-' ? -cur : cur; else { // overflow errno = ERANGE; *val = sgn == '-' ? I32_MIN : I32_MAX; } return cnt; }
U32 // floating: [+-]?[0-9]+(.[0-9]+)?([eE][+-]?[0-9]+)? Stream_parseF64(OBJ strm, F64 *val, BOOL skipSpc) { ensure( val, "invalid argument" ); U32 cnt = 0; // char counter I32 chr; // character I32 sgn = 0; // sign char F64 cur = 0; // value SEL sel = genericref(ggetChr); IMP1 get = cos_method_fastLookup1(sel, cos_object_id(strm)); // skip white spaces (nothing else) if (skipSpc) while (get(sel, strm, 0, &chr), chr == ' ') ; // sign (optional) if (chr == '-' || chr == '+') { sgn = chr, cnt++; get(sel, strm, 0, &cnt); } // significant digits while (isfinite(cur) && isdigit(chr)) { cur = cur * 10 + ((U32)chr - '0'), cnt++; get(sel, strm, 0, &chr); } // extra digits (discarded) while (isdigit(chr)) get(sel, strm, 0, &chr), cnt++; // decimal part if (chr == '.' || chr == ',') { F64 fra = 0; I32 exp = 0; // significant digits while (exp >= -DECIMAL_DIG && isdigit(chr)) { fra = fra * 10 + ((U32)chr - '0'), cnt++, exp--; get(sel, strm, 0, &chr); } // extra digits (discarded) while (isdigit(chr)) get(sel, strm, 0, &chr), cnt++; cur += fra * float_ipow(10, exp); } // exponent if (chr == 'E' || chr == 'e') { I32 exp = 0; U32 n = Stream_parseI16(strm, &exp, NO); if (n) { cnt += n; if (exp) cur *= float_ipow(10, exp); } } // restore lookahead if (chr != EndOfStream) gungetChr(strm, chr); if (cnt == 1 && sgn) gungetChr(strm, sgn), cnt--; // may fail // store result *val = sgn == '-' ? -cur : cur; return cnt; }