[v2.0.2]cJson--created by dll

Post your working scripts, libraries and tools.
User avatar
Mono919
Posts: 71
Joined: 05 May 2022, 02:36

[v2.0.2]cJson--created by dll

Post by Mono919 » 04 Feb 2023, 05:15

just dllcall cjson.dll
json := cJson()
you can use:
json.parse(text)
json.get() => toahktype (expect for cJsonArray and cJsonObject)
json.getType() => return a type number
json.has([item\index]) => for cJsonArray and cJsonObject
json[item] => return a new cJson() contains new cJsonItem, is do not has, return cJson.Null()
json.length => for cJsonArray to get length
json.type => equal to json.getType()

Source Code:

Code: Select all

flag := cJson.dll_file("cjson\lib\cJson.dll")
if flag
    dllcall("LoadLibrary", "str", flag)
else
    throw error("cJson.dll is not existed.")

class cJson
{
    static cJSON_False := 0
    static cJSON_True := 1
    static cJSON_NULL := 2
    static cJSON_Number := 3
    static cJSON_String := 4
    static cJSON_Array := 5
    static cJSON_Object := 6
    static cJSON_IsReference := 256
    static cJSON_StringIsConst := 512
    
    __new(jsonPtr := cJson.Null())
    {
        this.jsonPtr := 0
        if !(jsonPtr is cJson.Null)
            this.jsonPtr := jsonPtr
    }
    
    __call(name, param)
    {
        if substr(name, 1, 2) = "is"
        {
            if this.jsonPtr
                return cJson.%"cJSON_" name%(this.jsonPtr)
            return false
        }
    }
    
    __item[key]
    {
        get
        {
            try
            {
                if this.type = cJson.cJSON_Array
                {
                    return cJson(cJson.cJSON_GetArrayItem(this.jsonPtr, key))
                }
                else if this.type = cJson.cJSON_Object
                {
                    return cJson(cJson.cJSON_GetObjectItem(this.jsonPtr, key))
                }
            }
            return cJson.Null()
        }
    }
    
    get()
    {
        if this.type = cJson.cJSON_Number
            return cJson.cJSON_GetNumberValue(this.jsonPtr)
        else if this.type = cJson.cJSON_String
            return cJson.cJSON_GetStringValue(this.jsonPtr)
        else if this.type = cJson.cJSON_True
            return cJson.Boolean(true)
        else if this.type = cJson.cJSON_False
            return cJson.Boolean(false)
        else if this.type = cJson.cJSON_Array
        {
            ret := []
            loop this.length
                ret.push(this[a_index - 1].get())
            return ret
        }
        else if this.type = cJson.cJSON_Object
            return this
        return cJson.Null()
    }
    
    getType()
    {
        switch true
        {
            case this.IsFalse():
                return cJson.cJSON_False
            case this.IsTrue():
                return cJson.cJSON_True
            case this.IsNull():
                return cJson.cJSON_NULL
            case this.IsNumber():
                return cJson.cJSON_Number
            case this.IsString():
                return cJson.cJSON_String
            case this.IsArray():
                return cJson.cJSON_Array
            case this.IsObject():
                return cJson.cJSON_Object
            default:
                return -1
        }
    }
    
    has(key)
    {
        if this.type = cJson.cJSON_Array
            return isnumber(key) && key < this.length && key > 0
        else if this.type = cJson.cJSON_Object
            return cJson.cJSON_HasObjectItem(this.jsonPtr, key)
        return false
    }
    
    length
    {
        get => this.type = cJson.cJSON_Array ? cJson.cJSON_GetArraySize(this.jsonPtr) : 0
    }
    
    parse(value)
    {
        this.jsonPtr := cJson.cJSON_Parse(value)
        if this.jsonPtr
            return true
        return false
    }
    
    type
    {
        get => this.getType()
    }
    
    static dll_file(dll_name)
    {
        if !dll_name
            return false
        if fileexist(dll_name)
            return dll_name
        else if fileexist(format("{}\lib\{}", regread("HKLM\SOFTWARE\AutoHotkey", "InstallDir", ""), dll_name))
            return format("{}\lib\{}", regread("HKLM\SOFTWARE\AutoHotkey", "InstallDir", ""), dll_name)
        else if fileexist(format("{}\lib\{}", a_scriptdir, dll_name))
            return format("{}\lib\{}", a_scriptdir, dll_name)
        else
            return false
    }
    
    static strBuffer(str, encoding := "utf-8")
    {
        buf := buffer(strput(str, encoding))
        strput(str, buf, encoding)
        return buf
    }
    
    static cJSON_AddArrayToObject(_object, name)
    {
        return dllcall("cJson\cJSON_AddArrayToObject", "ptr", _object, "ptr", this.strBuffer(name))
    }
    
