/* * 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