forked from qt-creator/qt-creator
debugger: Fix dumper for std::string and unordered_multiset
Moves mac specific dumpers to separate file Creates android dumpers for stdtypes Change-Id: I33d28198e1a2f24fb7707313845db81e283686cd Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -30,9 +30,10 @@ set(resource_files
|
|||||||
debugger/pdbbridge.py
|
debugger/pdbbridge.py
|
||||||
debugger/personaltypes.py
|
debugger/personaltypes.py
|
||||||
debugger/qttypes.py
|
debugger/qttypes.py
|
||||||
debugger/qttypes.py
|
|
||||||
debugger/README.txt
|
debugger/README.txt
|
||||||
debugger/setup.cfg
|
debugger/setup.cfg
|
||||||
|
debugger/android_stdtypes.py
|
||||||
|
debugger/mac_stdtypes.py
|
||||||
debugger/stdtypes.py
|
debugger/stdtypes.py
|
||||||
debugger/utils.py
|
debugger/utils.py
|
||||||
)
|
)
|
||||||
|
155
share/qtcreator/debugger/android_stdtypes.py
Normal file
155
share/qtcreator/debugger/android_stdtypes.py
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
############################################################################
|
||||||
|
##
|
||||||
|
## Copyright (C) 2022 The Qt Company Ltd.
|
||||||
|
## Contact: https://www.qt.io/licensing/
|
||||||
|
##
|
||||||
|
## This file is part of Qt Creator.
|
||||||
|
##
|
||||||
|
## Commercial License Usage
|
||||||
|
## Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
## accordance with the commercial license agreement provided with the
|
||||||
|
## Software or, alternatively, in accordance with the terms contained in
|
||||||
|
## a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
## and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
## information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
##
|
||||||
|
## GNU General Public License Usage
|
||||||
|
## Alternatively, this file may be used under the terms of the GNU
|
||||||
|
## General Public License version 3 as published by the Free Software
|
||||||
|
## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
## included in the packaging of this file. Please review the following
|
||||||
|
## information to ensure the GNU General Public License requirements will
|
||||||
|
## be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
##
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
from dumper import DumperBase
|
||||||
|
from utils import DisplayFormat
|
||||||
|
|
||||||
|
import stdtypes
|
||||||
|
import mac_stdtypes
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____ndk1__array():
|
||||||
|
return [DisplayFormat.ArrayPlot]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__array(d, value):
|
||||||
|
stdtypes.qdump__std__array(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__complex(d, value):
|
||||||
|
stdtypes.qdump__std__complex(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__deque(d, value):
|
||||||
|
stdtypes.qdumpHelper__std__deque__libcxx(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__list(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__list(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__set(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__set(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__multiset(d, value):
|
||||||
|
qdump__std____ndk1__set(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____ndk1__map():
|
||||||
|
return [DisplayFormat.CompactMap]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__map(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__map(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____ndk1__multimap():
|
||||||
|
return [DisplayFormat.CompactMap]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__multimap(d, value):
|
||||||
|
qdump__std____ndk1__map(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__map__iterator(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__map__iterator(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__map__const_iterator(d, value):
|
||||||
|
qdump__std____ndk1__map__iterator(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__set__iterator(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__set__iterator(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__set_const_iterator(d, value):
|
||||||
|
qdump__std____ndk1__set__iterator(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__stack(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__stack(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__string(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__string(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__wstring(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__wstring(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__basic_string(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__basic_string(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__shared_ptr(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__shared_ptr(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__weak_ptr(d, value):
|
||||||
|
return qdump__std____ndk1__shared_ptr(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__unique_ptr(d, value):
|
||||||
|
stdtypes.qdump__std__unique_ptr(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____ndk1__unordered_map():
|
||||||
|
return [DisplayFormat.CompactMap]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__unordered_map(d, value):
|
||||||
|
mac_stdtypes.qdump__std____1__unordered_map(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__unordered_set(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__unordered_set(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__unordered_multiset(d, value):
|
||||||
|
qdump__std____ndk1__unordered_set(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____ndk1__valarray():
|
||||||
|
return [DisplayFormat.ArrayPlot]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__valarray(d, value):
|
||||||
|
return mac_stdtypes.qdump__std____1__valarray(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____ndk1__vector():
|
||||||
|
return [DisplayFormat.ArrayPlot]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__vector(d, value):
|
||||||
|
stdtypes.qdumpHelper__std__vector__libcxx(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____ndk1__once_flag(d, value):
|
||||||
|
stdtypes.qdump__std__once_flag(d, value)
|
@@ -2953,6 +2953,8 @@ class DumperBase():
|
|||||||
|
|
||||||
class Value():
|
class Value():
|
||||||
def __init__(self, dumper):
|
def __init__(self, dumper):
|
||||||
|
# This can be helpful to track down from where a Value was created
|
||||||
|
#self._stack = inspect.stack()
|
||||||
self.dumper = dumper
|
self.dumper = dumper
|
||||||
self.name = None
|
self.name = None
|
||||||
self._type = None
|
self._type = None
|
||||||
@@ -3998,16 +4000,21 @@ class DumperBase():
|
|||||||
return typeobj
|
return typeobj
|
||||||
raise RuntimeError('NEED TYPE, NOT %s' % type(typish))
|
raise RuntimeError('NEED TYPE, NOT %s' % type(typish))
|
||||||
|
|
||||||
def createValue(self, datish, typish):
|
def createValueFromAddressAndType(self, address, typish):
|
||||||
val = self.Value(self)
|
val = self.Value(self)
|
||||||
val._type = self.createType(typish)
|
val._type = self.createType(typish)
|
||||||
|
#DumperBase.warn('CREATING %s AT 0x%x' % (val.type.name, datish))
|
||||||
|
val.laddress = address
|
||||||
|
if self.useDynamicType:
|
||||||
|
val._type = val.type.dynamicType(address)
|
||||||
|
return val
|
||||||
|
|
||||||
|
def createValue(self, datish, typish):
|
||||||
if self.isInt(datish): # Used as address.
|
if self.isInt(datish): # Used as address.
|
||||||
#DumperBase.warn('CREATING %s AT 0x%x' % (val.type.name, datish))
|
return self.createValueFromAddressAndType(datish, typish)
|
||||||
val.laddress = datish
|
|
||||||
if self.useDynamicType:
|
|
||||||
val._type = val.type.dynamicType(datish)
|
|
||||||
return val
|
|
||||||
if isinstance(datish, bytes):
|
if isinstance(datish, bytes):
|
||||||
|
val = self.Value(self)
|
||||||
|
val._type = self.createType(typish)
|
||||||
#DumperBase.warn('CREATING %s WITH DATA %s' % (val.type.name, self.hexencode(datish)))
|
#DumperBase.warn('CREATING %s WITH DATA %s' % (val.type.name, self.hexencode(datish)))
|
||||||
val.ldata = datish
|
val.ldata = datish
|
||||||
val.check()
|
val.check()
|
||||||
|
356
share/qtcreator/debugger/mac_stdtypes.py
Normal file
356
share/qtcreator/debugger/mac_stdtypes.py
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
###########################################################################
|
||||||
|
##
|
||||||
|
## Copyright (C) 2022 The Qt Company Ltd.
|
||||||
|
## Contact: https://www.qt.io/licensing/
|
||||||
|
##
|
||||||
|
## This file is part of Qt Creator.
|
||||||
|
##
|
||||||
|
## Commercial License Usage
|
||||||
|
## Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
## accordance with the commercial license agreement provided with the
|
||||||
|
## Software or, alternatively, in accordance with the terms contained in
|
||||||
|
## a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
## and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
## information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
##
|
||||||
|
## GNU General Public License Usage
|
||||||
|
## Alternatively, this file may be used under the terms of the GNU
|
||||||
|
## General Public License version 3 as published by the Free Software
|
||||||
|
## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
## included in the packaging of this file. Please review the following
|
||||||
|
## information to ensure the GNU General Public License requirements will
|
||||||
|
## be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
##
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
from stdtypes import qdump__std__array, qdump__std__complex, qdump__std__once_flag, qdump__std__unique_ptr, qdumpHelper__std__deque__libcxx, qdumpHelper__std__vector__libcxx
|
||||||
|
from utils import DisplayFormat
|
||||||
|
from dumper import Children, DumperBase
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____1__array():
|
||||||
|
return [DisplayFormat.ArrayPlot]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__array(d, value):
|
||||||
|
qdump__std__array(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__complex(d, value):
|
||||||
|
qdump__std__complex(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__deque(d, value):
|
||||||
|
qdumpHelper__std__deque__libcxx(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__list(d, value):
|
||||||
|
if value.type.size() == 3 * d.ptrSize():
|
||||||
|
# C++11 only.
|
||||||
|
(dummy1, dummy2, size) = value.split("ppp")
|
||||||
|
d.putItemCount(size)
|
||||||
|
else:
|
||||||
|
# Need to count manually.
|
||||||
|
p = d.extractPointer(value)
|
||||||
|
head = value.address()
|
||||||
|
size = 0
|
||||||
|
while head != p and size < 1001:
|
||||||
|
size += 1
|
||||||
|
p = d.extractPointer(p)
|
||||||
|
d.putItemCount(size, 1000)
|
||||||
|
|
||||||
|
if d.isExpanded():
|
||||||
|
(prev, p) = value.split("pp")
|
||||||
|
innerType = value.type[0]
|
||||||
|
typeCode = "pp{%s}" % innerType.name
|
||||||
|
with Children(d, size, maxNumChild=1000, childType=innerType):
|
||||||
|
for i in d.childRange():
|
||||||
|
(prev, p, val) = d.split(typeCode, p)
|
||||||
|
d.putSubItem(i, val)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__set(d, value):
|
||||||
|
(proxy, head, size) = value.split("ppp")
|
||||||
|
|
||||||
|
d.check(0 <= size and size <= 100 * 1000 * 1000)
|
||||||
|
d.putItemCount(size)
|
||||||
|
|
||||||
|
if d.isExpanded():
|
||||||
|
valueType = value.type[0]
|
||||||
|
|
||||||
|
def in_order_traversal(node):
|
||||||
|
(left, right, parent, color, pad, data) = d.split("pppB@{%s}" % (valueType.name), node)
|
||||||
|
|
||||||
|
if left:
|
||||||
|
for res in in_order_traversal(left):
|
||||||
|
yield res
|
||||||
|
|
||||||
|
yield data
|
||||||
|
|
||||||
|
if right:
|
||||||
|
for res in in_order_traversal(right):
|
||||||
|
yield res
|
||||||
|
|
||||||
|
with Children(d, size, maxNumChild=1000):
|
||||||
|
for (i, data) in zip(d.childRange(), in_order_traversal(head)):
|
||||||
|
d.putSubItem(i, data)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__multiset(d, value):
|
||||||
|
qdump__std____1__set(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____1__map():
|
||||||
|
return [DisplayFormat.CompactMap]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__map(d, value):
|
||||||
|
try:
|
||||||
|
(proxy, head, size) = value.split("ppp")
|
||||||
|
d.check(0 <= size and size <= 100 * 1000 * 1000)
|
||||||
|
|
||||||
|
# Sometimes there is extra data at the front. Don't know why at the moment.
|
||||||
|
except RuntimeError:
|
||||||
|
(junk, proxy, head, size) = value.split("pppp")
|
||||||
|
d.check(0 <= size and size <= 100 * 1000 * 1000)
|
||||||
|
|
||||||
|
d.putItemCount(size)
|
||||||
|
|
||||||
|
if d.isExpanded():
|
||||||
|
keyType = value.type[0]
|
||||||
|
valueType = value.type[1]
|
||||||
|
pairType = value.type[3][0]
|
||||||
|
|
||||||
|
def in_order_traversal(node):
|
||||||
|
(left, right, parent, color, pad, pair) = d.split("pppB@{%s}" % (pairType.name), node)
|
||||||
|
|
||||||
|
if left:
|
||||||
|
for res in in_order_traversal(left):
|
||||||
|
yield res
|
||||||
|
|
||||||
|
yield pair.split("{%s}@{%s}" % (keyType.name, valueType.name))[::2]
|
||||||
|
|
||||||
|
if right:
|
||||||
|
for res in in_order_traversal(right):
|
||||||
|
yield res
|
||||||
|
|
||||||
|
with Children(d, size, maxNumChild=1000):
|
||||||
|
for (i, pair) in zip(d.childRange(), in_order_traversal(head)):
|
||||||
|
d.putPairItem(i, pair)
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____1__multimap():
|
||||||
|
return [DisplayFormat.CompactMap]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__multimap(d, value):
|
||||||
|
qdump__std____1__map(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__map__iterator(d, value):
|
||||||
|
d.putEmptyValue()
|
||||||
|
if d.isExpanded():
|
||||||
|
with Children(d):
|
||||||
|
node = value['__i_']['__ptr_'].dereference()['__value_']['__cc']
|
||||||
|
d.putSubItem('first', node['first'])
|
||||||
|
d.putSubItem('second', node['second'])
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__map__const_iterator(d, value):
|
||||||
|
qdump__std____1__map__iterator(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__set__iterator(d, value):
|
||||||
|
d.putEmptyValue()
|
||||||
|
d.putExpandable()
|
||||||
|
if value.type.name.endswith("::iterator"):
|
||||||
|
treeTypeName = value.type.name[:-len("::iterator")]
|
||||||
|
elif value.type.name.endswith("::const_iterator"):
|
||||||
|
treeTypeName = value.type.name[:-len("::const_iterator")]
|
||||||
|
treeType = d.lookupType(treeTypeName)
|
||||||
|
keyType = treeType[0]
|
||||||
|
if d.isExpanded():
|
||||||
|
with Children(d):
|
||||||
|
node = value['__ptr_'].dereference()['__value_']
|
||||||
|
node = node.cast(keyType)
|
||||||
|
d.putSubItem('value', node)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__set_const_iterator(d, value):
|
||||||
|
qdump__std____1__set__iterator(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__stack(d, value):
|
||||||
|
d.putItem(value["c"])
|
||||||
|
d.putBetterType(value.type)
|
||||||
|
|
||||||
|
|
||||||
|
def std_1_string_dumper(d, value):
|
||||||
|
charType = value['__l']['__data_'].dereference().type
|
||||||
|
|
||||||
|
D = value[0][0][0][0]
|
||||||
|
|
||||||
|
layoutDecider = D[0][0]
|
||||||
|
if not layoutDecider:
|
||||||
|
raise Exception("Could not find layoutDecider")
|
||||||
|
|
||||||
|
size = 0
|
||||||
|
size_mode_value = 0
|
||||||
|
short_mode = False
|
||||||
|
|
||||||
|
layoutModeIsDSC = layoutDecider.name == '__data_'
|
||||||
|
if (layoutModeIsDSC):
|
||||||
|
size_mode = D[1][1][0]
|
||||||
|
if not size_mode:
|
||||||
|
raise Exception("Could not find size_mode")
|
||||||
|
if not size_mode.name == '__size_':
|
||||||
|
size_mode = D[1][1][1]
|
||||||
|
if not size_mode:
|
||||||
|
raise Exception("Could not find size_mode")
|
||||||
|
|
||||||
|
size_mode_value = size_mode.integer()
|
||||||
|
short_mode = ((size_mode_value & 0x80) == 0)
|
||||||
|
else:
|
||||||
|
size_mode = D[1][0][0]
|
||||||
|
if not size_mode:
|
||||||
|
raise Exception("Could not find size_mode")
|
||||||
|
|
||||||
|
size_mode_value = size_mode.integer()
|
||||||
|
short_mode = ((size_mode_value & 1) == 0)
|
||||||
|
|
||||||
|
if short_mode:
|
||||||
|
s = D[1]
|
||||||
|
|
||||||
|
if not s:
|
||||||
|
raise Exception("Could not find s")
|
||||||
|
|
||||||
|
location_sp = s[0] if layoutModeIsDSC else s[1]
|
||||||
|
size = size_mode_value if layoutModeIsDSC else ((size_mode_value >> 1) % 256)
|
||||||
|
else:
|
||||||
|
l = D[0]
|
||||||
|
if not l:
|
||||||
|
raise Exception("Could not find l")
|
||||||
|
|
||||||
|
# we can use the layout_decider object as the data pointer
|
||||||
|
location_sp = layoutDecider if layoutModeIsDSC else l[2]
|
||||||
|
size_vo = l[1]
|
||||||
|
if not size_vo or not location_sp:
|
||||||
|
raise Exception("Could not find size_vo or location_sp")
|
||||||
|
size = size_vo.integer()
|
||||||
|
|
||||||
|
if short_mode and location_sp:
|
||||||
|
d.putCharArrayHelper(d.extractPointer(location_sp), size,
|
||||||
|
charType, d.currentItemFormat())
|
||||||
|
else:
|
||||||
|
d.putCharArrayHelper(location_sp.integer(),
|
||||||
|
size, charType, d.currentItemFormat())
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def qdump__std____1__string(d, value):
|
||||||
|
std_1_string_dumper(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__wstring(d, value):
|
||||||
|
std_1_string_dumper(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__basic_string(d, value):
|
||||||
|
innerType = value.type[0].name
|
||||||
|
if innerType in ("char", "char8_t", "char16_t"):
|
||||||
|
qdump__std____1__string(d, value)
|
||||||
|
elif innerType in ("wchar_t", "char32_t"):
|
||||||
|
qdump__std____1__wstring(d, value)
|
||||||
|
else:
|
||||||
|
d.warn("UNKNOWN INNER TYPE %s" % innerType)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__shared_ptr(d, value):
|
||||||
|
i = value["__ptr_"]
|
||||||
|
if i.pointer() == 0:
|
||||||
|
d.putValue("(null)")
|
||||||
|
else:
|
||||||
|
d.putItem(i.dereference())
|
||||||
|
d.putBetterType(value.type)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__weak_ptr(d, value):
|
||||||
|
return qdump__std____1__shared_ptr(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__unique_ptr(d, value):
|
||||||
|
qdump__std__unique_ptr(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____1__unordered_map():
|
||||||
|
return [DisplayFormat.CompactMap]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__unordered_map(d, value):
|
||||||
|
(size, _) = value["__table_"]["__p2_"].split("pp")
|
||||||
|
d.putItemCount(size)
|
||||||
|
|
||||||
|
keyType = value.type[0]
|
||||||
|
valueType = value.type[1]
|
||||||
|
pairType = value.type[4][0]
|
||||||
|
|
||||||
|
if d.isExpanded():
|
||||||
|
curr = value["__table_"]["__p1_"].split("pp")[0]
|
||||||
|
|
||||||
|
def traverse_list(node):
|
||||||
|
while node:
|
||||||
|
(next_, _, pad, pair) = d.split("pp@{%s}" % (pairType.name), node)
|
||||||
|
yield pair.split("{%s}@{%s}" % (keyType.name, valueType.name))[::2]
|
||||||
|
node = next_
|
||||||
|
|
||||||
|
with Children(d, size, childType=value.type[0], maxNumChild=1000):
|
||||||
|
for (i, value) in zip(d.childRange(), traverse_list(curr)):
|
||||||
|
d.putPairItem(i, value, 'key', 'value')
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__unordered_set(d, value):
|
||||||
|
(size, _) = value["__table_"]["__p2_"].split("pp")
|
||||||
|
d.putItemCount(size)
|
||||||
|
|
||||||
|
valueType = value.type[0]
|
||||||
|
|
||||||
|
if d.isExpanded():
|
||||||
|
curr = value["__table_"]["__p1_"].split("pp")[0]
|
||||||
|
|
||||||
|
def traverse_list(node):
|
||||||
|
while node:
|
||||||
|
(next_, _, pad, val) = d.split("pp@{%s}" % (valueType.name), node)
|
||||||
|
yield val
|
||||||
|
node = next_
|
||||||
|
|
||||||
|
with Children(d, size, childType=value.type[0], maxNumChild=1000):
|
||||||
|
for (i, value) in zip(d.childRange(), traverse_list(curr)):
|
||||||
|
d.putSubItem(i, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__unordered_multiset(d, value):
|
||||||
|
qdump__std____1__unordered_set(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____1__valarray():
|
||||||
|
return [DisplayFormat.ArrayPlot]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__valarray(d, value):
|
||||||
|
innerType = value.type[0]
|
||||||
|
(begin, end) = value.split('pp')
|
||||||
|
size = int((end - begin) / innerType.size())
|
||||||
|
d.putItemCount(size)
|
||||||
|
d.putPlotData(begin, size, innerType)
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std____1__vector():
|
||||||
|
return [DisplayFormat.ArrayPlot]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__vector(d, value):
|
||||||
|
qdumpHelper__std__vector__libcxx(d, value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__std____1__once_flag(d, value):
|
||||||
|
qdump__std__once_flag(d, value)
|
@@ -24,7 +24,7 @@
|
|||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
from utils import DisplayFormat
|
from utils import DisplayFormat
|
||||||
from dumper import Children, SubItem
|
from dumper import Children, SubItem, DumperBase
|
||||||
|
|
||||||
|
|
||||||
def qform__std__array():
|
def qform__std__array():
|
||||||
@@ -38,14 +38,6 @@ def qdump__std__array(d, value):
|
|||||||
d.putPlotData(value.address(), size, value.type[0])
|
d.putPlotData(value.address(), size, value.type[0])
|
||||||
|
|
||||||
|
|
||||||
def qform__std____1__array():
|
|
||||||
return [DisplayFormat.ArrayPlot]
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__array(d, value):
|
|
||||||
qdump__std__array(d, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std__function(d, value):
|
def qdump__std__function(d, value):
|
||||||
(ptr, dummy1, manager, invoker) = value.split('pppp')
|
(ptr, dummy1, manager, invoker) = value.split('pppp')
|
||||||
if manager:
|
if manager:
|
||||||
@@ -70,10 +62,6 @@ def qdump__std__complex(d, value):
|
|||||||
d.putSubItem("imag", imag)
|
d.putSubItem("imag", imag)
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__complex(d, value):
|
|
||||||
qdump__std__complex(d, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std__deque(d, value):
|
def qdump__std__deque(d, value):
|
||||||
if d.isQnxTarget():
|
if d.isQnxTarget():
|
||||||
qdumpHelper__std__deque__qnx(d, value)
|
qdumpHelper__std__deque__qnx(d, value)
|
||||||
@@ -91,10 +79,6 @@ def qdump__std__deque(d, value):
|
|||||||
qdumpHelper__std__deque__libstdcxx(d, value)
|
qdumpHelper__std__deque__libstdcxx(d, value)
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__deque(d, value):
|
|
||||||
qdumpHelper__std__deque__libcxx(d, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qdumpHelper__std__deque__libstdcxx(d, value):
|
def qdumpHelper__std__deque__libstdcxx(d, value):
|
||||||
innerType = value.type[0]
|
innerType = value.type[0]
|
||||||
innerSize = innerType.size()
|
innerSize = innerType.size()
|
||||||
@@ -266,31 +250,6 @@ def qdump__std____cxx11__list(d, value):
|
|||||||
qdump__std__list(d, value)
|
qdump__std__list(d, value)
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__list(d, value):
|
|
||||||
if value.type.size() == 3 * d.ptrSize():
|
|
||||||
# C++11 only.
|
|
||||||
(dummy1, dummy2, size) = value.split("ppp")
|
|
||||||
d.putItemCount(size)
|
|
||||||
else:
|
|
||||||
# Need to count manually.
|
|
||||||
p = d.extractPointer(value)
|
|
||||||
head = value.address()
|
|
||||||
size = 0
|
|
||||||
while head != p and size < 1001:
|
|
||||||
size += 1
|
|
||||||
p = d.extractPointer(p)
|
|
||||||
d.putItemCount(size, 1000)
|
|
||||||
|
|
||||||
if d.isExpanded():
|
|
||||||
(prev, p) = value.split("pp")
|
|
||||||
innerType = value.type[0]
|
|
||||||
typeCode = "pp{%s}" % innerType.name
|
|
||||||
with Children(d, size, maxNumChild=1000, childType=innerType):
|
|
||||||
for i in d.childRange():
|
|
||||||
(prev, p, val) = d.split(typeCode, p)
|
|
||||||
d.putSubItem(i, val)
|
|
||||||
|
|
||||||
|
|
||||||
def qform__std__map():
|
def qform__std__map():
|
||||||
return [DisplayFormat.CompactMap]
|
return [DisplayFormat.CompactMap]
|
||||||
|
|
||||||
@@ -576,117 +535,6 @@ def std1TreeNext(d, node):
|
|||||||
return node['__parent_']
|
return node['__parent_']
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__set(d, value):
|
|
||||||
(proxy, head, size) = value.split("ppp")
|
|
||||||
|
|
||||||
d.check(0 <= size and size <= 100 * 1000 * 1000)
|
|
||||||
d.putItemCount(size)
|
|
||||||
|
|
||||||
if d.isExpanded():
|
|
||||||
valueType = value.type[0]
|
|
||||||
|
|
||||||
def in_order_traversal(node):
|
|
||||||
(left, right, parent, color, pad, data) = d.split("pppB@{%s}" % (valueType.name), node)
|
|
||||||
|
|
||||||
if left:
|
|
||||||
for res in in_order_traversal(left):
|
|
||||||
yield res
|
|
||||||
|
|
||||||
yield data
|
|
||||||
|
|
||||||
if right:
|
|
||||||
for res in in_order_traversal(right):
|
|
||||||
yield res
|
|
||||||
|
|
||||||
with Children(d, size, maxNumChild=1000):
|
|
||||||
for (i, data) in zip(d.childRange(), in_order_traversal(head)):
|
|
||||||
d.putSubItem(i, data)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__multiset(d, value):
|
|
||||||
qdump__std____1__set(d, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qform__std____1__map():
|
|
||||||
return [DisplayFormat.CompactMap]
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__map(d, value):
|
|
||||||
try:
|
|
||||||
(proxy, head, size) = value.split("ppp")
|
|
||||||
d.check(0 <= size and size <= 100 * 1000 * 1000)
|
|
||||||
|
|
||||||
# Sometimes there is extra data at the front. Don't know why at the moment.
|
|
||||||
except RuntimeError:
|
|
||||||
(junk, proxy, head, size) = value.split("pppp")
|
|
||||||
d.check(0 <= size and size <= 100 * 1000 * 1000)
|
|
||||||
|
|
||||||
d.putItemCount(size)
|
|
||||||
|
|
||||||
if d.isExpanded():
|
|
||||||
keyType = value.type[0]
|
|
||||||
valueType = value.type[1]
|
|
||||||
pairType = value.type[3][0]
|
|
||||||
|
|
||||||
def in_order_traversal(node):
|
|
||||||
(left, right, parent, color, pad, pair) = d.split("pppB@{%s}" % (pairType.name), node)
|
|
||||||
|
|
||||||
if left:
|
|
||||||
for res in in_order_traversal(left):
|
|
||||||
yield res
|
|
||||||
|
|
||||||
yield pair.split("{%s}@{%s}" % (keyType.name, valueType.name))[::2]
|
|
||||||
|
|
||||||
if right:
|
|
||||||
for res in in_order_traversal(right):
|
|
||||||
yield res
|
|
||||||
|
|
||||||
with Children(d, size, maxNumChild=1000):
|
|
||||||
for (i, pair) in zip(d.childRange(), in_order_traversal(head)):
|
|
||||||
d.putPairItem(i, pair)
|
|
||||||
|
|
||||||
|
|
||||||
def qform__std____1__multimap():
|
|
||||||
return [DisplayFormat.CompactMap]
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__multimap(d, value):
|
|
||||||
qdump__std____1__map(d, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__map__iterator(d, value):
|
|
||||||
d.putEmptyValue()
|
|
||||||
if d.isExpanded():
|
|
||||||
with Children(d):
|
|
||||||
node = value['__i_']['__ptr_'].dereference()['__value_']['__cc']
|
|
||||||
d.putSubItem('first', node['first'])
|
|
||||||
d.putSubItem('second', node['second'])
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__map__const_iterator(d, value):
|
|
||||||
qdump__std____1__map__iterator(d, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__set__iterator(d, value):
|
|
||||||
d.putEmptyValue()
|
|
||||||
d.putExpandable()
|
|
||||||
if value.type.name.endswith("::iterator"):
|
|
||||||
treeTypeName = value.type.name[:-len("::iterator")]
|
|
||||||
elif value.type.name.endswith("::const_iterator"):
|
|
||||||
treeTypeName = value.type.name[:-len("::const_iterator")]
|
|
||||||
treeType = d.lookupType(treeTypeName)
|
|
||||||
keyType = treeType[0]
|
|
||||||
if d.isExpanded():
|
|
||||||
with Children(d):
|
|
||||||
node = value['__ptr_'].dereference()['__value_']
|
|
||||||
node = node.cast(keyType)
|
|
||||||
d.putSubItem('value', node)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__set_const_iterator(d, value):
|
|
||||||
qdump__std____1__set__iterator(d, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std__stack(d, value):
|
def qdump__std__stack(d, value):
|
||||||
d.putItem(value["c"])
|
d.putItem(value["c"])
|
||||||
d.putBetterType(value.type)
|
d.putBetterType(value.type)
|
||||||
@@ -696,11 +544,6 @@ def qdump__std____debug__stack(d, value):
|
|||||||
qdump__std__stack(d, value)
|
qdump__std__stack(d, value)
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__stack(d, value):
|
|
||||||
d.putItem(value["c"])
|
|
||||||
d.putBetterType(value.type)
|
|
||||||
|
|
||||||
|
|
||||||
def qform__std__string():
|
def qform__std__string():
|
||||||
return [DisplayFormat.Latin1String, DisplayFormat.SeparateLatin1String,
|
return [DisplayFormat.Latin1String, DisplayFormat.SeparateLatin1String,
|
||||||
DisplayFormat.Utf8String, DisplayFormat.SeparateUtf8String]
|
DisplayFormat.Utf8String, DisplayFormat.SeparateUtf8String]
|
||||||
@@ -776,58 +619,6 @@ def qdumpHelper__std__string__MSVC(d, value, charType, format):
|
|||||||
d.putCharArrayHelper(data, size, charType, format)
|
d.putCharArrayHelper(data, size, charType, format)
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__string__alternateLayoutHelper(d, value):
|
|
||||||
try:
|
|
||||||
_d = value['__s']['__data_'].address()
|
|
||||||
alternateLayout = (_d - value.address()) == 0
|
|
||||||
if alternateLayout:
|
|
||||||
lastByte = value.split('b')[-1]
|
|
||||||
if int(lastByte & 0x80) == 0:
|
|
||||||
# Short/internal
|
|
||||||
size = value['__s']['__size_'].integer()
|
|
||||||
data = value.address()
|
|
||||||
else:
|
|
||||||
# Long/external
|
|
||||||
(data, size, _) = value.split('ppp')
|
|
||||||
return size, data
|
|
||||||
else:
|
|
||||||
return None, None
|
|
||||||
except:
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__string(d, value):
|
|
||||||
(size, data) = qdump__std____1__string__alternateLayoutHelper(d, value)
|
|
||||||
if size is None or data is None:
|
|
||||||
firstByte = value.split('b')[0]
|
|
||||||
if int(firstByte & 1) == 0:
|
|
||||||
# Short/internal.
|
|
||||||
size = int(firstByte / 2)
|
|
||||||
data = value.address() + 1
|
|
||||||
else:
|
|
||||||
# Long/external.
|
|
||||||
(_, size, data) = value.split('ppp')
|
|
||||||
|
|
||||||
d.putCharArrayHelper(data, size, d.charType(), d.currentItemFormat())
|
|
||||||
d.putType("std::string")
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__wstring(d, value):
|
|
||||||
(size, data) = qdump__std____1__string__alternateLayoutHelper(d, value)
|
|
||||||
if size is None or data is None:
|
|
||||||
firstByte = value.split('b')[0]
|
|
||||||
if int(firstByte & 1) == 0:
|
|
||||||
# Short/internal.
|
|
||||||
size = int(firstByte / 2)
|
|
||||||
data = value.address() + 4
|
|
||||||
else:
|
|
||||||
# Long/external.
|
|
||||||
(_, size, data) = value.split('ppp')
|
|
||||||
|
|
||||||
d.putCharArrayHelper(data, size, d.createType('wchar_t'))
|
|
||||||
d.putType("std::wstring")
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____weak_ptr(d, value):
|
def qdump__std____weak_ptr(d, value):
|
||||||
return qdump__std__shared_ptr(d, value)
|
return qdump__std__shared_ptr(d, value)
|
||||||
|
|
||||||
@@ -836,10 +627,6 @@ def qdump__std__weak_ptr(d, value):
|
|||||||
return qdump__std__shared_ptr(d, value)
|
return qdump__std__shared_ptr(d, value)
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__weak_ptr(d, value):
|
|
||||||
return qdump__std____1__shared_ptr(d, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std__shared_ptr(d, value):
|
def qdump__std__shared_ptr(d, value):
|
||||||
if d.isMsvcTarget():
|
if d.isMsvcTarget():
|
||||||
i = value["_Ptr"]
|
i = value["_Ptr"]
|
||||||
@@ -853,15 +640,6 @@ def qdump__std__shared_ptr(d, value):
|
|||||||
d.putBetterType(value.type)
|
d.putBetterType(value.type)
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__shared_ptr(d, value):
|
|
||||||
i = value["__ptr_"]
|
|
||||||
if i.pointer() == 0:
|
|
||||||
d.putValue("(null)")
|
|
||||||
else:
|
|
||||||
d.putItem(i.dereference())
|
|
||||||
d.putBetterType(value.type)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std__unique_ptr(d, value):
|
def qdump__std__unique_ptr(d, value):
|
||||||
if value.type.size() == d.ptrSize():
|
if value.type.size() == d.ptrSize():
|
||||||
p = d.extractPointer(value)
|
p = d.extractPointer(value)
|
||||||
@@ -874,10 +652,6 @@ def qdump__std__unique_ptr(d, value):
|
|||||||
d.putBetterType(value.type)
|
d.putBetterType(value.type)
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__unique_ptr(d, value):
|
|
||||||
qdump__std__unique_ptr(d, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std__pair(d, value):
|
def qdump__std__pair(d, value):
|
||||||
typeCode = '{%s}@{%s}' % (value.type[0].name, value.type[1].name)
|
typeCode = '{%s}@{%s}' % (value.type[0].name, value.type[1].name)
|
||||||
first, pad, second = value.split(typeCode)
|
first, pad, second = value.split(typeCode)
|
||||||
@@ -1012,52 +786,6 @@ def qdump__std__unordered_set(d, value):
|
|||||||
p = d.extractPointer(p + offset)
|
p = d.extractPointer(p + offset)
|
||||||
|
|
||||||
|
|
||||||
def qform__std____1__unordered_map():
|
|
||||||
return [DisplayFormat.CompactMap]
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__unordered_map(d, value):
|
|
||||||
(size, _) = value["__table_"]["__p2_"].split("pp")
|
|
||||||
d.putItemCount(size)
|
|
||||||
|
|
||||||
keyType = value.type[0]
|
|
||||||
valueType = value.type[1]
|
|
||||||
pairType = value.type[4][0]
|
|
||||||
|
|
||||||
if d.isExpanded():
|
|
||||||
curr = value["__table_"]["__p1_"].split("pp")[0]
|
|
||||||
|
|
||||||
def traverse_list(node):
|
|
||||||
while node:
|
|
||||||
(next_, _, pad, pair) = d.split("pp@{%s}" % (pairType.name), node)
|
|
||||||
yield pair.split("{%s}@{%s}" % (keyType.name, valueType.name))[::2]
|
|
||||||
node = next_
|
|
||||||
|
|
||||||
with Children(d, size, childType=value.type[0], maxNumChild=1000):
|
|
||||||
for (i, value) in zip(d.childRange(), traverse_list(curr)):
|
|
||||||
d.putPairItem(i, value, 'key', 'value')
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__unordered_set(d, value):
|
|
||||||
(size, _) = value["__table_"]["__p2_"].split("pp")
|
|
||||||
d.putItemCount(size)
|
|
||||||
|
|
||||||
valueType = value.type[0]
|
|
||||||
|
|
||||||
if d.isExpanded():
|
|
||||||
curr = value["__table_"]["__p1_"].split("pp")[0]
|
|
||||||
|
|
||||||
def traverse_list(node):
|
|
||||||
while node:
|
|
||||||
(next_, _, pad, val) = d.split("pp@{%s}" % (valueType.name), node)
|
|
||||||
yield val
|
|
||||||
node = next_
|
|
||||||
|
|
||||||
with Children(d, size, childType=value.type[0], maxNumChild=1000):
|
|
||||||
for (i, value) in zip(d.childRange(), traverse_list(curr)):
|
|
||||||
d.putSubItem(i, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____debug__unordered_set(d, value):
|
def qdump__std____debug__unordered_set(d, value):
|
||||||
qdump__std__unordered_set(d, value)
|
qdump__std__unordered_set(d, value)
|
||||||
|
|
||||||
@@ -1083,17 +811,6 @@ def qdump__std__valarray(d, value):
|
|||||||
d.putPlotData(data, size, value.type[0])
|
d.putPlotData(data, size, value.type[0])
|
||||||
|
|
||||||
|
|
||||||
def qform__std____1__valarray():
|
|
||||||
return [DisplayFormat.ArrayPlot]
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__valarray(d, value):
|
|
||||||
innerType = value.type[0]
|
|
||||||
(begin, end) = value.split('pp')
|
|
||||||
size = int((end - begin) / innerType.size())
|
|
||||||
d.putItemCount(size)
|
|
||||||
d.putPlotData(begin, size, innerType)
|
|
||||||
|
|
||||||
def qdump__std__variant(d, value):
|
def qdump__std__variant(d, value):
|
||||||
which = int(value["_M_index"])
|
which = int(value["_M_index"])
|
||||||
type = d.templateArgument(value.type, which)
|
type = d.templateArgument(value.type, which)
|
||||||
@@ -1208,14 +925,6 @@ def qdumpHelper__std__vector__msvc(d, value):
|
|||||||
qdumpHelper__std__vector__nonbool(d, start, finish, alloc, inner_type)
|
qdumpHelper__std__vector__nonbool(d, start, finish, alloc, inner_type)
|
||||||
|
|
||||||
|
|
||||||
def qform__std____1__vector():
|
|
||||||
return [DisplayFormat.ArrayPlot]
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__vector(d, value):
|
|
||||||
qdumpHelper__std__vector__libcxx(d, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qform__std____debug__vector():
|
def qform__std____debug__vector():
|
||||||
return [DisplayFormat.ArrayPlot]
|
return [DisplayFormat.ArrayPlot]
|
||||||
|
|
||||||
@@ -1317,24 +1026,10 @@ def qform__std____cxx11__wstring():
|
|||||||
return qform__std__wstring()
|
return qform__std__wstring()
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__basic_string(d, value):
|
|
||||||
innerType = value.type[0].name
|
|
||||||
if innerType in ("char", "char8_t", "char16_t"):
|
|
||||||
qdump__std____1__string(d, value)
|
|
||||||
elif innerType in ("wchar_t", "char32_t"):
|
|
||||||
qdump__std____1__wstring(d, value)
|
|
||||||
else:
|
|
||||||
d.warn("UNKNOWN INNER TYPE %s" % innerType)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__wstring(d, value):
|
def qdump__wstring(d, value):
|
||||||
qdump__std__wstring(d, value)
|
qdump__std__wstring(d, value)
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__once_flag(d, value):
|
|
||||||
qdump__std__once_flag(d, value)
|
|
||||||
|
|
||||||
|
|
||||||
def qdump__std__once_flag(d, value):
|
def qdump__std__once_flag(d, value):
|
||||||
d.putValue(value.split("i")[0])
|
d.putValue(value.split("i")[0])
|
||||||
d.putBetterType(value.type)
|
d.putBetterType(value.type)
|
||||||
|
Reference in New Issue
Block a user