"Fossies" - the Fresh Open Source Software Archive

Member "AutoHotkey_L-1.1.33.09/source/script_object.h" (8 May 2021, 15037 Bytes) of package /windows/misc/AutoHotkey_L-1.1.33.09.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "script_object.h" see the Fossies "Dox" file reference documentation.

    1 #pragma once
    2 
    3 #define INVOKE_TYPE         (aFlags & IT_BITMASK)
    4 #define IS_INVOKE_SET       (aFlags & IT_SET)
    5 #define IS_INVOKE_GET       (INVOKE_TYPE == IT_GET)
    6 #define IS_INVOKE_CALL      (aFlags & IT_CALL)
    7 #define IS_INVOKE_META      (aFlags & IF_METAOBJ)
    8 #define SHOULD_INVOKE_METAFUNC (aFlags & IF_METAFUNC)
    9 
   10 #define INVOKE_NOT_HANDLED  CONDITION_FALSE
   11 
   12 enum ObjectMethodID { // Partially ported from v2 BuiltInFunctionID.  Used for code sharing.
   13     FID_ObjInsertAt, FID_ObjDelete, FID_ObjRemoveAt, FID_ObjPush, FID_ObjPop, FID_ObjLength
   14     , FID_ObjHasKey, FID_ObjGetCapacity, FID_ObjSetCapacity, FID_ObjGetAddress, FID_ObjClone
   15     , FID_ObjNewEnum, FID_ObjMaxIndex, FID_ObjMinIndex, FID_ObjRemove, FID_ObjInsert
   16     , FID_ObjCount
   17 };
   18 
   19 
   20 //
   21 // ObjectBase - Common base class, implements reference counting.
   22 //
   23 
   24 class DECLSPEC_NOVTABLE ObjectBase : public IObjectComCompatible
   25 {
   26 protected:
   27     ULONG mRefCount;
   28     
   29     virtual bool Delete()
   30     {
   31         delete this; // Derived classes MUST be instantiated with 'new' or override this function.
   32         return true; // See Release() for comments.
   33     }
   34 
   35 public:
   36     ULONG STDMETHODCALLTYPE AddRef()
   37     {
   38         return ++mRefCount;
   39     }
   40 
   41     ULONG STDMETHODCALLTYPE Release()
   42     {
   43         if (mRefCount == 1)
   44         {
   45             // If an object is implemented by script, it may need to run cleanup code before the object
   46             // is deleted.  This introduces the possibility that before it is deleted, the object ref
   47             // is copied to another variable (AddRef() is called).  To gracefully handle this, let
   48             // implementors decide when to delete and just decrement mRefCount if it doesn't happen.
   49             if (Delete())
   50                 return 0;
   51             // Implementor has ensured Delete() returns false only if delete wasn't called (due to
   52             // remaining references to this), so we must assume mRefCount > 1.  If Delete() really
   53             // deletes the object and (erroneously) returns false, checking if mRefCount is still
   54             // 1 may be just as unsafe as decrementing mRefCount as per usual.
   55         }
   56         return --mRefCount;
   57     }
   58 
   59     ObjectBase() : mRefCount(1) {}
   60 
   61     // Declare a virtual destructor for correct 'delete this' behaviour in Delete(),
   62     // and because it is likely to be more convenient and reliable than overriding
   63     // Delete(), especially with a chain of derived types.
   64     virtual ~ObjectBase() {}
   65 
   66 #ifdef CONFIG_DEBUGGER
   67     void DebugWriteProperty(IDebugProperties *, int aPage, int aPageSize, int aDepth);
   68 #endif
   69 };  
   70 
   71 
   72 //
   73 // EnumBase - Base class for enumerator objects following standard syntax.
   74 //
   75 
   76 class DECLSPEC_NOVTABLE EnumBase : public ObjectBase
   77 {
   78 public:
   79     ResultType STDMETHODCALLTYPE Invoke(ExprTokenType &aResultToken, ExprTokenType &aThisToken, int aFlags, ExprTokenType *aParam[], int aParamCount);
   80     virtual int Next(Var *aOutputVar1, Var *aOutputVar2) = 0;
   81 };
   82     
   83 
   84 //
   85 // Property: Invoked when a derived object gets/sets the corresponding key.
   86 //
   87 
   88 class Property : public ObjectBase
   89 {
   90 public:
   91     Func *mGet, *mSet;
   92 
   93     bool CanGet() { return mGet; }
   94     bool CanSet() { return mSet; }
   95 
   96     Property() : mGet(NULL), mSet(NULL) { }
   97     
   98     ResultType STDMETHODCALLTYPE Invoke(ExprTokenType &aResultToken, ExprTokenType &aThisToken, int aFlags, ExprTokenType *aParam[], int aParamCount);
   99     IObject_Type_Impl("Property")
  100 };
  101 
  102 
  103 //
  104 // Object - Scriptable associative array.
  105 //
  106 
  107 class Object : public ObjectBase
  108 {
  109 protected:
  110     typedef INT_PTR IntKeyType; // Same size as the other union members.
  111     typedef INT_PTR IndexType; // Type of index for the internal array.  Must be signed for FindKey to work correctly.
  112     union KeyType // Which of its members is used depends on the field's position in the mFields array.
  113     {
  114         LPTSTR s;
  115         IntKeyType i;
  116         IObject *p;
  117     };
  118     struct FieldType
  119     {
  120         union { // Which of its members is used depends on the value of symbol, below.
  121             __int64 n_int64;    // for SYM_INTEGER
  122             double n_double;    // for SYM_FLOAT
  123             IObject *object;    // for SYM_OBJECT
  124             struct {
  125                 LPTSTR marker;      // for SYM_OPERAND
  126                 size_t size;        // for SYM_OPERAND; allows reuse of allocated memory. For UNICODE: count in characters
  127             };
  128         };
  129         // key and symbol probably need to be adjacent to each other to conserve memory due to 8-byte alignment.
  130         KeyType key;
  131         SymbolType symbol;
  132         
  133         inline IntKeyType CompareKey(IntKeyType val) { return val - key.i; }  // Used by both int and object since they are stored separately.
  134         inline int CompareKey(LPTSTR val) { return _tcsicmp(val, key.s); }
  135 
  136         bool Assign(LPTSTR str, size_t len = -1, bool exact_size = false);
  137         bool Assign(ExprTokenType &val);
  138         void Get(ExprTokenType &result);
  139         void Free();
  140     
  141         inline void ToToken(ExprTokenType &aToken) // Used when we want the value as is, in a token.  Does not AddRef() or copy strings.
  142         {
  143             aToken.value_int64 = n_int64; // Union copy. Overlaps with buf on x86 builds, so do it first.
  144             if ((aToken.symbol = symbol) == SYM_OPERAND)
  145                 aToken.buf = NULL; // Indicate that this SYM_OPERAND token LACKS a pre-converted binary integer.
  146         }
  147     };
  148 
  149     class Enumerator : public EnumBase
  150     {
  151         Object *mObject;
  152         IndexType mOffset;
  153     public:
  154         Enumerator(Object *aObject) : mObject(aObject), mOffset(-1) { mObject->AddRef(); }
  155         ~Enumerator() { mObject->Release(); }
  156         int Next(Var *aKey, Var *aVal);
  157         IObject_Type_Impl("Object.Enumerator")
  158     };
  159     
  160     IObject *mBase;
  161     FieldType *mFields;
  162     IndexType mFieldCount, mFieldCountMax; // Current/max number of fields.
  163 
  164     // Holds the index of first key of a given type within mFields.  Must be in the order: int, object, string.
  165     // Compared to storing the key-type with each key-value pair, this approach saves 4 bytes per key (excluding
  166     // the 8 bytes taken by the two fields below) and speeds up lookups since only the section within mFields
  167     // with the appropriate type of key needs to be searched (and no need to check the type of each key).
  168     // mKeyOffsetObject should be set to mKeyOffsetInt + the number of int keys.
  169     // mKeyOffsetString should be set to mKeyOffsetObject + the number of object keys.
  170     // mKeyOffsetObject-1, mKeyOffsetString-1 and mFieldCount-1 indicate the last index of each prior type.
  171     static const IndexType mKeyOffsetInt = 0;
  172     IndexType mKeyOffsetObject, mKeyOffsetString;
  173 
  174 #ifdef CONFIG_DEBUGGER
  175     friend class Debugger;
  176 #endif
  177 
  178     Object()
  179         : mBase(NULL)
  180         , mFields(NULL), mFieldCount(0), mFieldCountMax(0)
  181         , mKeyOffsetObject(0), mKeyOffsetString(0)
  182     {}
  183 
  184     bool Delete();
  185     ~Object();
  186 
  187     template<typename T>
  188     FieldType *FindField(T val, IndexType left, IndexType right, IndexType &insert_pos);
  189     FieldType *FindField(SymbolType key_type, KeyType key, IndexType &insert_pos);  
  190     FieldType *FindField(ExprTokenType &key_token, LPTSTR aBuf, SymbolType &key_type, KeyType &key, IndexType &insert_pos);
  191     
  192     FieldType *Insert(SymbolType key_type, KeyType key, IndexType at);
  193 
  194     bool SetInternalCapacity(IndexType new_capacity);
  195     bool Expand()
  196     // Expands mFields by at least one field.
  197     {
  198         return SetInternalCapacity(mFieldCountMax ? mFieldCountMax * 2 : 4);
  199     }
  200     
  201     ResultType CallField(FieldType *aField, ExprTokenType &aResultToken, ExprTokenType &aThisToken, int aFlags, ExprTokenType *aParam[], int aParamCount);
  202     
  203 public:
  204     static Object *Create(ExprTokenType *aParam[] = NULL, int aParamCount = 0);
  205     static Object *CreateArray(ExprTokenType *aValue[] = NULL, int aValueCount = 0);
  206     static Object *CreateFromArgV(LPTSTR *aArgV, int aArgC);
  207 
  208     bool Append(LPTSTR aValue, size_t aValueLength = -1);
  209 
  210     // Used by Func::Call() for variadic functions/function-calls:
  211     Object *Clone(BOOL aExcludeIntegerKeys = false);
  212     void ArrayToParams(ExprTokenType *token, ExprTokenType **param_list, int extra_params, ExprTokenType **aParam, int aParamCount);
  213     ResultType ArrayToStrings(LPTSTR *aStrings, int &aStringCount, int aStringsMax);
  214     
  215     inline bool GetNextItem(ExprTokenType &aToken, INT_PTR &aOffset, INT_PTR &aKey)
  216     {
  217         if (++aOffset >= mKeyOffsetObject) // i.e. no more integer-keyed items.
  218             return false;
  219         FieldType &field = mFields[aOffset];
  220         aKey = field.key.i;
  221         field.ToToken(aToken);
  222         return true;
  223     }
  224 
  225     inline bool GetItemOffset(ExprTokenType &aToken, INT_PTR aOffset)
  226     {
  227         if (aOffset >= mKeyOffsetObject)
  228             return false;
  229         mFields[aOffset].ToToken(aToken);
  230         return true;
  231     }
  232 
  233     int GetNumericItemCount()
  234     {
  235         return (int)mKeyOffsetObject;
  236     }
  237 
  238     bool GetItem(ExprTokenType &aToken, ExprTokenType &aKey)
  239     {
  240         IndexType insert_pos;
  241         TCHAR buf[MAX_NUMBER_SIZE];
  242         SymbolType key_type;
  243         KeyType key;
  244         FieldType *field = FindField(aKey, buf, key_type, key, insert_pos);
  245         if (!field)
  246             return false;
  247         field->ToToken(aToken);
  248         return true;
  249     }
  250     
  251     bool GetItem(ExprTokenType &aToken, LPTSTR aKey)
  252     {
  253         ExprTokenType key;
  254         key.symbol = SYM_OPERAND;
  255         key.marker = aKey;
  256         key.buf = NULL;
  257         return GetItem(aToken, key);
  258     }
  259     
  260     bool SetItem(ExprTokenType &aKey, ExprTokenType &aValue)
  261     {
  262         IndexType insert_pos;
  263         TCHAR buf[MAX_NUMBER_SIZE];
  264         SymbolType key_type;
  265         KeyType key;
  266         FieldType *field = FindField(aKey, buf, key_type, key, insert_pos);
  267         if (!field && !(field = Insert(key_type, key, insert_pos))) // Relies on short-circuit boolean evaluation.
  268             return false;
  269         return field->Assign(aValue);
  270     }
  271 
  272     bool SetItem(LPTSTR aKey, ExprTokenType &aValue)
  273     {
  274         ExprTokenType key;
  275         key.symbol = SYM_OPERAND;
  276         key.marker = aKey;
  277         key.buf = NULL;
  278         return SetItem(key, aValue);
  279     }
  280 
  281     bool SetItem(LPTSTR aKey, __int64 aValue)
  282     {
  283         ExprTokenType token;
  284         token.symbol = SYM_INTEGER;
  285         token.value_int64 = aValue;
  286         return SetItem(aKey, token);
  287     }
  288 
  289     bool SetItem(LPTSTR aKey, IObject *aValue)
  290     {
  291         ExprTokenType token;
  292         token.symbol = SYM_OBJECT;
  293         token.object = aValue;
  294         return SetItem(aKey, token);
  295     }
  296     
  297     void ReduceKeys(INT_PTR aAmount)
  298     {
  299         for (IndexType i = 0; i < mKeyOffsetObject; ++i)
  300             mFields[i].key.i -= aAmount;
  301     }
  302 
  303     int MinIndex() { return (mKeyOffsetInt < mKeyOffsetObject) ? (int)mFields[0].key.i : 0; }
  304     int MaxIndex() { return (mKeyOffsetInt < mKeyOffsetObject) ? (int)mFields[mKeyOffsetObject-1].key.i : 0; }
  305     bool HasNonnumericKeys() { return mKeyOffsetObject < mFieldCount; }
  306 
  307     void SetBase(IObject *aNewBase)
  308     { 
  309         if (aNewBase)
  310             aNewBase->AddRef();
  311         if (mBase)
  312             mBase->Release();
  313         mBase = aNewBase;
  314     }
  315 
  316     IObject *Base() 
  317     {
  318         return mBase; // Callers only want to call Invoke(), so no AddRef is done.
  319     }
  320     
  321     LPTSTR Type();
  322     // Used by Object::_Insert() and Func::Call():
  323     bool InsertAt(INT_PTR aOffset, INT_PTR aKey, ExprTokenType *aValue[], int aValueCount);
  324 
  325     void EndClassDefinition();
  326     Object *GetUnresolvedClass(LPTSTR &aName);
  327     
  328     ResultType STDMETHODCALLTYPE Invoke(ExprTokenType &aResultToken, ExprTokenType &aThisToken, int aFlags, ExprTokenType *aParam[], int aParamCount);
  329 
  330     int GetBuiltinID(LPCTSTR aName);
  331     ResultType CallBuiltin(int aID, ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  332 
  333     ResultType _Insert(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  334     ResultType _InsertAt(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  335     ResultType _Push(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  336     
  337     enum RemoveMode { RM_RemoveKeyOrIndex, RM_RemoveKey, RM_RemoveAt, RM_Pop };
  338     ResultType _Remove_impl(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount, RemoveMode aMode);
  339     ResultType _Remove(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  340     ResultType _Delete(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  341     ResultType _RemoveAt(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  342     ResultType _Pop(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  343     
  344     ResultType _GetCapacity(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  345     ResultType _SetCapacity(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  346     ResultType _GetAddress(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  347     ResultType _Count(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  348     ResultType _Length(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  349     ResultType _MaxIndex(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  350     ResultType _MinIndex(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  351     ResultType _NewEnum(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  352     ResultType _HasKey(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  353     ResultType _Clone(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  354 
  355     static LPTSTR sMetaFuncName[];
  356 
  357 #ifdef CONFIG_DEBUGGER
  358     void DebugWriteProperty(IDebugProperties *, int aPage, int aPageSize, int aDepth);
  359 #endif
  360 };
  361 
  362 
  363 //
  364 // MetaObject:  Used only by g_MetaObject (not every meta-object); see comments below.
  365 //
  366 class MetaObject : public Object
  367 {
  368 public:
  369     // In addition to ensuring g_MetaObject is never "deleted", this avoids a
  370     // tiny bit of work when any reference to this object is added or released.
  371     // Temporary references such as when evaluating "".base.foo are most common.
  372     ULONG STDMETHODCALLTYPE AddRef() { return 1; }
  373     ULONG STDMETHODCALLTYPE Release() { return 1; }
  374     bool Delete() { return false; }
  375 
  376     ResultType STDMETHODCALLTYPE Invoke(ExprTokenType &aResultToken, ExprTokenType &aThisToken, int aFlags, ExprTokenType *aParam[], int aParamCount);
  377 };
  378 
  379 extern MetaObject g_MetaObject;     // Defines "object" behaviour for non-object values.
  380 
  381 
  382 //
  383 // BoundFunc
  384 //
  385 
  386 class BoundFunc : public ObjectBase
  387 {
  388     IObject *mFunc; // Future use: bind a BoundFunc or other object.
  389     Object *mParams;
  390     int mFlags;
  391     BoundFunc(IObject *aFunc, Object *aParams, int aFlags)
  392         : mFunc(aFunc), mParams(aParams), mFlags(aFlags)
  393     {}
  394 
  395 public:
  396     static BoundFunc *Bind(IObject *aFunc, ExprTokenType **aParam, int aParamCount, int aFlags);
  397     ~BoundFunc();
  398 
  399     ResultType STDMETHODCALLTYPE Invoke(ExprTokenType &aResultToken, ExprTokenType &aThisToken, int aFlags, ExprTokenType *aParam[], int aParamCount);
  400     IObject_Type_Impl("BoundFunc")
  401 };
  402 
  403 
  404 //
  405 // RegExMatchObject:  Returned by RegExMatch via UnquotedOutputVar.
  406 //
  407 class RegExMatchObject : public ObjectBase
  408 {
  409     LPTSTR mHaystack;
  410     int mHaystackStart;
  411     int *mOffset;
  412     LPTSTR *mPatternName;
  413     int mPatternCount;
  414     LPTSTR mMark;
  415 
  416     RegExMatchObject() : mHaystack(NULL), mOffset(NULL), mPatternName(NULL), mPatternCount(0), mMark(NULL) {}
  417     
  418     ~RegExMatchObject()
  419     {
  420         if (mHaystack)
  421             free(mHaystack);
  422         if (mOffset)
  423             free(mOffset);
  424         if (mPatternName)
  425         {
  426             // Free the strings:
  427             for (int p = 1; p < mPatternCount; ++p) // Start at 1 since 0 never has a name.
  428                 if (mPatternName[p])
  429                     free(mPatternName[p]);
  430             // Free the array:
  431             free(mPatternName);
  432         }
  433         if (mMark)
  434             free(mMark);
  435     }
  436 
  437 public:
  438     static RegExMatchObject *Create(LPCTSTR aHaystack, int *aOffset, LPCTSTR *aPatternName
  439         , int aPatternCount, int aCapturedPatternCount, LPCTSTR aMark);
  440     
  441     ResultType STDMETHODCALLTYPE Invoke(ExprTokenType &aResultToken, ExprTokenType &aThisToken, int aFlags, ExprTokenType *aParam[], int aParamCount);
  442     IObject_Type_Impl("RegExMatch")
  443 
  444 #ifdef CONFIG_DEBUGGER
  445     void DebugWriteProperty(IDebugProperties *, int aPage, int aPageSize, int aDepth);
  446 #endif
  447 };