    static cJSON_AddBoolToObject(_object, name, b)
    {
        return dllcall("cJson\cJSON_AddBoolToObject", "ptr", _object, "ptr", this.strBuffer(name), "int", b)
    }
    
    static cJSON_AddFalseToObject(_object, name)
    {
        return dllcall("cJson\cJSON_AddFalseToObject", "ptr", _object, "ptr", this.strBuffer(name))
    }
    
    static cJSON_AddItemReferenceToArray(_array, item)
    {
        return dllcall("cJson\cJSON_AddItemReferenceToArray", "ptr", _array, "ptr", item)
    }
    
    static cJSON_AddItemReferenceToObject(_object, _string, item)
    {
        return dllcall("cJson\cJSON_AddItemReferenceToObject", "ptr", _object, "ptr", _string, "ptr", item)
    }
    
    static cJSON_AddItemToArray(_array, item)
    {
        return dllcall("cJson\cJSON_AddItemToArray", "ptr", _array, "ptr", item)
    }
    
    static cJSON_AddItemToObject(_object, _string, item)
    {
        return dllcall("cJson\cJSON_AddItemToObject", "ptr", _object, "ptr", this.strBuffer(_string), "ptr", item)
    }
    
    static cJSON_AddItemToObjectCS(_object, _string, item)
    {
        return dllcall("cJson\cJSON_AddItemToObjectCS", "ptr", _object, "ptr", this.strBuffer(_string), "ptr", item)
    }
    
    static cJSON_AddNullToObject(_object, name)
    {
        return dllcall("cJson\cJSON_AddNullToObject", "ptr", _object, "ptr", this.strBuffer(name))
    }
    
    static cJSON_AddNumberToObject(_object, name, n)
    {
        return dllcall("cJson\cJSON_AddNumberToObject", "ptr", _object, "ptr", this.strBuffer(name), "int", n)
    }
    
    static cJSON_AddObjectToObject(_object, name)
    {
        return dllcall("cJson\cJSON_AddObjectToObject", "ptr", _object, "ptr", this.strBuffer(name))
    }
    
    static cJSON_AddRawToObject(_object, name, raw)
    {
        return dllcall("cJson\cJSON_AddRawToObject", "ptr", _object, "ptr", this.strBuffer(name), "ptr", this.strBuffer(raw))
    }
    
    static cJSON_AddStringToObject(_object, name, s)
    {
        return dllcall("cJson\cJSON_AddStringToObject", "ptr", _object, "ptr", this.strBuffer(name), "ptr", this.strBuffer(s))
    }
    
    static cJSON_AddTrueToObject(_object, name)
    {
        return dllcall("cJson\cJSON_AddTrueToObject", "ptr", _object, "ptr", this.strBuffer(name))
    }
    
    static cJSON_Compare(a, b, case_sensitive) ; => int
    {
        return dllcall("cJson\cJSON_Compare", "ptr", a, "ptr", b, "int", case_sensitive)
    }
    
