diff --git a/src/sbbs3/js_queue.c b/src/sbbs3/js_queue.c index c54774738582c4d5c1e1712ebfd3bb52e7c840c6..452c2b22174a7f7ff13d70fc588b8bf6581698a6 100644 --- a/src/sbbs3/js_queue.c +++ b/src/sbbs3/js_queue.c @@ -42,11 +42,9 @@ typedef struct { char name[128]; int type; - size_t length; union { JSBool b; - int32 i; - jsdouble d; + jsdouble n; char* s; } value; } queued_value_t; @@ -71,32 +69,56 @@ static void js_finalize_queue(JSContext *cx, JSObject *obj) JS_SetPrivate(cx, obj, NULL); } -static void parse_queued_value(JSContext *cx, queued_value_t* v, jsval* rval, BOOL peek) +static void parse_queued_value(JSContext *cx, JSObject *parent + ,queued_value_t* v, jsval* rval, BOOL peek) { + queued_value_t* pv; + queued_value_t term; + jsval prop_val; + jsuint index=0; + JSObject *obj; + + ZERO_VAR(term); + *rval = JSVAL_VOID; if(v==NULL) return; switch(v->type) { - case JSVAL_BOOLEAN: + case JSTYPE_BOOLEAN: *rval = BOOLEAN_TO_JSVAL(v->value.b); break; - case JSVAL_INT: - JS_NewNumberValue(cx,v->value.i,rval); - break; - case JSVAL_DOUBLE: - JS_NewNumberValue(cx,v->value.d,rval); + case JSTYPE_NUMBER: + JS_NewNumberValue(cx,v->value.n,rval); break; - case JSVAL_STRING: + case JSTYPE_STRING: if(v->value.s) { *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,v->value.s)); if(!peek) free(v->value.s); } break; + case JSTYPE_OBJECT: + obj = JS_DefineObject(cx, parent, v->name, NULL, NULL + ,JSPROP_ENUMERATE); + for(pv=v+1;memcmp(pv,&term,sizeof(term));pv++) { + parse_queued_value(cx,obj,pv,&prop_val,peek); + JS_DefineProperty(cx, obj, pv->name, prop_val + ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY); + } + *rval = OBJECT_TO_JSVAL(obj); + break; + case JSTYPE_ARRAY: + obj = JS_DefineObject(cx, parent, v->name, NULL, NULL + ,JSPROP_ENUMERATE); + for(pv=v+1;memcmp(pv,&term,sizeof(term));pv++) { + parse_queued_value(cx,obj,pv,&prop_val,peek); + JS_SetElement(cx,obj,index++,&prop_val); + } + *rval = OBJECT_TO_JSVAL(obj); + break; } - free(v); } /* Queue Object Methods */ @@ -145,7 +167,9 @@ js_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) } else v=msgQueueRead(q, /* timeout */0); - parse_queued_value(cx, v, rval, /* peek */FALSE); + parse_queued_value(cx, obj, v, rval, /* peek */FALSE); + + FREE_AND_NULL(v); return(JS_TRUE); } @@ -163,40 +187,96 @@ js_peek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) v=msgQueuePeek(q, /* timeout */0); - parse_queued_value(cx, v, rval, /* peek */TRUE); + parse_queued_value(cx, obj, v, rval, /* peek */TRUE); + + FREE_AND_NULL(v); return(JS_TRUE); } -BOOL js_enqueue_value(JSContext *cx, msg_queue_t* q, jsval val, char* name) +static queued_value_t* js_encode_value(JSContext *cx, jsval val, char* name + ,queued_value_t* v, size_t* count) { - queued_value_t v; - - ZERO_VAR(v); + jsint i; + jsval prop_name; + jsval prop_val; + JSObject* obj; + JSIdArray* id_array; + queued_value_t* nv; + + if((nv=realloc(v,((*count)+1)*sizeof(queued_value_t)))==NULL) { + if(v) free(v); + return(NULL); + } + v=nv; + nv=v+(*count); + memset(nv,0,sizeof(queued_value_t)); + (*count)++; if(name!=NULL) - SAFECOPY(v.name,name); + SAFECOPY(nv->name,name); - switch(v.type=JSVAL_TAG(val)) { + switch(JSVAL_TAG(val)) { case JSVAL_BOOLEAN: - v.length = sizeof(JSBool); - v.value.b=JSVAL_TO_BOOLEAN(val); + nv->type=JSTYPE_BOOLEAN; + nv->value.b=JSVAL_TO_BOOLEAN(val); break; - case JSVAL_DOUBLE: - v.length =sizeof(jsdouble); - v.value.d = *JSVAL_TO_DOUBLE(val); + case JSVAL_OBJECT: + nv->type=JSTYPE_ARRAY; + obj = JSVAL_TO_OBJECT(val); + + if(JSVAL_IS_NULL(val)) + break; + + if(JS_IsArrayObject(cx, obj)) + nv->type=JSTYPE_ARRAY; + + if((id_array=JS_Enumerate(cx,obj))==NULL) { + free(v); + return(NULL); + } + for(i=0; i<id_array->length; i++) { + /* property name */ + JS_IdToValue(cx,id_array->vector[i],&prop_name); + if(JSVAL_IS_STRING(prop_name)) { + name=JS_GetStringBytes(JSVAL_TO_STRING(prop_name)); + /* value */ + JS_GetProperty(cx,obj,name,&prop_val); + } else { + name=NULL; + JS_GetElement(cx,obj,i,&prop_val); + } + if((v=js_encode_value(cx,prop_val,name,v,count))==NULL) + break; + } + v=js_encode_value(cx,JSVAL_NULL,NULL,v,count); /* terminate object */ break; default: if(JSVAL_IS_NUMBER(val)) { - v.type = JSVAL_INT; - JS_ValueToInt32(cx,val,&v.value.i); + nv->type = JSTYPE_NUMBER; + JS_ValueToNumber(cx,val,&nv->value.n); } else { - v.type= JSVAL_STRING; - v.value.s = strdup(JS_GetStringBytes(JS_ValueToString(cx,val))); + nv->type= JSTYPE_STRING; + nv->value.s = strdup(JS_GetStringBytes(JS_ValueToString(cx,val))); } break; } - return(msgQueueWrite(q,&v,sizeof(v))); + + return(v); +} + +BOOL js_enqueue_value(JSContext *cx, msg_queue_t* q, jsval val, char* name) +{ + queued_value_t* v; + size_t count=0; + BOOL result; + + if((v=js_encode_value(cx,val,name,NULL,&count))==NULL || count<1) + return(FALSE); + + result=msgQueueWrite(q,v,count*sizeof(queued_value_t)); + free(v); + return(result); } static JSBool