static ls_tcp_t *new_tcp_handle(lua_State *l) { ls_tcp_t *tcp = (ls_tcp_t*)ls_malloc(l, sizeof(ls_tcp_t)); ls_wait_object_init(&tcp->wait_object); uv_tcp_init(uv_default_loop(), &tcp->handle); return tcp; }
static ls_write_t *new_write_req(lua_State *l) { int i; ls_write_t *wr; wr = (ls_write_t*)ls_malloc(l, sizeof(ls_write_t)); wr->wait_object.mthread_ref = LUA_NOREF; for (i=0; i<arraysize(wr->data_refs); i++) wr->data_refs[i] = LUA_NOREF; wr->refcnt = 0; return wr; }
static int tcp_create_client(lua_State *l) { const char *rip4 = "0.0.0.0"; int rport = 0; ls_tcp_t *client; uv_tcp_t *handle; uv_loop_t *loop = uv_default_loop(); uv_connect_t *connect_req; int connect_timeout; if (lua_gettop(l) >= 2) { rip4 = luaL_checkstring(l, 1); rport = luaL_checkint(l, 2); luaL_argcheck(l, strnlen(rip4, 256) > 0, 1, "invalid ipv4 address"); luaL_argcheck(l, rport > 0, 2, "port number should > 0"); } else if (lua_gettop(l) == 1) { rport = luaL_checkint(l, 1); luaL_argcheck(l, rport > 0, 1, "port number should > 0"); } else return ls_error_return(l, LS_ERRCODE_INVAL, "server ip and port should be specified."); client = new_tcp_handle(l); connect_req = (uv_connect_t*)ls_malloc(l, sizeof(uv_connect_t)); if (uv_tcp_connect(connect_req, &client->handle, uv_ip4_addr(rip4, rport), tcp_connect_cb)) { ls_free(l, connect_req); uv_close((uv_handle_t*)client, tcp_close_cb); return ls_last_error_return(l, loop); } lua_getglobal(l, "tcp"); lua_getfield(l, -1, "connect_timeout"); connect_timeout = lua_tointeger(l, -1); lua_pop(l, 2); ls_set_waiting(l, &client->wait_object, connect_timeout); return lua_yield(l, 0); }
char *_ntos(const struct ls_object *number, int radix) { int is_complex, type_re, type_im; char fmt[20]; char *str; int len, n; void *arg1 = NULL, *arg2 = NULL; fmt[0] = '\0'; /* TODO: radix other than 10 */ UNUSED_ARGUMENT(radix); is_complex = lso_is_complex(number); type_re = lso_number_type_re(number); type_im = lso_number_type_im(number); switch(type_re) { case 0: if (is_complex && number->u1.val == 0) { arg1 = &n; /* simply placeholder */ strcpy(fmt, "%n"); } else { arg1 = (void *)((long) number->u1.val); strcpy(fmt, "%d"); } break; case 1: arg1 = *((mpz_t *)number->u1.ptr); strcpy(fmt, "%Zd"); break; case 2: arg1 = *((mpq_t *)number->u1.ptr); strcpy(fmt, "%Qd"); break; case 3: arg1 = *((mpf_t *)number->u1.ptr); /* we have to use different styles for integers and non-integers */ if (mpf_integer_p(*((mpf_t *)number->u1.ptr))) strcpy(fmt, "%#.1Ff"); else strcpy(fmt, "%.16Fg"); break; } if (is_complex) { switch(type_im) { case 0: arg2 = (void *)((long) number->u2.val); if (number->u2.val == 1) { arg2 = &n; strcat(fmt, "+%ni"); } else if (number->u2.val == -1) { arg2 = &n; strcat(fmt, "-%ni"); } else strcat(fmt, "%+di"); break; case 1: arg2 = *((mpz_t *)number->u2.ptr); strcat(fmt, "%+Zdi"); break; case 2: arg2 = *((mpq_t *)number->u2.ptr); strcat(fmt, "%+Qdi"); break; case 3: arg2 = *((mpf_t *)number->u2.ptr); if (mpf_integer_p(*((mpf_t *)number->u2.ptr))) strcat(fmt, "%#+.1Ffi"); else strcat(fmt, "%+.16Fgi"); break; } } len = gmp_snprintf(NULL, 0, fmt, arg1, arg2); str = (char *) ls_malloc(len + 1); gmp_snprintf(str, len + 1, fmt, arg1, arg2); return str; }
void _ston(struct ls_object *obj, const char *num, int defradix) { char *dup = strdup(num), *ptr = dup; char *end; char saved; int exactness = -1, radix = -1; int flag, flag2, type, allowre = 1, allowim = 1; struct ls_real re = { 0, { 0 } }; /* prefix */ while (*ptr == '#') { ptr++; switch (*ptr) { case 'i': case 'e': if (exactness == -1) exactness = ((*ptr == 'i')? 0: 1); else goto err; ptr++; break; case 'b': case 'o': case 'd': case 'x': if (radix == -1) radix = ((*ptr == 'b')? 2: (*ptr == 'o')? 8: (*ptr == 'd')? 10: 16); else goto err; ptr++; break; default: goto err; } } if (radix == -1) radix = defradix; restart: /* default to big integer */ type = 1; /* parsing */ flag = _ston_parse_real(ptr, &end, radix); if (!(flag & stonf_valid)) goto err; if (*end == '/') { type = 2; flag2 = _ston_parse_real(end + 1, &end, radix); /* sanity for rational */ if (!(flag2 & stonf_valid)) goto err; if ((flag & stonf_decimal) || (flag2 & stonf_signed) || (flag2 & stonf_decimal)) goto err; } if (flag & stonf_decimal) type = 3; if ((*end == 'i' && allowim == 0) || (*end != 'i' && allowre == 0)) goto err; /* generating initial result */ if ((*end == 'i' && (flag & stonf_iunit))) { type = 0; if (!(flag & stonf_signed)) goto err; if (*ptr == '+') re.v = 1; else re.v = -1; } saved = *end; *end = '\0'; /* no _re_clear can be called from now until the content is fully set up */ re.type = type; if (*ptr == '+') /* tackle around strange behavior of mpx_set_str */ ptr++; switch (re.type) { case 1: re.z = (mpz_t *) ls_malloc(sizeof *re.z); mpz_init(*re.z); mpz_set_str(*re.z, ptr, radix); break; case 2: re.q = (mpq_t *) ls_malloc(sizeof *re.q); mpq_init(*re.q); mpq_set_str(*re.q, ptr, radix); break; case 3: if (exactness == 1) { /* * unfortunately, #e<decimal> has to be handled here manually, * the result inexact->exact is normally not acceptable */ re.type = 2; re.q = (mpq_t *) ls_malloc(sizeof *re.q); mpq_init(*re.q); _lsrt_mpq_set_decimal(*re.q, ptr, radix); } else { re.f = (mpf_t *) ls_malloc(sizeof *re.f); /* * TODO: gmp only guarantees that result prec is no lower * than specified, check R5RS requirement */ if (flag & stonf_prec_mask) mpf_init2(*re.f, flag & stonf_prec_mask); else mpf_init(*re.f); mpf_set_str(*re.f, ptr, radix); } break; } *end = saved; /* canonicalize and transform */ if (exactness == 0 || ((flag & stonf_pound) && exactness != 1)) _re_promote(&re, 3, 0); _re_canonicalize(&re); /* store */ if (*end == 'i') { if (!(flag & stonf_signed)) /* imaginary must be signed */ goto err; allowim = 0; _re_update_lso_im(obj, &re); end++; } else { allowre = 0; _re_update_lso_re(obj, &re); } if (*end) { ptr = end; goto restart; } free(dup); return; err: free(dup); _re_clear(&re); lso_set_type(obj, ls_t_boolean); obj->u1.val = 0; }