    static cJSON_CreateArray() ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateArray")
    }
    
    static cJSON_CreateArrayReference(child) ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateArrayReference", "ptr", child)
    }
    
    static cJSON_CreateBool(b) ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateBool", "int", b)
    }
    
    static cJSON_CreateDoubleArray(numbers, count) ; => cJSON*
    {
        dllcall("cJson\cJSON_CreateDoubleArray", "ptr", numbers, "int", count)
    }
    
    static cJSON_CreateFalse() ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateFalse")
    }
    
    static cJSON_CreateFloatArray(numbers, count) ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateFloatArray", "ptr", numbers, "int", count)
    }
    
    static cJSON_CreateIntArray(numbers, count) ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateIntArray", "ptr", numbers, "int", count)
    }
    
    static cJSON_CreateNull() ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateNull")
    }
    
    static cJSON_CreateNumber(num) ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateNumber", "double", num)
    }
    
    static cJSON_CreateObject() ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateObject")
    }
    
    static cJSON_CreateObjectReference(child) ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateObjectReference", "ptr", child)
    }
    
    static cJSON_CreateRaw(raw) ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateRaw", "ptr", this.strBuffer(raw))
    }
    
    static cJSON_CreateString(_string) ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateString", "ptr", this.strBuffer(_string))
    }
    
    static cJSON_CreateStringArray(strings, count) ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateStringArray", "ptr", strings, "int", count)
    }
    
    static cJSON_CreateStringReference(_string) ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateStringReference", "ptr", this.strBuffer(_string))
    }
    
    static cJSON_CreateTrue() ; => cJSON*
    {
        return dllcall("cJson\cJSON_CreateTrue")
    }
    
    static cJSON_Delete(c)
    {
        return dllcall("cJson\cJSON_Delete", "ptr", c)
    }
    
    static cJSON_DeleteItemFromArray(_array, which)
    {
        return dllcall("cJson\cJSON_DeleteItemFromArray", "ptr", _array, "int", which)
    }
    
    static cJSON_DeleteItemFromObject(_object, _string)
    {
        return dllcall("cJson\cJSON_DeleteItemFromObject", "ptr", _object, "ptr", this.strBuffer(_string))
    }
    
    static cJSON_DeleteItemFromObjectCaseSensitive(_object, _string)
    {
        return dllcall("cJson\cJSON_DeleteItemFromObjectCaseSensitive", "ptr", _object, "ptr", this.strBuffer(_string))
    }
    
    static cJSON_DetachItemFromArray(_array, which) ; => cJSON*
    {
        return dllcall("cJson\cJSON_DetachItemFromArray", "ptr", _array, "int", which)
    }
    
    static cJSON_DetachItemFromObject(_object, _string) ; => cJSON*
    {
        return dllcall("cJson\cJSON_DetachItemFromObject", "ptr", _object, "ptr", this.strBuffer(_string))
    }
    
    static cJSON_DetachItemFromObjectCaseSensitive(_object, _string) ; => cJSON*
    {
        return dllcall("cJson\cJSON_DetachItemFromObjectCaseSensitive", "ptr", _object, "ptr", this.strBuffer(_string))
    }
    
    static cJSON_DetachItemViaPointer(parent, item) ; => cJSON*
    {
        return dllcall("cJson\cJSON_DetachItemViaPointer", "ptr", parent, "ptr", item)
    }
    
    static cJSON_Duplicate(item, recurse) ; => cJSON*
    {
        return dllcall("cJson\cJSON_Duplicate", "ptr", item, "int", recurse)
    }
    
    static cJSON_GetArrayItem(_array, index) ; => cJSON*
    {
        return dllcall("cJson\cJSON_GetArrayItem", "ptr", _array, "int", index)
    }
    
    static cJSON_GetArraySize(_array) ; => int
    {
        return dllcall("cJson\cJSON_GetArraySize", "ptr", _array)
    }
    
    static cJSON_GetErrorPtr() ; => const char*
    {
        return strget(dllcall("cJson\cJSON_GetErrorPtr"), , "utf-8")
    }
    
    static cJSON_GetNumberValue(item) ; => double
    {
        return dllcall("cJson\cJSON_GetNumberValue", "ptr", item, "double")
    }
    
    static cJSON_GetObjectItem(_object, _string) ; => cJSON*
    {
        return dllcall("cJson\cJSON_GetObjectItem", "ptr", _object, "ptr", this.strBuffer(_string))
    }
    
    static cJSON_GetObjectItemCaseSensitive(_object, _string) ; => cJSON*
    {
        return dllcall("cJson\cJSON_GetObjectItemCaseSensitive", "ptr", _object, "ptr", this.strBuffer(_string))
    }
    
    static cJSON_GetStringValue(item) ; => char*
    {
        return strget(dllcall("cJson\cJSON_GetStringValue", "ptr", item), , "utf-8")
    }
    
    static cJSON_GetObjectType(_object, flags := false)
    {
        if flags
            return _object
        _mcode := "2,x64:SIsCSIsQSIsCSGNIGEiJCsM="
        fn := cJson.native.func(_mcode, 1, 1)
        fn(_type := _object)
        return _type
    }
    
    static cJSON_HasObjectItem(_object, _string) ; => int
    {
        return dllcall("cJson\cJSON_HasObjectItem", "ptr", _object, "ptr", this.strBuffer(_string))
    }
    
    static cJSON_InitHooks(hooks)
    {
        return dllcall("cJson\cJSON_InitHooks", "ptr", hooks)
    }
    
    static cJSON_InsertItemInArray(_array, which, newitem)
    {
        return dllcall("cJson\cJSON_InsertItemInArray", "ptr", _array, "int", which, "ptr", newitem)
    }
    
    static cJSON_IsArray(_array) ; => int
    {
        return dllcall("cJson\cJSON_IsArray", "ptr", _array)
    }
    
    static cJSON_IsBool(b) ; => int
    {
        return dllcall("cJson\cJSON_IsBool", "ptr", b)
    }
    
    static cJSON_IsFalse(b) ; => int
    {
        return dllcall("cJson\cJSON_IsFalse", "ptr", b)
    }
    
    static cJSON_IsInvalid(b) ; => int
    {
        return dllcall("cJson\cJSON_IsInvalid", "ptr" b)
    }
    
    static cJSON_IsNull(n) ; => int
    {
        return dllcall("cJson\cJSON_IsNull", "ptr", n)
    }
    
    static cJSON_IsNumber(num) ; => int
    {
        return dllcall("cJson\cJSON_IsNumber", "ptr", num)
    }
    
    static cJSON_IsObject(_object) ; => int
    {
        return dllcall("cJson\cJSON_IsObject", "ptr", _object)
    }
    
    static cJSON_IsRaw(raw) ; => int
    {
        return dllcall("cJson\cJSON_IsRaw", "ptr", raw)
    }
    
    static cJSON_IsString(_string) ; => int
    {
        return dllcall("cJson\cJSON_IsString", "ptr", _string)
    }
    
    static cJSON_IsTrue(b) ; => int
    {
        return dllcall("cJson\cJSON_IsTrue", "ptr", b)
    }
    
    static cJSON_Minify(json) ; => char*
    {
        buf := this.strBuffer(json)
        dllcall("cJson\cJSON_Minify", "ptr", buf)
        return strget(buf, , "utf-8")
    }
    
    static cJSON_Parse(value) ; => cJson*
    {
        if value is file
            value := value.read()
        else
        {
            try
                value := fileread(value)
        }
        return dllcall("cJson\cJSON_Parse", "ptr", this.strBuffer(value))
    }
    
    static cJSON_ParseWithLength(_string, buffer_length) ; => cJSON*
    {
        return dllcall("cJson\cJSON_ParseWithLength", "ptr", this.strBuffer(_string), "int", buffer_length)
    }
    
    static cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated) ; => cJSON*
    {
        return dllcall("cJson\cJSON_ParseWithLengthOpts", "ptr", value, "int", buffer_length, "ptr", return_parse_end, "int", require_null_terminated)
    }
    
    static cJSON_ParseWithOpts(value, return_parse_end, require_null_terminated) ; => cJSON*
    {
        return dllcall("cJson\cJSON_ParseWithOpts", "ptr", this.strBuffer(value), "ptr", return_parse_end, "int", require_null_terminated)
    }
    
    static cJSON_Print(item) ; => char*
    {
        return strget(dllcall("cJson\cJSON_Print", "ptr", item), , "utf-8")
    }
    
    static cJSON_PrintBuffered(item, prebuffer, fmt) ; => char*
    {
        return strget(dllcall("cJson\cJSON_PrintBuffered", "ptr", item, "int", prebuffer, "int", fmt), , "utf-8")
    }
    
    static cJSON_PrintPreallocated(item, buffer, length, fmt) ; => int
    {
        return dllcall("cJson\cJSON_PrintPreallocated", "ptr", item, "ptr", buffer, "int", length, "int", fmt)
    }
    
    static cJSON_PrintUnformatted(item) ; => char*
    {
        return strget(dllcall("cJson\cJSON_PrintUnformatted", "ptr", item), , "utf-8")
    }
    
    static cJSON_ReplaceItemInArray(_array, which, newitem)
    {
        return dllcall("cJson\cJSON_ReplaceItemInArray", "ptr", _array, "int", which, "ptr", newitem)
    }
    
    static cJSON_ReplaceItemInObject(_object, _string, newitem)
    {
        return dllcall("cJson\cJSON_ReplaceItemInObject", "ptr", _object, "ptr", this.strBuffer(_string), "ptr", newitem)
    }
    
    static cJSON_ReplaceItemInObjectCaseSensitive(_object, _string, newitem, case_sensitive)
    {
        return dllcall("cJson\cJSON_ReplaceItemInObjectCaseSensitive", "ptr", _object, "ptr", this.strBuffer(_string), "ptr", newitem, "int", case_sensitive)
    }
    
    static cJSON_ReplaceItemViaPointer(_object, item, replacement)
    {
        return dllcall("cJson\cJSON_ReplaceItemViaPointer", "ptr", _object, "ptr", item, "ptr", replacement)
    }
    
    static cJSON_SetNumberHelper(_object, num)
    {
        return dllcall("cJson\cJSON_SetNumberHelper", "ptr", _object, "double", num)
    }
    
    static cJSON_SetValuestring(item, _string)
    {
        return dllcall("cJson\cJSON_SetValuestring", "ptr", item, "ptr", this.strBuffer(_string))
    }
    
    static cJSON_Version()
    {
        return strget(dllcall("cJson\cJSON_Version"), , "utf-8")
    }
    
    static cJSON_free(_object)
    {
        return dllcall("cJson\cJSON_free", "ptr", _object)
    }
    
    static cJSON_malloc(len) ; => ptr
    {
        return dllcall("cJson\cJSON_malloc", "int", len)
    }
    
    class Boolean
    {
        __new(flag)
        {
            this.data := !!flag
        }
    }
    
    class native extends func
    {
        static prototype.caches := map()

        ; Auto free the NativeFunc object memory, because destructor is overridden, ahk will not free the memory.
        ; Freeing memory before func obj is released can cause invalid reads and writes to memory.
        ; Delayed free memory, the memory of the last function is freed when the function object is released.
        __delete()
        {
            numput('ptr', pthis := objptr(this), objptr(this.base.caches[''] := buffer()), 3 * A_PtrSize + 8)
            try this.base.caches.delete(numget(pthis + 6 * A_PtrSize + 16, 'ptr'))
        }

        ; Provides a way for modules to call ahk objects
        static __get(name, params) => params.length ? %name%[params*] : %name%
        static __call(name, params)
        {
            if name = 'throw'
            {
                if len := params.length
                {
                    msg := params[1], extra := len > 1 ? params[2] : '', errobj := len > 2 ? %params[3]% : msg is Integer ? oserror : error
                    throw errobj(msg, -1, extra)
                }
                throw error('An exception occurred', -1)
            }
            return %name%(params*)
        }

        ; create c/c++ function from mcode, and return the function address
        static mcode(hex)
        {
            static reg := "^([12]?).*" (A_PtrSize = 8 ? "x64" : "x86") ":([A-Za-z\d+/=]+)"
            if (regexmatch(hex, reg, &m))
                hex := m[2], flag := m[1] = "1" ? 4 : m[1] = "2" ? 1 : hex ~= "[+/=]" ? 1 : 4
            else
                flag := hex ~= "[+/=]" ? 1 : 4
            if (!dllcall("crypt32\CryptStringToBinary", "str", hex, "uint", 0, "uint", flag, "ptr", 0, "uint*", &s := 0, "ptr", 0, "ptr", 0))
                throw oserror(A_LastError)
            if (dllcall("crypt32\CryptStringToBinary", "str", hex, "uint", 0, "uint", flag, "ptr", p := (code := buffer(s)).Ptr, "uint*", &s, "ptr", 0, "ptr", 0) && dllcall("VirtualProtect", "ptr", code, "uint", s, "uint", 0x40, "uint*", 0))
                return (this.prototype.caches[p] := code, p)
            throw oserror(A_LastError)
        }

        /**
         * Generate a func object with native code
         * @param BIF Function addresses, `void funcname(ResultToken &aResultToken, ExprTokenType *aParam[], int aParamCount)`
         * @param MinParams The number of required parameters
         * @param ParamCount The number of maximum parameters, ParamCount = 255 if the function is variadic
         * @param OutputVars The array that contains one-based indexs of outputvars, up to seven
         * @param FID Function ID, `aResultToken.func->mFID`, for code sharing: this function's ID in the group of functions which share the same c++ function
         */
        static func(bif, minparams := 0, paramcount := 0, outputvars := 0, fid := 0)
        {
            static p__init := objptr(Any.__Init), size := 8 * A_PtrSize + 16
            if bif is string
                bif := this.mcode(bif)
            ; copy a func object memory
            sbif := buffer(outputvars ? size + 7 : size, 0), dllcall('RtlMoveMemory', 'ptr', sbif, 'ptr', p__init, 'uint', size)
            obif := objfromptr(sbif.Ptr)
            if isvariadic := paramcount == 255
                paramcount := minparams
            else paramcount := max(minparams, paramcount)
            ; init func refcount and base obj
            numput('uint', 1, 'uint', 0, 'ptr', objptraddref(cJson.native.prototype), sbif, A_PtrSize)
            ; init func infos
            numput('ptr', strptr('User-bif'), 'int', paramcount, 'int', minparams, 'int', isvariadic, sbif, 3 * A_PtrSize + 8)
            numput('ptr', bif, 'ptr', fid, sbif, 6 * A_PtrSize + 16)
            if outputvars
            {
                numput('ptr', s := sbif.Ptr + size, sbif, 5 * A_PtrSize + 16)	; mOutputVars
                loop min(outputvars.length, 7)	; MAX_FUNC_OUTPUT_VAR = 7
                    s := numput('uchar', outputvars[A_Index], s)
            }
            numput('ptr', 0, 'ptr', 0, objptr(sbif), 3 * A_PtrSize + 8) ; Avoid the memory of func object be freed when buffer is released
            return obif
        }

        /**
         * Generate a method with native code, is same with `cJson.native.func`
         * @param base The base of instance
         */
        static method(base, bim, mit, minparams := 0, paramcount := 0, mid := 0)
        {
            static pownprops := objptr({}.OwnProps), size := 9 * A_PtrSize + 16, nameoffset := 3 * A_PtrSize + 8
            if bim is string
                bim := this.mcode(bim)
            sbim := buffer(size, 0), dllcall('RtlMoveMemory', 'ptr', sbim, 'ptr', pownprops, 'uint', size)
            obim := objfromptr(sbim.ptr), isvariadic := paramcount == 255
            switch mit, false
            {
                case 'call', 2: ++minparams, paramcount := isvariadic ? minparams : max(minparams, paramcount + 1), numput('ptr', strptr('User-bim'), sbim, nameoffset), mit := 2
                case 'set', 1: minparams += 2, paramcount += 2, mit := 1, numput('ptr', strptr('User-bim.Set'), sbim, nameoffset)
                case 'get', 0: ++minparams, paramcount := max(minparams, paramcount + 1), numput('ptr', strptr('User-bim.Get'), sbim, nameoffset), mit := 0
            }
            numput('uint', 1, 'uint', 0, 'ptr', objptraddref(cJson.native.prototype), sbim, A_PtrSize)
            numput('int', max(minparams, paramcount), 'int', minparams, 'int', isvariadic, sbim, 4 * A_PtrSize + 8)
            numput('ptr', bim, 'ptr', base, 'uchar', mid, 'uchar', mit, sbim, 6 * A_PtrSize + 16)
            numput('ptr', 0, 'ptr', 0, objptr(sbim), 3 * A_PtrSize + 8)
            return obim
        }

        /**
         * Defines a new own property with native code, is similar with `obj.DefineProp`
         * @param obj Any object
         * @param name The name of the property
         * @param desc An object with one of following own properties, or both `Get` and `Set`
         * 
         * `Call, Get, Set`: an object with `bim` property and optional properties `minparams`, `paramcount`, `outputvars`, `mid`, is same with the parameters of `BuiltInFunc`
         * 
         * `bim`: `void (IObject::* ObjectMethod)(ResultToken& aResultToken, int aID, int aFlags, ExprTokenType* aParam[], int aParamCount)`
         */
        static defineprop(obj, name, desc)
        {
            descobj := {}, baseobj := objptr(obj.base)
            for mit in ['call', 'set', 'get']
                if desc.hasownprop(mit)
                {
                    t := desc.%mit%, minparams := paramcount := mid := 0, bim := t.bim
                    for k in ['minparams', 'paramcount', 'mid']
                        if t.hasownprop(k)
                            %k% := t.%k%
                    descobj.%mit% := this.method(baseobj, bim, mit, minparams, paramcount, mid)
                }
            obj.defineprop(name, descobj)
        }

        /**
         * Create a class with constructor function address
         * @param ctor constructor function address, `void funcname(ResultToken &aResultToken, ExprTokenType *aParam[], int aParamCount)`
         * 
         * constructor function used to create an object
         */
        static class(name, ctor := 0, fid := 0)
        {
            cls := class(), cls.prototype := { base: object.prototype, __class: name }
            if ctor
                cls.defineprop('Call', {call: this.func(ctor, 1, 255, 0, fid)})
            return cls
        }

        /**
         * Load a dll file with the specified format to create native functions and classes
         * @param path ahk module path
         * @param load_symbols Load symbols that specific names, will overwrite existing global classes
         * @param loader Create native functions and classes based on the information provided by the module, or do it in the module
         * @param provider Used to provide the ahk objects required by the module
         */
        static loadmodule(path, load_symbols := 0, loader := 0, provider := 0)
        {
            if !(module := dllcall('LoadLibrary', 'str', path, 'ptr'))
                throw oserror(A_LastError)
            module_load_addr := dllcall('GetProcAddress', 'ptr', module, 'astr', 'ahk2_module_load', 'ptr') || dllcall('GetProcAddress', 'ptr', module, 'ptr', 1, 'ptr')
            if !module_load_addr
                throw error('Export function not found')
            if load_symbols
            {
                t := map(), t.casesense := false
                for k in load_symbols
                    t[k] := true
                load_symbols := t
            }
            if !p := dllcall(module_load_addr, 'ptr', objptr(loader || default_loader), 'ptr', objptr(provider || cJson.native), 'cdecl ptr')
                throw error('Load module fail', -1, oserror(A_LastError).Message)
            return objfromptr(p)

            default_loader(count, addr)
            {
                static size := 2 * A_PtrSize + 16
                symbols := map(), symbols.casesense := false, symbols.defineprop('__call', { call: (s, n, p) => s[n](p*) })
                loop count
                {
                    name := strget(pname := numget(addr, 'ptr'))
                    if load_symbols && !load_symbols.Has(name)
                    {
                        addr += size
                        continue
                    }
                    funcaddr := numget(addr += A_PtrSize, 'ptr')
                    minparams := numget(addr += A_PtrSize, 'uchar')
                    maxparams := numget(addr += 1, 'uchar')
                    id := numget(addr += 1, 'ushort')
                    if member_count := numget(addr += 2, 'uint')
                    {
                        try
                        {
                            if !load_symbols || !isobject(symbol := %name%)
                                throw
                            symbols[name] := symbol
                            if !symbol.hasownprop('prototype')
                                symbol.prototype := this.class(name, 0).prototype
                            if funcaddr
                                symbol.defineprop('Call', {call: me := this.func(funcaddr, 1, maxparams + 1, 0, id)}), numput('ptr', pname, objptr(me), 3 * A_PtrSize + 8)
                        }
                        catch
                            symbols[name] := symbol := this.class(name, funcaddr, id)
                        pmem := numget(addr += 4, 'ptr')
                    }
                    staticmembers := {}, members := {}
                    loop member_count
                    {
                        name := strget(pname := numget(pmem, 'ptr'))
                        method := numget(pmem += A_PtrSize, 'ptr')
                        id := numget(pmem += A_PtrSize, 'uchar')
                        mit := numget(pmem += 1, 'uchar')
                        minparams := numget(pmem += 1, 'uchar')
                        maxparams := numget(pmem += 1, 'uchar')
                        namearr := strsplit(name, '.')
                        if mit < 2 && namearr.length > 2
                            namearr.pop()
                        name := namearr.pop()
                        sub := mit = 2 ? 'call' : mit = 1 ? 'set' : 'get'
                        if namearr.length < 2
                            mems := staticmembers, pbase := objptr(symbol.base)
                        else
                            mems := members, pbase := objptr(symbol.prototype.base)
                        if !mems.hasownprop(name)
                            t := mems.%name% := {}
                        else t := mems.%name%
                        t.%sub% := me := this.method(pbase, method, mit, minparams, maxparams, id)
                        numput('ptr', pname, objptr(me), 3 * A_PtrSize + 8)
                        pmem += A_PtrSize - 3
                    }
                    else
                    {
                        symbols[name] := symbol := this.func(funcaddr, minparams, maxparams, 0, id)
                        numput('ptr', pname, objptr(symbol), 3 * A_PtrSize + 8)
                        if numget(addr += 4, 'uchar')	; set mOutputVars
                            numput('ptr', addr, objptr(symbol), 5 * A_PtrSize + 16)
                    }
                    if member_count
                    {
                        if symbol == map	; Break circular references if map has define native funcs
                            OnExit(onexitapp.Bind(map(map, [staticmembers*], map.prototype, [members*])))
                        for name, desc in staticmembers.ownprops()
                            symbol.defineprop(name, desc)
                        symbol := symbol.prototype
                        for name, desc in members.ownprops()
                            symbol.defineprop(name, desc)
                    }
                    addr += 8
                }
                return symbols

                onexitapp(todels, *)
                {
                    for o, arr in todels
                    {
                        for n in arr
                            try o.deleteprop(n)
                    }
                }
            }
        }
        
        static mdfunc(fn, sig, prototype := 0)
        {
            static p_mdfunc := objptr(msgbox), size := 10 * A_PtrSize + 16
            static mdtypes :=
            {
                void: 0,
                int8: 1,
                uint8: 2,
                int16: 3,
                uint16: 4,
                int32: 5,
                uint32: 6,
                int64: 7,
                uint64: 8,
                float64: 9,
                float32: 10,
                string: 11,
                object: 12,
                variant: 13,
                bool32: 14,
                resulttype: 15,
                fresult: 16,
                params: 17,
                optional: 0x80,
                retval: 0x81,
                out: 0x82,
                ; thiscall,
                uintptr: A_PtrSize = 8 ? 8 : 6,
                intptr: A_PtrSize = 8 ? 7 : 5,
            }
            if fn is string
                fn := this.mcode(fn)
            ; copy a func object memory
            smdf := buffer(size, 0), dllcall('RtlMoveMemory', 'ptr', smdf, 'ptr', p_mdfunc, 'uint', size)
            p := numput('ptr', fn, smdf, 6 * A_PtrSize + 16), ac := pc := minparams := 0
            if prototype
                numput('char', 1, numput('ptr', isobject(prototype) ? objptr(prototype) : prototype, p) + A_PtrSize + 3), ac := pc := minparams := 1
            isvariadic := false, maxresulttokens := 0
            if sig is array
            {
                if sig.length > 1
                    ret := sig.removeat(1), smdf.size += sig.length, ret is string && ret := mdtypes.%ret%
                else ret := 0
                opt := false, retval := false, out := 0
                loop sig.length
                {
                    c := sig[A_Index]
                    if c is String
                        sig[A_Index] := c := mdtypes.%c%
                    numput('uchar', c, smdf, size + A_Index - 1)
                    if c >= 128
                    {
                        if c = 128
                            opt := true
                        else if c = 0x82
                            out := c
                        else if c = 0x81
                            retval := true
                        continue
                    }
                    if A_PtrSize = 4 && c >= 7 && c <= 9 && !out && !opt
                        ac++
                    ac++
                    if c = 17
                        isvariadic := true
                    else if !retval
                    {
                        ++pc
                        if !opt && pc - 1 = minparams
                            minparams := pc
                        if c = 13 && out
                            ++MaxResultTokens
                    }
                    opt := false, retval := false, out := 0
                }
                numput('ptr', smdf.ptr + size, 'uchar', ret, 'uchar', ac, 'uchar', sig.length, smdf, 8 * A_PtrSize + 16)
            }
            else throw
            paramcount := pc
            obif := objfromptr(smdf.ptr)
            ; init func refcount and base obj
            numput('uint', 1, 'uint', 0, 'ptr', objptraddref(cJson.native.prototype), smdf, A_PtrSize)
            ; init func infos
            numput('ptr', strptr('User-MdFunc'), 'int', paramcount, 'int', minparams, 'int', isvariadic, smdf, 3 * A_PtrSize + 8)
            numput('ptr', 0, 'ptr', 0, objptr(smdf), 3 * A_PtrSize + 8)	; Avoid the memory of func object be freed when buffer is released
            return obif
        }
    }

    native_mcode(hex, argtypes := 0, &code := 0)
    {
        static reg := "^([12]?).*" (c := a_ptrsize = 8 ? "x64" : "x86") ":([A-Za-z\d+/=]+)"
        if (regexmatch(hex, reg, &m))
            hex := m[2], flag := m[1] = "1" ? 4 : m[1] = "2" ? 1 : hex ~= "[+/=]" ? 1 : 4
        else
            flag := hex ~= "[+/=]" ? 1 : 4
        if (!dllcall("crypt32\CryptStringToBinary", "str", hex, "uint", 0, "uint", flag, "ptr", 0, "uint*", &s := 0, "ptr", 0, "ptr", 0))
            return
        code := buffer(s)
        if (dllcall("crypt32\CryptStringToBinary", "str", hex, "uint", 0, "uint", flag, "ptr", code, "uint*", &s, "ptr", 0, "ptr", 0) && dllcall("VirtualProtect", "ptr", code, "uint", s, "uint", 0x40, "uint*", 0))
        {
            args := []
            if (argtypes is array && argtypes.Length)
            {
                args.length := argtypes.length * 2 - 1
                for i, t in argtypes
                    args[i * 2 - 1] := t
            }
            return dllcall.bind(code, args*)
        }
    }
    
    class Null
    {
        
    }
}
Attachments
cjson.zip
(31.33 KiB) Downloaded 96 times

