/* * Limited-length atoi, with auto-advance of the string */ int lib_atoi_adv(const char *&str, size_t &len) { /* parse the sign, if present */ int s = 1; if (len >= 1 && *str == '-') s = -1, ++str, --len; else if (len >= 1 && *str == '+') ++str, --len; /* scan digits */ int acc; for (acc = 0 ; len > 0 && is_digit(*str) ; acc *= 10, acc += value_of_digit(*str), ++str, --len) ; /* apply the sign and return the result */ return s * acc; }
/* * Set up the thread. All string parameters are provided in internal * string format, with VMB_LEN length prefixes. */ HttpReqThread(VMG_ const vm_val_t *id, const char *url, const char *verb, int32 options, const char *hdrs, vm_val_t *body, const char *body_type, const vm_rcdesc *rc) { /* save the VM globals */ vmg = VMGLOB_ADDR; /* add a reference on the net event queue */ if ((queue = G_net_queue) != 0) queue->add_ref(); /* create a global for the ID value */ idg = G_obj_table->create_global_var(); idg->val = *id; /* save the option flags */ this->options = options; /* set up to parse the URL */ size_t urll = vmb_get_len(url); url += VMB_LEN; /* note whether the scheme is plain http or https */ https = (urll >= 8 && memcmp(url, "https://", 8) == 0); /* we don't have any URL pieces yet */ host = 0; resource = 0; port = (https ? 443 : 80); /* skip the scheme prefix */ size_t pfx = (urll >= 7 && memcmp(url, "http://", 7) == 0 ? 7 : urll >= 8 && memcmp(url, "https://", 8) == 0 ? 8 : 0); url += pfx, urll -= pfx; /* the host name is the part up to the ':', '/', or end of string */ const char *start; for (start = url ; urll > 0 && *url != ':' && *url != '/' ; ++url, --urll) ; /* save the host name */ host = lib_copy_str(start, url - start); /* parse the port, if present */ if (urll > 0 && *url == ':') { /* parse the port number string */ for (--urll, start = ++url, port = 0 ; urll > 0 && *url != '/' ; ++url, --urll) { if (is_digit(*url)) port = port*10 + value_of_digit(*url); } } /* * The rest (including the '/') is the resource string. If there's * nothing left, the resource is implicitly '/'. */ if (urll > 0) resource = lib_copy_str(url, urll); else resource = lib_copy_str("/"); /* make null-terminated copies of the various strings */ this->verb = lib_copy_str(verb + VMB_LEN, vmb_get_len(verb)); this->hdrs = (hdrs == 0 ? 0 : lib_copy_str(hdrs + VMB_LEN, vmb_get_len(hdrs))); /* if there's a content body, set up the payload */ this->body = 0; if (body != 0) { /* set up an empty payload */ this->body = new OS_HttpPayload(); /* * Convert the body to a stream payload, if it's a string or * ByteArray. If it's a LookupTable, it's a set of form * fields. */ if (body->typ == VM_OBJ && CVmObjLookupTable::is_lookup_table_obj(vmg_ body->val.obj)) { /* * The body is a LookupTable, so we have a set of form * fields to encode as HTML form data. */ /* cast the object value */ CVmObjLookupTable *tab = (CVmObjLookupTable *)vm_objp(vmg_ body->val.obj); /* add each key in the table as a form field */ iter_body_table_ctx ctx(this, rc); tab->for_each(vmg_ iter_body_table, &ctx); } else { /* * It's not a lookup table, so it must be bytes to upload, * as a string or ByteArray. */ const char *def_mime_type = 0; CVmStream *stream = val_to_stream(vmg_ body, &def_mime_type); /* presume we're going to use the default mime type */ const char *mime_type = def_mime_type; size_t mime_type_len = (mime_type != 0 ? strlen(mime_type) : 0); /* if the caller specified a mime type, use it instead */ if (body_type != 0) { mime_type = body_type + VMB_LEN; mime_type_len = vmb_get_len(body_type); } /* add the stream */ this->body->add( "", 0, "", 0, mime_type, mime_type_len, stream); } } }
/* * buffer-checked vsprintf implementation */ size_t t3vsprintf(char *buf, size_t buflen, const char *fmt, va_list args0) { size_t rem; size_t need = 0; char *dst; /* * make a private copy of the arguments, to ensure that we don't modify * the caller's copy (on some platforms, va_list is a reference type; * the caller might want to reuse their argument pointer for a two-pass * operation, such as a pre-format pass to measure how much space is * needed) */ va_list args; os_va_copy(args, args0); /* scan the buffer */ for (dst = buf, rem = buflen ; *fmt != '\0' ; ++fmt) { /* check for a format specifier */ if (*fmt == '%') { const char *fmt_start = fmt; const char *nth = ""; const char *txt; size_t txtlen; char buf[20]; int fld_wid = -1; int fld_prec = -1; char lead_char = ' '; int plus = FALSE; int approx = FALSE; int add_ellipsis = FALSE; int left_align = FALSE; size_t i; /* skip the '%' */ ++fmt; /* check for the "approximation" flag */ if (*fmt == '~') { approx = TRUE; ++fmt; } /* check for an explicit sign */ if (*fmt == '+') { plus = TRUE; ++fmt; } /* check for left alignment */ if (*fmt == '-') { left_align = TRUE; ++fmt; } /* if leading zeros are desired, note it */ if (*fmt == '0') lead_char = '0'; /* check for a field width specifier */ if (is_digit(*fmt)) { /* scan the digits */ for (fld_wid = 0 ; is_digit(*fmt) ; ++fmt) { fld_wid *= 10; fld_wid += value_of_digit(*fmt); } } else if (*fmt == '*') { /* the value is an integer taken from the arguments */ fld_wid = va_arg(args, int); /* skip the '*' */ ++fmt; } /* check for a precision specifier */ if (*fmt == '.') { /* skip the '.' */ ++fmt; /* check what we have */ if (*fmt == '*') { /* the value is an integer taken from the arguments */ fld_prec = va_arg(args, int); /* skip the '*' */ ++fmt; } else { /* scan the digits */ for (fld_prec = 0 ; is_digit(*fmt) ; ++fmt)
/* * buffer-checked vsprintf implementation */ void t3vsprintf(char *buf, size_t buflen, const char *fmt, va_list args) { size_t rem; char *dst; /* if there's no room at all in the buffer, give up immediately */ if (buflen == 0) return; /* scan the buffer */ for (dst = buf, rem = buflen - 1 ; *fmt != '\0' && rem != 0 ; ++fmt) { /* check for a format specifier */ if (*fmt == '%') { const char *fmt_start = fmt; const char *txt; size_t txtlen; char buf[20]; int fld_wid = -1; int fld_prec = -1; char lead_char = ' '; int approx = FALSE; int add_ellipsis = FALSE; int left_align = FALSE; size_t i; /* skip the '%' */ ++fmt; /* check for the "approximation" flag */ if (*fmt == '~') { approx = TRUE; ++fmt; } /* check for left alignment */ if (*fmt == '-') { left_align = TRUE; ++fmt; } /* if leading zeroes are desired, note it */ if (*fmt == '0') lead_char = '0'; /* check for a field width specifier */ if (is_digit(*fmt)) { /* scan the digits */ for (fld_wid = 0 ; is_digit(*fmt) ; ++fmt) { fld_wid *= 10; fld_wid += value_of_digit(*fmt); } } else if (*fmt == '*') { /* the value is an integer taken from the arguments */ fld_wid = va_arg(args, int); /* skip the '*' */ ++fmt; } /* check for a precision specifier */ if (*fmt == '.') { /* skip the '.' */ ++fmt; /* check what we have */ if (*fmt == '*') { /* the value is an integer taken from the arguments */ fld_prec = va_arg(args, int); /* skip the '*' */ ++fmt; } else { /* scan the digits */ for (fld_prec = 0 ; is_digit(*fmt) ; ++fmt)