2012-05-08 13 views
5

Ha pasado mucho tiempo desde que utilicé C++, e incluso más tiempo desde que envolví mi cabeza en los tipos duros. Simplemente estoy buscando un trabajando un liner para obtener un argumento de v8, o un valor predeterminado cuando no se proporcionó un argumento.¿La forma más corta (una línea) para obtener un argumento predeterminado de una función v8?

v8::String::Utf8Value arg0(args[0]); 
v8::String::Utf8Value arg1(args[1]); 
v8::String::Utf8Value arg2(args[2]); 
const char *username = (args.Length() > 0) ? *arg0 : ""; 
const char *password = (args.Length() > 1) ? *arg1 : ""; 
const char *service = (args.Length() > 2) ? *arg2 : "login"; 

Salidas:

 
func(); // { username: "", password: "", service: "login" } 
func('1'); // { username: "1", password: "", service: "login" } 
func('1', '2'); // { username: "1", password: "2", service: "login" } 
func('a', 'b', 'c'); // { username: "a", password: "b", service: "c" } 

Por desgracia, la seguía de cerca-a-ideales solución no funciona para mí (cualquier idea por qué?):

const char *username = (args.Length() > 0) ? *v8::String::Utf8Value(args[0]->ToString()) : ""; 
const char *password = (args.Length() > 1) ? *v8::String::Utf8Value(args[1]->ToString()) : ""; 
const char *service = (args.Length() > 2) ? *v8::String::Utf8Value(args[2]->ToString()) : "login"; 
+0

voy a admitir que no sé demasiado sobre v8, pero su reemplazo se ve poderoso sospechoso de un C++ POV para mí: cuando los destructores do arg0/arg1/arg2 de correr? ¿Cuándo se ejecutan esos destructores en tu línea única? ¿Qué sucede con la memoria asignada cuando se ejecuta el destructor de la clase? – hvd

+0

Hah, oh Dios ...afaik (aparte del hecho de que todo en v8 es estático y horrible para la administración de memoria porque es un motor JS que necesita acceso a todo en todas partes): args * might * se destruirá una vez que mi función regrese ... pero ... es muy posible ese v8 se cuelga en los datos para su "seguimiento de pila" interno. Básicamente, no lo sé de manera positiva, definitivamente estaré perfilando el código cuando esté terminado. ;) –

+0

Convoluted one liners no son exactamente las soluciones "más limpias". –

Respuesta

8

Vyacheslav Egorov clavó con su comentario, en el momento en que estaba accediendo a la cuerda, había sido destruida. En última instancia Terminé usando:

char *get(v8::Local<v8::Value> value, const char *fallback = "") { 
    if (value->IsString()) { 
     v8::String::AsciiValue string(value); 
     char *str = (char *) malloc(string.length() + 1); 
     strcpy(str, *string); 
     return str; 
    } 
    char *str = (char *) malloc(strlen(fallback) + 1); 
    strcpy(str, fallback); 
    return str; 
} 

uso Ejemplo:

v8::Handle<v8::Value> myMethod(const v8::Arguments &args) { 
    char *username = get(args[0], "user"); 
    char *password = get(args[1], "pass"); 

    ... 
} 
+2

P.S. Aceptaré una mejor respuesta que la mía. Realmente odio responder mis propias preguntas. –

3

Este trozo de código funcionó bien para mí para extraer un valor de cadena de un valor V8 en una línea:

std::string tempString(*v8::String::Utf8Value(args[someInteger])); 

El constructor std :: string debe manejar sus escenarios predeterminados sin necesidad de código adicional, pero si necesita verificar manualmente los valores nulos, esto es trivial.

Este código sirve de ejemplo, obtiene valores de cadena de todos los argumentos y los imprime en stdout, y por supuesto los pone en una buena matriz, porque ¿para qué sirve imprimirlos?

std::string* printAllArgs(const Arguments& args){ 
    std::cout << "PRINTING ALL ARGS: "; 
    std::string* stringArray = new std::string[args.Length()]; 
    for(int i = 0; i < args.Length(); i++){ 
     std::string tempString(*v8::String::Utf8Value(args[i])); 
     stringArray[i] = tempString; 
     std::cout << tempString << ";"; 
    } 
    return stringArray; 
} 
2

Egorov es correcto en que el AsciiValue objeto temporal ha sido destruida automóvil como un puntero inteligente en la notación compacta:

const char *username = *v8::String::Utf8Value(args[0]->ToString()); 
//transient AsciiValue object has gone out of scope, and its destructor has been called in 
// previous line, rendering the pointer (content) invalid henceforth! 
... 

Esto se debe a la AsciiValue ha ido fuera de campo en esa sola alcance de línea

En su lugar, debe dividirla en 2 líneas si tiene intención de utilizar el puntero 'caché' varias veces:

{ 
    v8::String::Utf8Value usernameObj(args[0]->ToString()); 
    const char *username = *usernameObj; 
    ... 
    //use username pointer as often as desired; it remains valid in this entire scope. 
    doSomethingWithString(username); //OK 

    //can also dereference Utf8Value object only when needed: 
    doSomethingWithString(*usernameObj); //OK 
} 
//here, usernameObj is out of scope and is destroyed, and username will become invalid. 

Si tan sólo la intención de utilizar el valor de cadena una vez, sigue siendo perfectamente bien usar la notación compacta:

doSomethingWithString(*v8::String::Utf8Value(args[0]->ToString())); //OK 

la función doSomethingWithString obtiene el valor correcto para trabajar. Solo después de regresar de él, el Utf8Value si se destruye automáticamente.

Lo mismo ocurre con String :: AsciiValue.

0
string bi = info[0]->IsUndefined() ? "backwardIndex.dat" : string(*Nan::Utf8String(info[0])); 
Cuestiones relacionadas