Better embedding API support (and tests!) for strings with null bytes.
- Test that a foreign method can return strings. - Test that a foreign method can return a string with null bytes. - Test wrenCall(). - Allow passing NULL for "v" to wrenCall(). - Allow "a" for passing an explicit length byte array to wrenCall().
This commit is contained in:
+3
-3
@@ -172,7 +172,7 @@ static void initVM()
|
||||
static void freeVM()
|
||||
{
|
||||
schedulerReleaseMethods();
|
||||
|
||||
|
||||
uv_loop_close(loop);
|
||||
free(loop);
|
||||
|
||||
@@ -259,8 +259,8 @@ uv_loop_t* getLoop()
|
||||
return loop;
|
||||
}
|
||||
|
||||
void setForeignCallbacks(
|
||||
WrenBindForeignMethodFn bindMethod, WrenBindForeignClassFn bindClass)
|
||||
void setTestCallbacks(WrenBindForeignMethodFn bindMethod,
|
||||
WrenBindForeignClassFn bindClass)
|
||||
{
|
||||
bindMethodFn = bindMethod;
|
||||
bindClassFn = bindClass;
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ uv_loop_t* getLoop();
|
||||
//
|
||||
// Used by the API test executable to let it wire up its own foreign functions.
|
||||
// This must be called before calling [createVM()].
|
||||
void setForeignCallbacks(WrenBindForeignMethodFn bindMethod,
|
||||
WrenBindForeignClassFn bindClass);
|
||||
void setTestCallbacks(WrenBindForeignMethodFn bindMethod,
|
||||
WrenBindForeignClassFn bindClass);
|
||||
|
||||
#endif
|
||||
|
||||
+14
-4
@@ -213,8 +213,15 @@ WrenValue* wrenGetMethod(WrenVM* vm, const char* module, const char* variable,
|
||||
// will allocate its own string and copy the characters from this, so
|
||||
// you don't have to worry about the lifetime of the string you pass to
|
||||
// Wren.
|
||||
// - "a" - An array of bytes converted to a Wren String. This requires two
|
||||
// consecutive arguments in the argument list: `const char*` pointing
|
||||
// to the array of bytes, followed by an `int` defining the length of
|
||||
// the array. This is used when the passed string may contain null
|
||||
// bytes, or just to avoid the implicit `strlen()` call of "s" if you
|
||||
// happen to already know the length.
|
||||
// - "v" - A previously acquired WrenValue*. Passing this in does not implicitly
|
||||
// release the value.
|
||||
// release the value. If the passed argument is NULL, this becomes a
|
||||
// Wren NULL.
|
||||
//
|
||||
// [method] must have been created by a call to [wrenGetMethod]. If [result] is
|
||||
// not `NULL`, the return value of the method will be stored in a new
|
||||
@@ -302,9 +309,12 @@ void wrenReturnDouble(WrenVM* vm, double value);
|
||||
// Provides a string return value for a foreign call.
|
||||
//
|
||||
// The [text] will be copied to a new string within Wren's heap, so you can
|
||||
// free memory used by it after this is called. If [length] is non-zero, Wren
|
||||
// will copy that many bytes from [text]. If it is -1, then the length of
|
||||
// [text] will be calculated using `strlen()`.
|
||||
// free memory used by it after this is called.
|
||||
//
|
||||
// If [length] is non-zero, Wren copies that many bytes from [text], including
|
||||
// any null bytes. If it is -1, then the length of [text] is calculated using
|
||||
// `strlen()`. If the string may contain any null bytes in the middle, then you
|
||||
// must pass an explicit length.
|
||||
void wrenReturnString(WrenVM* vm, const char* text, int length);
|
||||
|
||||
// Provides the return value for a foreign call.
|
||||
|
||||
+15
-3
@@ -1334,17 +1334,29 @@ WrenInterpretResult wrenCall(WrenVM* vm, WrenValue* method, WrenValue** result,
|
||||
Value value = NULL_VAL;
|
||||
switch (*argType)
|
||||
{
|
||||
case 'a':
|
||||
{
|
||||
const char* bytes = va_arg(argList, const char*);
|
||||
int length = va_arg(argList, int);
|
||||
value = wrenNewString(vm, bytes, (size_t)length);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'b': value = BOOL_VAL(va_arg(argList, int)); break;
|
||||
case 'd': value = NUM_VAL(va_arg(argList, double)); break;
|
||||
case 'i': value = NUM_VAL((double)va_arg(argList, int)); break;
|
||||
case 'n': value = NULL_VAL; va_arg(argList, void*); break;
|
||||
case 's':
|
||||
{
|
||||
value = wrenStringFormat(vm, "$", va_arg(argList, const char*));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'v': value = va_arg(argList, WrenValue*)->value; break;
|
||||
case 'v':
|
||||
{
|
||||
// Allow a NULL value pointer for Wren null.
|
||||
WrenValue* wrenValue = va_arg(argList, WrenValue*);
|
||||
if (wrenValue != NULL) value = wrenValue->value;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ASSERT(false, "Unknown argument type.");
|
||||
|
||||
Reference in New Issue
Block a user