Adventurer
Posts: 23
Joined: 18 Apr 2019, 06:24

Re: [v2.0.2]cJson--created by dll

Post by Adventurer » 04 Nov 2023, 12:14

Is this based on G33kDude's cJson library for v1.1 or does it just happen to have the same name?

User avatar
Animan8000
Posts: 57
Joined: 11 May 2022, 05:00
Contact:

Re: [v2.0.2]cJson--created by dll

Post by Animan8000 » 05 Nov 2023, 03:26

@Adventurer

Not based of geek's library

Descolada
Posts: 1123
Joined: 23 Dec 2021, 02:30

Re: [v2.0.2]cJson--created by dll

Post by Descolada » 05 Nov 2023, 04:40

@Mono919
1) You should also provide the source code for the dll (at least I didn't find it from your post nor the zip file). I for one refuse to execute random code from the web without also having access to its source code. Who knows what viruses/malware it might contain otherwise...
2) A library with the name cJson already exists by @geek. AHK library names probably aren't trademarked (?), but have you by chance asked permission from him to use the same name?

valuex
Posts: 86
Joined: 01 Nov 2014, 08:17

Re: [v2.0.2]cJson--created by dll

Post by valuex » 07 Nov 2023, 08:32

Could you show some demo scripts?
I've trid to code like this, but no value returned.

