| 849 | |
| 850 | |
| 851 | HRESULT TokenToVarType(ExprTokenType &aToken, VARTYPE aVarType, void *apValue, bool aCallerIsComValue) |
| 852 | // Copy the value of a given token into a variable of the given VARTYPE. |
| 853 | { |
| 854 | if (aVarType == VT_VARIANT) |
| 855 | { |
| 856 | VariantClear((VARIANT *)apValue); |
| 857 | TokenToVariant(aToken, *(VARIANT *)apValue, FALSE); |
| 858 | return S_OK; |
| 859 | } |
| 860 | |
| 861 | #define U 0 // Unsupported in SAFEARRAY/VARIANT (but vt 15 has no assigned meaning). |
| 862 | #define P sizeof(void *) |
| 863 | // Unfortunately there appears to be no function to get the size of a given VARTYPE, |
| 864 | // and VariantCopyInd() copies in the wrong direction. An alternative approach to |
| 865 | // the following would be to switch(aVarType) and copy using the appropriate pointer |
| 866 | // type, but disassembly shows that approach produces larger code and internally uses |
| 867 | // an array of sizes like this anyway: |
| 868 | static char vt_size[] = {U,U,2,4,4,8,8,8,P,P,4,2,U,P,U,U,1,1,2,4,8,8,4,4,U,U,U,U,U,U,U,U,U,U,U,U,U,P,P}; |
| 869 | // Checking aCallerIsComValue has these purposes: |
| 870 | // - Let ComValue() accept a raw pointer/integer value for VT_BYREF, VT_ARRAY and |
| 871 | // any types not explicitly supported. |
| 872 | // - When an integer value is passed by ComValue(), copy all 64 bits. |
| 873 | size_t vsize = aCallerIsComValue ? 8 : (aVarType < _countof(vt_size)) ? vt_size[aVarType] : 0; |
| 874 | if (!vsize) |
| 875 | return DISP_E_BADVARTYPE; |
| 876 | #undef P |
| 877 | #undef U |
| 878 | |
| 879 | VARIANT src; |
| 880 | |
| 881 | if (aVarType == VT_BOOL) |
| 882 | { |
| 883 | // Use AutoHotkey's boolean evaluation rules, but VARIANT_TRUE == -1. |
| 884 | *((VARIANT_BOOL*)apValue) = -TokenToBOOL(aToken); |
| 885 | return S_OK; |
| 886 | } |
| 887 | |
| 888 | if (TypeOfToken(aToken) == SYM_INTEGER) |
| 889 | { |
| 890 | // This has a few uses: |
| 891 | // - Allows pointer types to be initialized by pointer value for ComValue(). |
| 892 | // - Avoids truncation or loss of precision for large integer values, |
| 893 | // since TokenToVariant() only uses the common VT_I4 or VT_R8 types. |
| 894 | // - Probably faster. |
| 895 | src.vt = VT_I8; |
| 896 | src.llVal = TokenToInt64(aToken); |
| 897 | switch (aVarType) |
| 898 | { |
| 899 | case VT_R4: |
| 900 | case VT_R8: |
| 901 | case VT_DATE: // Date is "double" based. |
| 902 | // Doesn't make sense to reinterpret the bits of an integer value as float. |
| 903 | break; |
| 904 | case VT_CY: |
| 905 | // This ensures 42 and 42.0 produce the same value. |
| 906 | src.llVal *= 10000; |
| 907 | *((CY*)apValue) = src.cyVal; |
| 908 | return S_OK; |
no test coverage detected