/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkScript_DEFINED
#define SkScript_DEFINED
#include "SkOperand.h"
#include "SkIntArray.h"
#include "SkTDict.h"
#include "SkTDStack.h"
class SkAnimateMaker;
class SkScriptEngine {
public:
enum Error {
kNoError,
kArrayIndexOutOfBounds,
kCouldNotFindReferencedID,
kDotOperatorExpectsObject,
kErrorInArrrayIndex,
kErrorInFunctionParameters,
kExpectedArray,
kExpectedBooleanExpression,
kExpectedFieldName,
kExpectedHex,
kExpectedIntForConditionOperator,
kExpectedNumber,
kExpectedNumberForArrayIndex,
kExpectedOperator,
kExpectedToken,
kExpectedTokenBeforeDotOperator,
kExpectedValue,
kHandleMemberFailed,
kHandleMemberFunctionFailed,
kHandleUnboxFailed,
kIndexOutOfRange,
kMismatchedArrayBrace,
kMismatchedBrackets,
kNoFunctionHandlerFound,
kPrematureEnd,
kTooManyParameters,
kTypeConversionFailed,
kUnterminatedString
};
enum SkOpType {
kNoType,
kInt = 1,
kScalar = 2,
kString = 4,
kArray = 8,
kObject = 16
// kStruct = 32
};
typedef bool (*_boxCallBack)(void* userStorage, SkScriptValue* result);
typedef bool (*_functionCallBack)(const char* func, size_t len, SkTDArray<SkScriptValue>& params,
void* userStorage, SkScriptValue* result);
typedef bool (*_memberCallBack)(const char* member, size_t len, void* object,
void* userStorage, SkScriptValue* result);
typedef bool (*_memberFunctionCallBack)(const char* member, size_t len, void* object,
SkTDArray<SkScriptValue>& params, void* userStorage, SkScriptValue* result);
// typedef bool (*_objectToStringCallBack)(void* object, void* userStorage, SkScriptValue* result);
typedef bool (*_propertyCallBack)(const char* prop, size_t len, void* userStorage, SkScriptValue* result);
typedef bool (*_unboxCallBack)(void* userStorage, SkScriptValue* result);
SkScriptEngine(SkOpType returnType);
~SkScriptEngine();
void boxCallBack(_boxCallBack func, void* userStorage);
bool convertTo(SkDisplayTypes , SkScriptValue* );
bool evaluateScript(const char** script, SkScriptValue* value);
void forget(SkTypedArray* array);
void functionCallBack(_functionCallBack func, void* userStorage);
Error getError() const { return fError; }
#ifdef SK_DEBUG
bool getErrorString(SkString* err) const;
#endif
void memberCallBack(_memberCallBack , void* userStorage);
void memberFunctionCallBack(_memberFunctionCallBack , void* userStorage);
// void objectToStringCallBack(_objectToStringCallBack , void* userStorage);
void propertyCallBack(_propertyCallBack prop, void* userStorage);
void track(SkTypedArray* array);
void track(SkString* string);
void unboxCallBack(_unboxCallBack func, void* userStorage);
static bool ConvertTo(SkScriptEngine* , SkDisplayTypes toType, SkScriptValue* value);
static SkScalar IntToScalar(int32_t );
static SkDisplayTypes ToDisplayType(SkOpType type);
static SkOpType ToOpType(SkDisplayTypes type);
static bool ValueToString(SkScriptValue value, SkString* string);
enum CallBackType {
kBox,
kFunction,
kMember,
kMemberFunction,
// kObjectToString,
kProperty,
kUnbox
};
struct UserCallBack {
CallBackType fCallBackType;
void* fUserStorage;
union {
_boxCallBack fBoxCallBack;
_functionCallBack fFunctionCallBack;
_memberCallBack fMemberCallBack;
_memberFunctionCallBack fMemberFunctionCallBack;
// _objectToStringCallBack fObjectToStringCallBack;
_propertyCallBack fPropertyCallBack;
_unboxCallBack fUnboxCallBack;
};
};
enum SkOp {
kUnassigned,
kAdd,
kAddInt = kAdd,
kAddScalar,
kAddString, // string concat
kArrayOp,
kBitAnd,
kBitNot,
kBitOr,
kDivide,
kDivideInt = kDivide,
kDivideScalar,
kElse,
kEqual,
kEqualInt = kEqual,
kEqualScalar,
kEqualString,
kFlipOps,
kGreaterEqual,
kGreaterEqualInt = kGreaterEqual,
kGreaterEqualScalar,
kGreaterEqualString,
kIf,
kLogicalAnd,
kLogicalNot,
kLogicalOr,
kMinus,
kMinusInt = kMinus,
kMinusScalar,
kModulo,
kModuloInt = kModulo,
kModuloScalar,
kMultiply,
kMultiplyInt = kMultiply,
kMultiplyScalar,
kParen,
kShiftLeft,
kShiftRight, // signed
kSubtract,
kSubtractInt = kSubtract,
kSubtractScalar,
kXor,
kArtificialOp = 0x40
};
enum SkOpBias {
kNoBias,
kTowardsNumber = 0,
kTowardsString
};
protected:
struct SkOperatorAttributes {
unsigned int fLeftType : 3; // SkOpType, but only lower values
unsigned int fRightType : 3; // SkOpType, but only lower values
SkOpBias fBias : 1;
};
struct SkSuppress { // !!! could be compressed to a long
SkOp fOperator; // operand which enabled suppression
int fOpStackDepth; // depth when suppression operator was found
SkBool8 fSuppress; // set if suppression happens now, as opposed to later
SkBool8 fElse; // set on the : half of ? :
};
static const SkOperatorAttributes gOpAttributes[];
static const signed char gPrecedence[];
int arithmeticOp(char ch, char nextChar, bool lastPush);
void commonCallBack(CallBackType type, UserCallBack& callBack, void* userStorage);
bool convertParams(SkTDArray<SkScriptValue>&, const SkFunctionParamType* ,
int paramTypeCount);
void convertToString(SkOperand& operand, SkDisplayTypes type) {
SkScriptValue scriptValue;
scriptValue.fOperand = operand;
scriptValue.fType = type;
convertTo(SkType_String, &scriptValue);
operand = scriptValue.fOperand;
}
bool evaluateDot(const char*& script, bool suppressed);
bool evaluateDotParam(const char*& script, bool suppressed, const char* field, size_t fieldLength);
bool functionParams(const char** scriptPtr, SkTDArray<SkScriptValue>& params);
bool handleArrayIndexer(const char** scriptPtr, bool suppressed);
bool handleBox(SkScriptValue* value);
bool handleFunction(const char** scriptPtr, bool suppressed);
bool handleMember(const char* field, size_t len, void* object);
bool handleMemberFunction(const char* field, size_t len, void* object, SkTDArray<SkScriptValue>& params);
// bool handleObjectToString(void* object);
bool handleProperty(bool suppressed);
bool handleUnbox(SkScriptValue* scriptValue);
bool innerScript(const char** scriptPtr, SkScriptValue* value);
int logicalOp(char ch, char nextChar);
Error opError();
bool processOp();
void setAnimateMaker(SkAnimateMaker* maker) { fMaker = maker; }
bool setError(Error , const char* pos);
enum SkBraceStyle {
// kStructBrace,
kArrayBrace,
kFunctionBrace
};
#if 0
SkIntArray(SkBraceStyle) fBraceStack; // curly, square, function paren
SkIntArray(SkOp) fOpStack;
SkIntArray(SkOpType) fTypeStack;
SkTDOperandArray fOperandStack;
SkTDArray<SkSuppress> fSuppressStack;
#else
SkTDStack<SkBraceStyle> fBraceStack; // curly, square, function paren
SkTDStack<SkOp> fOpStack;
SkTDStack<SkOpType> fTypeStack;
SkTDStack<SkOperand> fOperandStack;
SkTDStack<SkSuppress> fSuppressStack;
#endif
SkAnimateMaker* fMaker;
SkTDTypedArrayArray fTrackArray;
SkTDStringArray fTrackString;
const char* fToken; // one-deep stack
size_t fTokenLength;
SkTDArray<UserCallBack> fUserCallBacks;
SkOpType fReturnType;
Error fError;
int fErrorPosition;
private:
friend class SkTypedArray;
#ifdef SK_SUPPORT_UNITTEST
public:
static void UnitTest();
#endif
};
#ifdef SK_SUPPORT_UNITTEST
struct SkScriptNAnswer {
const char* fScript;
SkDisplayTypes fType;
int32_t fIntAnswer;
SkScalar fScalarAnswer;
const char* fStringAnswer;
};
#endif
#endif // SkScript_DEFINED