Code: Select all

#include D:\Downloads\cjson\cjson\cjson.ahk
JsonFile:="D:\Downloads\cjson\cjson\cfg.json"
JsonFileContent := FileRead(JsonFile)
MyJson:=cJson(JsonFileContent)
MsgBox MyJson["CategoryDisplayPosition"].get()
Attachments
cjson-demo-script.zip
(31.56 KiB) Downloaded 41 times

Adventurer
Posts: 23
Joined: 18 Apr 2019, 06:24

Re: [v2.0.2]cJson--created by dll

Post by Adventurer » 10 Nov 2023, 11:45

Descolada wrote:
05 Nov 2023, 04:40
@Mono919
1) You should also provide the source code for the dll (at least I didn't find it from your post nor the zip file). I for one refuse to execute random code from the web without also having access to its source code. Who knows what viruses/malware it might contain otherwise...
2) A library with the name cJson already exists by @geek. AHK library names probably aren't trademarked (?), but have you by chance asked permission from him to use the same name?

Apparently it's named that way because this is a wrapper for the cJSON library, which dates back to 2009: https://github.com/DaveGamble/cJSON

I checked the DLL's endpoints and they match up to the functions that the documentation describes. Based off the date of the releases and the Last Modified Date of the DLL, the DLL is probably a compiled version of 1.7.15 from Microsoft vcpkg service (latest is 1.7.16).

Post Reply

Return to “Scripts and Functions (v2)”