* EnumerationValue -> EnumeratorValue

* Since some types don't have names (e.g. pointer types or anonymous structs or
  unions), each type does now also have a unique ID. The global type cache
  registers types by ID and by name (if they have one). This fixes clashes of
  types with empty names.
* Completely refactored the code dealing with variable values. Formerly we had
  Variable and TypeComponentPath to navigate to a component, mapped to a
  BVariant representing the value. Now we have:
  * Interface Value with various subclasses (BoolValue, IntegerValue, etc.) to
    represent a value, with the flexibility for more esoteric values.
  * A tree of ValueNode+ValueNodeChild objects to represent the components of a
    variable. On top of each ValueNodeChild sits a ValueNode representing the
    value of the component, potentially having ValueNodeChild children. This
    should allow casting a component value, simply by replacing its ValueNode.
  * Interface ValueHandler and various implementations for the different value
    types. It is basically a factory for classes allowing to format/display a
    value.
  * ValueHandlerRoster -- a registry for ValueHandlers, finding the best one
    for a given value.
  * Interface TypeHandler and various implementions for the different type
    kinds (primitive, compound, address, etc.). It is basically a factory for
    ValueNodes for that type.
  * TypeHandlerRoster -- a registry for TypeHandlers, finding the best one
    for a given type.

  That's still a bit work in progress. It introduces at least one regression:
  The VariablesView doesn't save/restore its state anymore. Will take a while
  until that is added back.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33907 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-11-05 18:15:21 +00:00
parent 173227dd53
commit 59ea286fac
84 changed files with 6373 additions and 1470 deletions
+12
View File
@@ -23,6 +23,8 @@
#include "MessageCodes.h"
#include "SettingsManager.h"
#include "TeamDebugger.h"
#include "TypeHandlerRoster.h"
#include "ValueHandlerRoster.h"
extern const char* __progname;
@@ -178,10 +180,20 @@ public:
~Debugger()
{
ValueHandlerRoster::DeleteDefault();
TypeHandlerRoster::DeleteDefault();
}
status_t Init()
{
status_t error = TypeHandlerRoster::CreateDefault();
if (error != B_OK)
return error;
error = ValueHandlerRoster::CreateDefault();
if (error != B_OK)
return error;
return fSettingsManager.Init();
}
+85 -30
View File
@@ -12,17 +12,23 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings generic ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui model ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui team_window ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui util ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui value ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) util ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) value ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) value value_handlers ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) value value_nodes ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) value values ] ;
local debugAnalyzerSources
= [ FDirName $(HAIKU_TOP) src apps debuganalyzer ] ;
@@ -96,31 +102,6 @@ Application Debugger :
LocatableFile.cpp
SourceFile.cpp
# user_interface
UserInterface.cpp
# user_interface/gui
GraphicalUserInterface.cpp
# user_interface/gui/model
VariablesViewState.cpp
VariablesViewStateHistory.cpp
# user_interface/gui/team_window
BreakpointListView.cpp
BreakpointsView.cpp
ImageFunctionsView.cpp
ImageListView.cpp
RegistersView.cpp
SourceView.cpp
StackTraceView.cpp
TeamWindow.cpp
ThreadListView.cpp
VariablesView.cpp
# user_interface/gui/util
TargetAddressTableColumn.cpp
# ids
FunctionID.cpp
LocalVariableID.cpp
@@ -154,6 +135,11 @@ Application Debugger :
TeamSettings.cpp
SettingsManager.cpp
# settings/generic
Setting.cpp
Settings.cpp
SettingsDescription.cpp
# source_language
CLanguage.cpp
CLanguageFamily.cpp
@@ -168,11 +154,80 @@ Application Debugger :
TargetAddressRangeList.cpp
ValueLocation.cpp
# user_interface
UserInterface.cpp
# user_interface/gui
GraphicalUserInterface.cpp
# user_interface/gui/model
VariablesViewState.cpp
VariablesViewStateHistory.cpp
# user_interface/gui/team_window
BreakpointListView.cpp
BreakpointsView.cpp
ImageFunctionsView.cpp
ImageListView.cpp
RegistersView.cpp
SourceView.cpp
StackTraceView.cpp
TeamWindow.cpp
ThreadListView.cpp
VariablesView.cpp
# user_interface/gui/util
SettingsMenu.cpp
TargetAddressTableColumn.cpp
# user_interface/gui/value
TableCellBoolRenderer.cpp
TableCellEnumerationRenderer.cpp
TableCellFloatRenderer.cpp
TableCellIntegerRenderer.cpp
TableCellStringRenderer.cpp
TableCellValueRenderer.cpp
TableCellValueRendererUtils.cpp
# util
ArchivingUtils.cpp
BitBuffer.cpp
IntegerFormatter.cpp
StringUtils.cpp
# value
TypeHandler.cpp
TypeHandlerRoster.cpp
Value.cpp
ValueHandler.cpp
ValueHandlerRoster.cpp
ValueLoader.cpp
ValueNode.cpp
ValueNodeContainer.cpp
# value/value_handlers
AddressValueHandler.cpp
BoolValueHandler.cpp
EnumerationValueHandler.cpp
FloatValueHandler.cpp
IntegerValueHandler.cpp
# value/value_nodes
AddressValueNode.cpp
ArrayValueNode.cpp
CompoundValueNode.cpp
EnumerationValueNode.cpp
PointerToMemberValueNode.cpp
PrimitiveValueNode.cpp
VariableValueNodeChild.cpp
# value/values
AddressValue.cpp
BoolValue.cpp
EnumerationValue.cpp
FloatValue.cpp
IntegerValue.cpp
:
<nogrist>Debugger_demangler.o
<nogrist>Debugger_disasm_x86.o
+146 -562
View File
@@ -29,7 +29,11 @@
#include "Tracing.h"
#include "Type.h"
#include "TypeComponentPath.h"
#include "Value.h"
#include "ValueLoader.h"
#include "ValueLocation.h"
#include "ValueNode.h"
#include "ValueNodeContainer.h"
#include "Variable.h"
@@ -406,627 +410,211 @@ LoadSourceCodeJob::Do()
}
// #pragma mark - GetStackFrameValueJobKey
// #pragma mark - ResolveValueNodeValueJob
GetStackFrameValueJobKey::GetStackFrameValueJobKey(StackFrame* stackFrame,
Variable* variable, TypeComponentPath* path)
:
stackFrame(stackFrame),
variable(variable),
path(path)
{
}
uint32
GetStackFrameValueJobKey::HashValue() const
{
uint32 hash = (uint32)(addr_t)stackFrame;
hash = hash * 13 + (uint32)(addr_t)variable;
return hash * 13 + path->HashValue();
}
bool
GetStackFrameValueJobKey::operator==(const JobKey& other) const
{
const GetStackFrameValueJobKey* otherKey
= dynamic_cast<const GetStackFrameValueJobKey*>(&other);
return otherKey != NULL && stackFrame == otherKey->stackFrame
&& variable == otherKey->variable && *path == *otherKey->path;
}
// #pragma mark - GetStackFrameValueJob
GetStackFrameValueJob::GetStackFrameValueJob(
ResolveValueNodeValueJob::ResolveValueNodeValueJob(
DebuggerInterface* debuggerInterface, Architecture* architecture,
Thread* thread, StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path)
CpuState* cpuState, ValueNodeContainer* container, ValueNode* valueNode)
:
fKey(stackFrame, variable, path),
fKey(valueNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE),
fDebuggerInterface(debuggerInterface),
fArchitecture(architecture),
fThread(thread),
fStackFrame(stackFrame),
fVariable(variable),
fPath(path)
fCpuState(cpuState),
fContainer(container),
fValueNode(valueNode)
{
fThread->AcquireReference();
fStackFrame->AcquireReference();
fVariable->AcquireReference();
fPath->AcquireReference();
if (fCpuState != NULL)
fCpuState->AcquireReference();
fContainer->AcquireReference();
fValueNode->AcquireReference();
}
GetStackFrameValueJob::~GetStackFrameValueJob()
ResolveValueNodeValueJob::~ResolveValueNodeValueJob()
{
fThread->ReleaseReference();
fStackFrame->ReleaseReference();
fVariable->ReleaseReference();
fPath->ReleaseReference();
if (fCpuState != NULL)
fCpuState->ReleaseReference();
fContainer->ReleaseReference();
fValueNode->ReleaseReference();
}
const JobKey&
GetStackFrameValueJob::Key() const
ResolveValueNodeValueJob::Key() const
{
return fKey;
}
status_t
GetStackFrameValueJob::Do()
ResolveValueNodeValueJob::Do()
{
status_t error = _GetValue();
if (error == B_OK)
return B_OK;
// check whether the node still belongs to the container
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
if (fValueNode->Container() != fContainer)
return B_BAD_VALUE;
// in case of error, set the value to invalid to avoid triggering this job
// again
AutoLocker<Team> locker(fThread->GetTeam());
fStackFrame->Values()->SetValue(fVariable->ID(), fPath, BVariant());
// if already resolved, we're done
status_t nodeResolutionState
= fValueNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
containerLocker.Unlock();
// resolve
status_t error = _ResolveNodeValue();
if (error != B_OK) {
nodeResolutionState = fValueNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
containerLocker.Lock();
fValueNode->SetLocationAndValue(NULL, NULL, error);
containerLocker.Unlock();
}
return error;
}
status_t
GetStackFrameValueJob::_GetValue()
ResolveValueNodeValueJob::_ResolveNodeValue()
{
TRACE_LOCALS_ONLY(
TRACE_LOCALS("GetStackFrameValueJob::_GetValue(): %s ",
fVariable->Name().String());
fPath->Dump();
TRACE_LOCALS("\n");
)
// get the node child and parent node
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
ValueNodeChild* nodeChild = fValueNode->NodeChild();
Reference<ValueNodeChild> nodeChildReference(nodeChild);
Type* type;
ValueNode* parentNode = nodeChild->Parent();
Reference<ValueNode> parentNodeReference(parentNode);
// Check whether the node child location has been resolved already
// (successfully).
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
bool nodeChildDone = nodeChildResolutionState != VALUE_NODE_UNRESOLVED;
if (nodeChildDone && nodeChildResolutionState != B_OK)
return nodeChildResolutionState;
// If the child node location has not been resolved yet, check whether the
// parent node location and value have been resolved already (successfully).
bool parentDone = true;
if (!nodeChildDone && parentNode != NULL) {
status_t parentResolutionState
= parentNode->LocationAndValueResolutionState();
parentDone = parentResolutionState != VALUE_NODE_UNRESOLVED;
if (parentDone && parentResolutionState != B_OK)
return parentResolutionState;
}
containerLocker.Unlock();
// resolve the parent node location and value, if necessary
if (!parentDone) {
status_t error = _ResolveParentNodeValue(parentNode);
if (error != B_OK) {
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
"node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n",
fValueNode, fValueNode->Name().String(), parentNode);
return error;
}
}
// resolve the node child location, if necessary
if (!nodeChildDone) {
status_t error = _ResolveNodeChildLocation(nodeChild);
if (error != B_OK) {
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
"node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n",
fValueNode, fValueNode->Name().String(), nodeChild);
return error;
}
}
// resolve the node location and value
ValueLoader valueLoader(fArchitecture, fDebuggerInterface, fCpuState);
ValueLocation* location;
bool valueResolved;
status_t error = _ResolveTypeAndLocation(type, location, valueResolved);
if (error != B_OK || valueResolved) {
TRACE_LOCALS(" -> error: %#lx, valueResolved: %d\n", error,
valueResolved);
return error;
}
Type* actualType = type;
Reference<Type> typeReference(type);
Reference<Type> actualTypeReference(actualType);
Reference<ValueLocation> locationReference(location);
// find out the type of the data we want to read
type_code valueType = 0;
bool shortValueIsFine = false;
while (valueType == 0) {
switch (type->Kind()) {
case TYPE_PRIMITIVE:
valueType = dynamic_cast<PrimitiveType*>(type)->TypeConstant();
shortValueIsFine = BVariant::TypeIsInteger(valueType)
|| valueType == B_BOOL_TYPE;
TRACE_LOCALS(" TYPE_PRIMITIVE: '%c%c%c%c'\n",
int(valueType >> 24), int(valueType >> 16),
int(valueType >> 8), int(valueType));
if (valueType == 0) {
TRACE_LOCALS(" -> unknown type constant\n");
return B_BAD_VALUE;
}
break;
case TYPE_MODIFIED:
TRACE_LOCALS(" TYPE_MODIFIED\n");
// ignore modifiers
type = dynamic_cast<ModifiedType*>(type)->BaseType();
break;
case TYPE_TYPEDEF:
TRACE_LOCALS(" TYPE_TYPEDEF\n");
type = dynamic_cast<TypedefType*>(type)->BaseType();
break;
case TYPE_ADDRESS:
case TYPE_POINTER_TO_MEMBER:
TRACE_LOCALS(" TYPE_ADDRESS/TYPE_POINTER_TO_MEMBER\n");
if (fArchitecture->AddressSize() == 4) {
valueType = B_UINT32_TYPE;
TRACE_LOCALS(" -> 32 bit\n");
} else {
valueType = B_UINT64_TYPE;
TRACE_LOCALS(" -> 64 bit\n");
}
break;
case TYPE_COMPOUND:
case TYPE_ARRAY:
TRACE_LOCALS(" TYPE_COMPOUND/TYPE_ARRAY\n");
// We can't retrieve the actual value of the compound object/
// array (just of its components/elements), but to make the
// recursion work smoothly, we have to set the type and
// location at least.
return _SetValue(BVariant(), actualType, location);
case TYPE_ENUMERATION:
{
TRACE_LOCALS(" TYPE_ENUMERATION\n");
// If a base type is known, use that.
EnumerationType* enumType
= dynamic_cast<EnumerationType*>(type);
if (enumType->BaseType() != NULL) {
type = enumType->BaseType();
break;
}
// get the value type constant
// TODO: This is C source language specific!
switch (enumType->ByteSize()) {
case 1:
valueType = B_INT8_TYPE;
break;
case 2:
valueType = B_INT16_TYPE;
break;
case 4:
default:
valueType = B_INT32_TYPE;
break;
case 8:
valueType = B_INT64_TYPE;
break;
}
shortValueIsFine = true;
break;
}
case TYPE_SUBRANGE:
TRACE_LOCALS(" TYPE_SUBRANGE -> unsupported\n");
return B_UNSUPPORTED;
case TYPE_UNSPECIFIED:
// Can't get the value for an unspecified type!
return B_BAD_VALUE;
case TYPE_FUNCTION:
TRACE_LOCALS(" TYPE_FUNCTION\n");
// Can't get the value for a function type!
return B_BAD_VALUE;
}
}
// update the reference in case the type has changed
typeReference.SetTo(type);
if (valueType == B_STRING_TYPE) {
TRACE_LOCALS(" -> B_STRING_TYPE: unsupported\n");
return B_UNSUPPORTED;
// TODO:...
}
// check whether we know the complete location
int32 count = location->CountPieces();
TRACE_LOCALS_ONLY(location->Dump();)
if (count == 0) {
TRACE_LOCALS(" -> no location\n");
return B_ENTRY_NOT_FOUND;
}
// If the source language implementation uses descriptors to point to
// objects, we need to resolve the object address to the data address.
if (count == 1) {
ValuePieceLocation piece = location->PieceAt(0);
if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
ValueLocation* dataLocation;
error = type->ResolveObjectDataLocation(*location, dataLocation);
if (error != B_OK)
return error;
location = dataLocation;
locationReference.SetTo(location, true);
}
}
static const size_t kMaxPieceSize = 16;
uint64 totalBitSize = 0;
for (int32 i = 0; i < count; i++) {
ValuePieceLocation piece = location->PieceAt(i);
switch (piece.type) {
case VALUE_PIECE_LOCATION_INVALID:
case VALUE_PIECE_LOCATION_UNKNOWN:
return B_ENTRY_NOT_FOUND;
case VALUE_PIECE_LOCATION_MEMORY:
case VALUE_PIECE_LOCATION_REGISTER:
break;
}
if (piece.size > kMaxPieceSize) {
TRACE_LOCALS(" -> overly long piece size (%llu bytes)\n",
piece.size);
return B_UNSUPPORTED;
}
totalBitSize += piece.bitSize;
}
TRACE_LOCALS(" -> totalBitSize: %llu\n", totalBitSize);
if (totalBitSize == 0) {
TRACE_LOCALS(" -> no size\n");
return B_ENTRY_NOT_FOUND;
}
if (totalBitSize > 64) {
TRACE_LOCALS(" -> longer than 64 bits: unsupported\n");
return B_UNSUPPORTED;
}
uint64 valueBitSize = BVariant::SizeOfType(valueType) * 8;
if (!shortValueIsFine && totalBitSize < valueBitSize) {
TRACE_LOCALS(" -> too short for value type (%llu vs. %llu bits)\n",
totalBitSize, valueBitSize);
return B_BAD_VALUE;
}
// Load the data. Since the BitBuffer class we're using only supports big
// endian bit semantics, we convert all data to big endian before pushing
// them to the buffer. For later conversion to BVariant we need to make sure
// the final buffer has the size of the value type, so we pad the most
// significant bits with zeros.
BitBuffer valueBuffer;
if (totalBitSize < valueBitSize)
valueBuffer.AddZeroBits(valueBitSize - totalBitSize);
bool bigEndian = fArchitecture->IsBigEndian();
const Register* registers = fArchitecture->Registers();
for (int32 i = 0; i < count; i++) {
ValuePieceLocation piece = location->PieceAt(
bigEndian ? i : count - i - 1);
uint32 bytesToRead = piece.size;
uint32 bitSize = piece.bitSize;
uint8 bitOffset = piece.bitOffset;
switch (piece.type) {
case VALUE_PIECE_LOCATION_INVALID:
case VALUE_PIECE_LOCATION_UNKNOWN:
return B_ENTRY_NOT_FOUND;
case VALUE_PIECE_LOCATION_MEMORY:
{
target_addr_t address = piece.address;
TRACE_LOCALS(" piece %ld: memory address: %#llx, bits: %lu\n",
i, address, bitSize);
uint8 pieceBuffer[kMaxPieceSize];
ssize_t bytesRead = fDebuggerInterface->ReadMemory(address,
pieceBuffer, bytesToRead);
if (bytesRead < 0)
return bytesRead;
if ((uint32)bytesRead != bytesToRead)
return B_BAD_ADDRESS;
TRACE_LOCALS_ONLY(
TRACE_LOCALS(" -> read: ");
for (ssize_t k = 0; k < bytesRead; k++)
TRACE_LOCALS("%02x", pieceBuffer[k]);
TRACE_LOCALS("\n");
)
// convert to big endian
if (!bigEndian) {
for (int32 k = bytesRead / 2 - 1; k >= 0; k--) {
std::swap(pieceBuffer[k],
pieceBuffer[bytesRead - k - 1]);
}
}
valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset);
break;
}
case VALUE_PIECE_LOCATION_REGISTER:
{
TRACE_LOCALS(" piece %ld: register: %lu, bits: %lu\n", i,
piece.reg, bitSize);
BVariant registerValue;
if (!fStackFrame->GetCpuState()->GetRegisterValue(
registers + piece.reg, registerValue)) {
return B_ENTRY_NOT_FOUND;
}
if (registerValue.Size() < bytesToRead)
return B_ENTRY_NOT_FOUND;
if (!bigEndian)
registerValue.SwapEndianess();
valueBuffer.AddBits(registerValue.Bytes(), bitSize, bitOffset);
break;
}
}
}
// If we don't have enough bits in the buffer apparently adding some failed.
if (valueBuffer.BitSize() < valueBitSize)
return B_NO_MEMORY;
// convert the bits into something we can work with
BVariant value;
error = value.SetToTypedData(valueBuffer.Bytes(), valueType);
Value* value;
status_t error = fValueNode->ResolvedLocationAndValue(&valueLoader,
location, value);
if (error != B_OK) {
TRACE_LOCALS(" -> failed to set typed data: %s\n", strerror(error));
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
"node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() "
"failed\n", fValueNode, fValueNode->Name().String());
return error;
}
Reference<ValueLocation> locationReference(location, true);
Reference<Value> valueReference(value, true);
// convert to host endianess
#if B_HOST_IS_LENDIAN
value.SwapEndianess();
#endif
// set location and value on the node
containerLocker.Lock();
status_t nodeResolutionState
= fValueNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
fValueNode->SetLocationAndValue(location, value, B_OK);
containerLocker.Unlock();
return _SetValue(value, actualType, location);
}
status_t
GetStackFrameValueJob::_SetValue(const BVariant& value, Type* type,
ValueLocation* location)
{
// set the value
AutoLocker<Team> locker(fThread->GetTeam());
status_t error = fStackFrame->Values()->SetValue(fVariable->ID(), fPath,
value);
if (error != B_OK) {
TRACE_LOCALS(" -> failed to set value: %s\n", strerror(error));
return error;
}
fStackFrame->ValueInfos()->SetInfo(fVariable->ID(), fPath, type, location);
fStackFrame->NotifyValueRetrieved(fVariable, fPath);
return B_OK;
}
status_t
GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type,
ValueLocation*& _location, bool& _valueResolved)
ResolveValueNodeValueJob::_ResolveNodeChildLocation(ValueNodeChild* nodeChild)
{
if (fPath->CountComponents() == 0) {
fVariable->GetType()->AcquireReference();
fVariable->Location()->AcquireReference();
_type = fVariable->GetType();
_location = fVariable->Location();
_valueResolved = false;
return B_OK;
}
// resolve the location
ValueLoader valueLoader(fArchitecture, fDebuggerInterface, fCpuState);
ValueLocation* location = NULL;
status_t error = nodeChild->ResolveLocation(&valueLoader, location);
Reference<ValueLocation> locationReference(location, true);
// get the parent value
int32 componentCount = fPath->CountComponents();
TypeComponentPath* parentPath = fPath->CreateSubPath(componentCount - 1);
if (parentPath == NULL)
return B_NO_MEMORY;
Reference<TypeComponentPath> parentPathReference(parentPath, true);
// set the location on the node child
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
if (nodeChildResolutionState == VALUE_NODE_UNRESOLVED)
nodeChild->SetLocation(location, error);
else
error = nodeChildResolutionState;
Type* parentType;
ValueLocation* parentLocation;
BVariant parentValue;
status_t error = _GetTypeLocationAndValue(parentPath, parentType,
parentLocation, parentValue);
if (error != B_OK) {
TRACE_LOCALS("GetStackFrameValueJob::_ResolveTypeAndLocation(): "
"_GetTypeLocationAndValue() failed: %s\n", strerror(error));
return error;
}
Reference<Type> parentTypeReference(parentType, true);
Reference<ValueLocation> parentLocationReference(parentLocation, true);
// resolve the last component
TypeComponent component = fPath->ComponentAt(componentCount - 1);
switch (component.typeKind) {
case TYPE_PRIMITIVE:
case TYPE_ENUMERATION:
case TYPE_SUBRANGE:
case TYPE_UNSPECIFIED:
case TYPE_FUNCTION:
case TYPE_POINTER_TO_MEMBER:
// cannot happen
TRACE_LOCALS("GetStackFrameValueJob::_ResolveTypeAndLocation(): "
"TYPE_PRIMITIVE/TYPE_ENUMERATION/TYPE_SUBRANGE/"
"TYPE_UNSPECIFIED/TYPE_FUNCTION/TYPE_POINTER_TO_MEMBER "
"subcomponent!\n");
return B_BAD_VALUE;
case TYPE_COMPOUND:
{
CompoundType* compoundType
= dynamic_cast<CompoundType*>(parentType);
// base type
if (component.componentKind == TYPE_COMPONENT_BASE_TYPE) {
BaseType* baseType = compoundType->BaseTypeAt(
component.index);
if (baseType == NULL)
return B_BAD_VALUE;
// The parent's location refers to the location of the complete
// object. We want to extract the location of a member.
ValueLocation* location;
error = compoundType->ResolveBaseTypeLocation(baseType,
*parentLocation, location);
if (error != B_OK) {
TRACE_LOCALS("GetStackFrameValueJob::"
"_ResolveTypeAndLocation(): TYPE_COMPOUND: "
"ResolveBaseTypeLocation() failed: %s\n",
strerror(error));
return error;
}
baseType->GetType()->AcquireReference();
_type = baseType->GetType();
_location = location;
_valueResolved = false;
return B_OK;
}
// data member
if (component.componentKind == TYPE_COMPONENT_DATA_MEMBER) {
DataMember* dataMember = compoundType->DataMemberAt(
component.index);
if (dataMember == NULL)
return B_BAD_VALUE;
// The parent's location refers to the location of the complete
// object. We want to extract the location of a member.
ValueLocation* location;
error = compoundType->ResolveDataMemberLocation(dataMember,
*parentLocation, location);
if (error != B_OK) {
TRACE_LOCALS("GetStackFrameValueJob::"
"_ResolveTypeAndLocation(): TYPE_COMPOUND: "
"ResolveDataMemberLocation() failed: %s\n",
strerror(error));
return error;
}
dataMember->GetType()->AcquireReference();
_type = dataMember->GetType();
_location = location;
_valueResolved = false;
return B_OK;
}
return B_UNSUPPORTED;
}
case TYPE_MODIFIED:
case TYPE_TYPEDEF:
{
Type* type = component.typeKind == TYPE_MODIFIED
? dynamic_cast<ModifiedType*>(parentType)->BaseType()
: dynamic_cast<TypedefType*>(parentType)->BaseType();
_valueResolved = true;
return _SetValue(parentValue, type, parentLocation);
}
case TYPE_ADDRESS:
{
// The parent's value is an address pointing to this component.
// resolve the location
Type* type = dynamic_cast<AddressType*>(parentType)->BaseType();
ValueLocation* location;
error = type->ResolveObjectDataLocation(parentValue.ToUInt64(),
location);
if (error != B_OK) {
TRACE_LOCALS("GetStackFrameValueJob::"
"_ResolveTypeAndLocation(): "
"TYPE_ADDRESS/TYPE_POINTER_TO_MEMBER: "
"ResolveObjectDataLocation() failed: %s\n",
strerror(error));
return error;
}
type->AcquireReference();
_type = type;
_location = location;
_valueResolved = false;
return B_OK;
}
case TYPE_ARRAY:
{
ArrayType* arrayType = dynamic_cast<ArrayType*>(parentType);
if (component.componentKind != TYPE_COMPONENT_ARRAY_ELEMENT)
return B_UNSUPPORTED;
// get the index path
ArrayIndexPath indexPath;
error = indexPath.SetTo(component.name.String());
if (error != B_OK)
return error;
if (indexPath.CountIndices() != arrayType->CountDimensions())
return B_UNSUPPORTED;
// resolve the element location
ValueLocation* location;
error = arrayType->ResolveElementLocation(indexPath,
*parentLocation, location);
if (error != B_OK) {
TRACE_LOCALS("GetStackFrameValueJob::"
"_ResolveTypeAndLocation(): TYPE_ARRAY: "
"ResolveElementLocation() failed: %s\n",
strerror(error));
return error;
}
arrayType->BaseType()->AcquireReference();
_type = arrayType->BaseType();
_location = location;
_valueResolved = false;
return B_OK;
}
}
// Can never get here.
return B_UNSUPPORTED;
return error;
}
status_t
GetStackFrameValueJob::_GetTypeLocationAndValue(TypeComponentPath* parentPath,
Type*& _parentType, ValueLocation*& _parentLocation, BVariant& _parentValue)
ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode* parentNode)
{
AutoLocker<Team> teamLocker(fThread->GetTeam());
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
// If there's already a value for the parent path, we're done.
StackFrameValues* values = fStackFrame->Values();
StackFrameValueInfos* valueInfos = fStackFrame->ValueInfos();
if (values->HasValue(fVariable->ID(), parentPath)) {
if (!values->GetValue(fVariable->ID(), parentPath, _parentValue)
|| !valueInfos->GetInfo(fVariable->ID(), parentPath, &_parentType,
&_parentLocation)) {
return B_ERROR;
}
if (parentNode->Container() != fContainer)
return B_BAD_VALUE;
return B_OK;
}
// if the parent node already has a value, we're done
status_t nodeResolutionState
= parentNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
// check whether a job is already in progress
AutoLocker<Worker> workerLocker(GetWorker());
GetStackFrameValueJobKey jobKey(fStackFrame, fVariable, parentPath);
SimpleJobKey jobKey(parentNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE);
if (GetWorker()->GetJob(jobKey) == NULL) {
workerLocker.Unlock();
// schedule the job
status_t error = GetWorker()->ScheduleJob(
new(std::nothrow) GetStackFrameValueJob(fDebuggerInterface,
fArchitecture, fThread, fStackFrame, fVariable, parentPath));
new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface,
fArchitecture, fCpuState, fContainer, parentNode));
if (error != B_OK) {
// scheduling failed -- set the value to invalid
values->SetValue(fVariable->ID(), parentPath, BVariant());
parentNode->SetLocationAndValue(NULL, NULL, error);
return error;
}
}
// wait for the job to finish
workerLocker.Unlock();
teamLocker.Unlock();
containerLocker.Unlock();
switch (WaitFor(jobKey)) {
case JOB_DEPENDENCY_SUCCEEDED:
@@ -1040,14 +628,10 @@ GetStackFrameValueJob::_GetTypeLocationAndValue(TypeComponentPath* parentPath,
return B_ERROR;
}
teamLocker.Lock();
containerLocker.Lock();
// now there should be a value for the path
if (!values->GetValue(fVariable->ID(), parentPath, _parentValue)
|| !valueInfos->GetInfo(fVariable->ID(), parentPath, &_parentType,
&_parentLocation)) {
return B_ERROR;
}
return B_OK;
// now there should be a value for the node
nodeResolutionState = parentNode->LocationAndValueResolutionState();
return nodeResolutionState != VALUE_NODE_UNRESOLVED
? nodeResolutionState : B_ERROR;
}
+20 -46
View File
@@ -24,6 +24,9 @@ class Thread;
class Type;
class TypeComponentPath;
class ValueLocation;
class ValueNode;
class ValueNodeChild;
class ValueNodeContainer;
class Variable;
@@ -34,7 +37,8 @@ enum {
JOB_TYPE_GET_STACK_TRACE,
JOB_TYPE_LOAD_IMAGE_DEBUG_INFO,
JOB_TYPE_LOAD_SOURCE_CODE,
JOB_TYPE_GET_STACK_FRAME_VALUE
JOB_TYPE_GET_STACK_FRAME_VALUE,
JOB_TYPE_RESOLVE_VALUE_NODE_VALUE
};
@@ -143,63 +147,33 @@ private:
};
struct GetStackFrameValueJobKey : JobKey {
StackFrame* stackFrame;
Variable* variable;
TypeComponentPath* path;
class ResolveValueNodeValueJob : public Job {
public:
GetStackFrameValueJobKey(
StackFrame* stackFrame,
Variable* variable,
TypeComponentPath* path);
virtual uint32 HashValue() const;
virtual bool operator==(const JobKey& other) const;
};
class GetStackFrameValueJob : public Job {
public:
GetStackFrameValueJob(
ResolveValueNodeValueJob(
DebuggerInterface* debuggerInterface,
Architecture* architecture,
Thread* thread, StackFrame* stackFrame,
Variable* variable,
TypeComponentPath* path);
virtual ~GetStackFrameValueJob();
CpuState* cpuState,
ValueNodeContainer* container,
ValueNode* valueNode);
virtual ~ResolveValueNodeValueJob();
virtual const JobKey& Key() const;
virtual status_t Do();
private:
struct ValueJobKey;
status_t _ResolveNodeValue();
status_t _ResolveNodeChildLocation(
ValueNodeChild* nodeChild);
status_t _ResolveParentNodeValue(ValueNode* parentNode);
private:
status_t _GetValue();
status_t _SetValue(const BVariant& value, Type* type,
ValueLocation* location);
status_t _ResolveTypeAndLocation(Type*& _type,
ValueLocation*& _location,
bool& _valueResolved);
// returns references
status_t _GetTypeLocationAndValue(
TypeComponentPath* parentPath,
Type*& _parentType,
ValueLocation*& _parentLocation,
BVariant& _parentValue);
// returns references
private:
GetStackFrameValueJobKey fKey;
SimpleJobKey fKey;
DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture;
Thread* fThread;
StackFrame* fStackFrame;
Variable* fVariable;
TypeComponentPath* fPath;
CpuState* fCpuState;
ValueNodeContainer* fContainer;
ValueNode* fValueNode;
};
+32 -21
View File
@@ -7,30 +7,41 @@
enum {
MSG_THREAD_RUN = 'run_',
MSG_THREAD_STOP = 'stop',
MSG_THREAD_STEP_OVER = 'stov',
MSG_THREAD_STEP_INTO = 'stin',
MSG_THREAD_STEP_OUT = 'stou',
MSG_SET_BREAKPOINT = 'sbrk',
MSG_CLEAR_BREAKPOINT = 'cbrk',
MSG_ENABLE_BREAKPOINT = 'ebrk',
MSG_DISABLE_BREAKPOINT = 'dbrk',
MSG_THREAD_RUN = 'run_',
MSG_THREAD_STOP = 'stop',
MSG_THREAD_STEP_OVER = 'stov',
MSG_THREAD_STEP_INTO = 'stin',
MSG_THREAD_STEP_OUT = 'stou',
MSG_SET_BREAKPOINT = 'sbrk',
MSG_CLEAR_BREAKPOINT = 'cbrk',
MSG_ENABLE_BREAKPOINT = 'ebrk',
MSG_DISABLE_BREAKPOINT = 'dbrk',
MSG_THREAD_STATE_CHANGED = 'tsch',
MSG_THREAD_CPU_STATE_CHANGED = 'tcsc',
MSG_THREAD_STACK_TRACE_CHANGED = 'tstc',
MSG_STACK_FRAME_VALUE_RETRIEVED = 'sfvr',
MSG_IMAGE_DEBUG_INFO_CHANGED = 'idic',
MSG_IMAGE_FILE_CHANGED = 'ifch',
MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc',
MSG_USER_BREAKPOINT_CHANGED = 'ubrc',
MSG_DEBUGGER_EVENT = 'dbge',
MSG_LOAD_SETTINGS = 'ldst',
MSG_THREAD_STATE_CHANGED = 'tsch',
MSG_THREAD_CPU_STATE_CHANGED = 'tcsc',
MSG_THREAD_STACK_TRACE_CHANGED = 'tstc',
MSG_STACK_FRAME_VALUE_RETRIEVED = 'sfvr',
MSG_IMAGE_DEBUG_INFO_CHANGED = 'idic',
MSG_IMAGE_FILE_CHANGED = 'ifch',
MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc',
MSG_USER_BREAKPOINT_CHANGED = 'ubrc',
MSG_DEBUGGER_EVENT = 'dbge',
MSG_LOAD_SETTINGS = 'ldst',
MSG_TEXTVIEW_AUTOSCROLL = 'tvas',
MSG_SETTINGS_MENU_IMPL_ITEM_SELECTED = 'smii',
MSG_SETTINGS_MENU_IMPL_OPTION_ITEM_SELECTED = 'smio',
MSG_TEAM_DEBUGGER_QUIT = 'dbqt'
MSG_TEXTVIEW_AUTOSCROLL = 'tvas',
MSG_VARIABLES_VIEW_CONTEXT_MENU_DONE = 'ctxd',
MSG_VARIABLES_VIEW_NODE_SETTINGS_CHANGED = 'vvns',
MSG_VALUE_NODE_CHANGED = 'vnch',
MSG_VALUE_NODE_CHILDREN_CREATED = 'vncc',
MSG_VALUE_NODE_CHILDREN_DELETED = 'vncd',
MSG_VALUE_NODE_VALUE_CHANGED = 'vnvc',
MSG_TEAM_DEBUGGER_QUIT = 'dbqt'
};
+15 -10
View File
@@ -38,6 +38,8 @@
#include "TeamDebugInfo.h"
#include "TeamSettings.h"
#include "Tracing.h"
#include "ValueNode.h"
#include "ValueNodeContainer.h"
#include "Variable.h"
// #pragma mark - ImageHandler
@@ -558,26 +560,29 @@ TeamDebugger::ImageDebugInfoRequested(Image* image)
void
TeamDebugger::StackFrameValueRequested(::Thread* thread, StackFrame* stackFrame,
Variable* variable, TypeComponentPath* path)
TeamDebugger::ValueNodeValueRequested(CpuState* cpuState,
ValueNodeContainer* container, ValueNode* valueNode)
{
// the team is already locked
AutoLocker<ValueNodeContainer> containerLocker(container);
if (valueNode->Container() != container)
return;
// check whether a job is already in progress
AutoLocker<Worker> workerLocker(fWorker);
GetStackFrameValueJobKey jobKey(stackFrame, variable, path);
SimpleJobKey jobKey(valueNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE);
if (fWorker->GetJob(jobKey) != NULL)
return;
workerLocker.Unlock();
// schedule the job
if (fWorker->ScheduleJob(
new(std::nothrow) GetStackFrameValueJob(fDebuggerInterface,
fDebuggerInterface->GetArchitecture(), thread, stackFrame,
variable, path),
this) != B_OK) {
status_t error = fWorker->ScheduleJob(
new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface,
fDebuggerInterface->GetArchitecture(), cpuState, container,
valueNode),
this);
if (error != B_OK) {
// scheduling failed -- set the value to invalid
stackFrame->Values()->SetValue(variable->ID(), path, BVariant());
valueNode->SetLocationAndValue(NULL, NULL, error);
}
}
+3 -3
View File
@@ -47,9 +47,9 @@ private:
virtual void FunctionSourceCodeRequested(
FunctionInstance* function);
virtual void ImageDebugInfoRequested(Image* image);
virtual void StackFrameValueRequested(::Thread* thread,
StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path);
virtual void ValueNodeValueRequested(CpuState* cpuState,
ValueNodeContainer* container,
ValueNode* valueNode);
virtual void ThreadActionRequested(thread_id threadID,
uint32 action);
virtual void SetBreakpointRequested(target_addr_t address,
@@ -193,6 +193,13 @@ DwarfTypeFactory::CreateType(DIEType* typeEntry, DwarfType*& _type)
AutoLocker<GlobalTypeCache> cacheLocker(fTypeCache);
Type* globalType = name.Length() > 0
? fTypeCache->GetType(name) : NULL;
if (globalType == NULL) {
// lookup by name failed -- try lookup by ID
BString id;
if (DwarfType::GetTypeID(typeEntry, id))
globalType = fTypeCache->GetTypeByID(id);
}
if (globalType != NULL) {
DwarfType* globalDwarfType = dynamic_cast<DwarfType*>(globalType);
if (globalDwarfType != NULL) {
@@ -228,15 +235,15 @@ DwarfTypeFactory::CreateType(DIEType* typeEntry, DwarfType*& _type)
// Insert the type into the cache. Re-check, as the type may already
// have been inserted (e.g. in the compound type case).
if (name.Length() > 0) {
cacheLocker.Lock();
if (fTypeCache->GetType(name) == NULL) {
error = fTypeCache->AddType(name, type);
if (error != B_OK)
return error;
}
cacheLocker.Unlock();
cacheLocker.Lock();
if (name.Length() > 0
? fTypeCache->GetType(name) == NULL
: fTypeCache->GetTypeByID(type->ID()) == NULL) {
error = fTypeCache->AddType(type);
if (error != B_OK)
return error;
}
cacheLocker.Unlock();
// try to get the type's size
uint64 size;
@@ -354,9 +361,12 @@ DwarfTypeFactory::_CreateCompoundType(const BString& name,
// incomplete type could become visible to other threads. Hence we keep the
// context locked, but that essentially kills multi-threading for this context.
AutoLocker<GlobalTypeCache> cacheLocker(fTypeCache);
status_t error = fTypeCache->AddType(name, type);
status_t error = fTypeCache->AddType(type);
if (error != B_OK)
{
printf(" -> failed to add type to cache\n");
return error;
}
// cacheLocker.Unlock();
// find the abstract origin or specification that defines the data members
@@ -388,7 +398,7 @@ DwarfTypeFactory::_CreateCompoundType(const BString& name,
Reference<DwarfDataMember> memberReference(member, true);
if (member == NULL || !type->AddDataMember(member)) {
cacheLocker.Lock();
fTypeCache->RemoveType(name);
fTypeCache->RemoveType(type);
return B_NO_MEMORY;
}
}
@@ -423,7 +433,7 @@ DwarfTypeFactory::_CreateCompoundType(const BString& name,
true);
if (inheritance == NULL || !type->AddInheritance(inheritance)) {
cacheLocker.Lock();
fTypeCache->RemoveType(name);
fTypeCache->RemoveType(type);
return B_NO_MEMORY;
}
}
@@ -808,10 +818,10 @@ DwarfTypeFactory::_CreateEnumerationType(const BString& name,
}
// create and add the enumeration value object
DwarfEnumerationValue* enumValue
= new(std::nothrow) DwarfEnumerationValue(enumeratorEntry,
DwarfEnumeratorValue* enumValue
= new(std::nothrow) DwarfEnumeratorValue(enumeratorEntry,
enumeratorEntry->Name(), value);
Reference<DwarfEnumerationValue> enumValueReference(enumValue, true);
Reference<DwarfEnumeratorValue> enumValueReference(enumValue, true);
if (enumValue == NULL || !type->AddValue(enumValue))
return B_NO_MEMORY;
}
@@ -32,7 +32,7 @@ class DwarfArrayType;
class DwarfCompoundType;
class DwarfDataMember;
class DwarfEnumerationType;
class DwarfEnumerationValue;
class DwarfEnumeratorValue;
class DwarfFile;
class DwarfFunctionParameter;
class DwarfFunctionType;
+46 -22
View File
@@ -85,13 +85,16 @@ DwarfTypeContext::~DwarfTypeContext()
// #pragma mark - DwarfType
DwarfType::DwarfType(DwarfTypeContext* typeContext, const BString& name)
DwarfType::DwarfType(DwarfTypeContext* typeContext, const BString& name,
const DIEType* entry)
:
fTypeContext(typeContext),
fName(name),
fByteSize(0)
{
fTypeContext->AcquireReference();
GetTypeID(entry, fID);
}
@@ -101,6 +104,20 @@ DwarfType::~DwarfType()
}
/*static*/ bool
DwarfType::GetTypeID(const DIEType* entry, BString& _id)
{
char buffer[32];
snprintf(buffer, sizeof(buffer), "dwarf:%p", entry);
BString id = buffer;
if (id.Length() == 0)
return false;
_id = id;
return true;
}
image_id
DwarfType::ImageID() const
{
@@ -108,10 +125,17 @@ DwarfType::ImageID() const
}
const char*
const BString&
DwarfType::ID() const
{
return fID;
}
const BString&
DwarfType::Name() const
{
return fName.Length() > 0 ? fName.String() : NULL;
return fName;
}
@@ -308,10 +332,10 @@ DwarfDataMember::GetType() const
}
// #pragma mark - DwarfEnumerationValue
// #pragma mark - DwarfEnumeratorValue
DwarfEnumerationValue::DwarfEnumerationValue(DIEEnumerator* entry,
DwarfEnumeratorValue::DwarfEnumeratorValue(DIEEnumerator* entry,
const BString& name, const BVariant& value)
:
fEntry(entry),
@@ -321,19 +345,19 @@ DwarfEnumerationValue::DwarfEnumerationValue(DIEEnumerator* entry,
}
DwarfEnumerationValue::~DwarfEnumerationValue()
DwarfEnumeratorValue::~DwarfEnumeratorValue()
{
}
const char*
DwarfEnumerationValue::Name() const
DwarfEnumeratorValue::Name() const
{
return fName.Length() > 0 ? fName.String() : NULL;
}
BVariant
DwarfEnumerationValue::Value() const
DwarfEnumeratorValue::Value() const
{
return fValue;
}
@@ -403,7 +427,7 @@ DwarfFunctionParameter::GetType() const
DwarfPrimitiveType::DwarfPrimitiveType(DwarfTypeContext* typeContext,
const BString& name, DIEBaseType* entry, uint32 typeConstant)
:
DwarfType(typeContext, name),
DwarfType(typeContext, name, entry),
fEntry(entry),
fTypeConstant(typeConstant)
{
@@ -430,7 +454,7 @@ DwarfPrimitiveType::TypeConstant() const
DwarfCompoundType::DwarfCompoundType(DwarfTypeContext* typeContext,
const BString& name, DIECompoundType* entry)
:
DwarfType(typeContext, name),
DwarfType(typeContext, name, entry),
fEntry(entry)
{
}
@@ -684,7 +708,7 @@ DwarfCompoundType::_ResolveDataMemberLocation(DwarfType* memberType,
DwarfArrayType::DwarfArrayType(DwarfTypeContext* typeContext,
const BString& name, DIEArrayType* entry, DwarfType* baseType)
:
DwarfType(typeContext, name),
DwarfType(typeContext, name, entry),
fEntry(entry),
fBaseType(baseType)
{
@@ -908,7 +932,7 @@ DwarfModifiedType::DwarfModifiedType(DwarfTypeContext* typeContext,
const BString& name, DIEModifiedType* entry, uint32 modifiers,
DwarfType* baseType)
:
DwarfType(typeContext, name),
DwarfType(typeContext, name, entry),
fEntry(entry),
fModifiers(modifiers),
fBaseType(baseType)
@@ -950,7 +974,7 @@ DwarfModifiedType::GetDIEType() const
DwarfTypedefType::DwarfTypedefType(DwarfTypeContext* typeContext,
const BString& name, DIETypedef* entry, DwarfType* baseType)
:
DwarfType(typeContext, name),
DwarfType(typeContext, name, entry),
fEntry(entry),
fBaseType(baseType)
{
@@ -985,7 +1009,7 @@ DwarfAddressType::DwarfAddressType(DwarfTypeContext* typeContext,
const BString& name, DIEAddressingType* entry,
address_type_kind addressKind, DwarfType* baseType)
:
DwarfType(typeContext, name),
DwarfType(typeContext, name, entry),
fEntry(entry),
fAddressKind(addressKind),
fBaseType(baseType)
@@ -1027,7 +1051,7 @@ DwarfAddressType::GetDIEType() const
DwarfEnumerationType::DwarfEnumerationType(DwarfTypeContext* typeContext,
const BString& name, DIEEnumerationType* entry, DwarfType* baseType)
:
DwarfType(typeContext, name),
DwarfType(typeContext, name, entry),
fEntry(entry),
fBaseType(baseType)
{
@@ -1038,7 +1062,7 @@ DwarfEnumerationType::DwarfEnumerationType(DwarfTypeContext* typeContext,
DwarfEnumerationType::~DwarfEnumerationType()
{
for (int32 i = 0; DwarfEnumerationValue* value = fValues.ItemAt(i); i++)
for (int32 i = 0; DwarfEnumeratorValue* value = fValues.ItemAt(i); i++)
value->ReleaseReference();
if (fBaseType != NULL)
@@ -1060,7 +1084,7 @@ DwarfEnumerationType::CountValues() const
}
EnumerationValue*
EnumeratorValue*
DwarfEnumerationType::ValueAt(int32 index) const
{
return fValues.ItemAt(index);
@@ -1075,7 +1099,7 @@ DwarfEnumerationType::GetDIEType() const
bool
DwarfEnumerationType::AddValue(DwarfEnumerationValue* value)
DwarfEnumerationType::AddValue(DwarfEnumeratorValue* value)
{
if (!fValues.AddItem(value))
return false;
@@ -1092,7 +1116,7 @@ DwarfSubrangeType::DwarfSubrangeType(DwarfTypeContext* typeContext,
const BString& name, DIESubrangeType* entry, DwarfType* baseType,
const BVariant& lowerBound, const BVariant& upperBound)
:
DwarfType(typeContext, name),
DwarfType(typeContext, name, entry),
fEntry(entry),
fBaseType(baseType),
fLowerBound(lowerBound),
@@ -1142,7 +1166,7 @@ DwarfSubrangeType::UpperBound() const
DwarfUnspecifiedType::DwarfUnspecifiedType(DwarfTypeContext* typeContext,
const BString& name, DIEUnspecifiedType* entry)
:
DwarfType(typeContext, name),
DwarfType(typeContext, name, entry),
fEntry(entry)
{
}
@@ -1166,7 +1190,7 @@ DwarfUnspecifiedType::GetDIEType() const
DwarfFunctionType::DwarfFunctionType(DwarfTypeContext* typeContext,
const BString& name, DIESubroutineType* entry, DwarfType* returnType)
:
DwarfType(typeContext, name),
DwarfType(typeContext, name, entry),
fEntry(entry),
fReturnType(returnType),
fHasVariableArguments(false)
@@ -1249,7 +1273,7 @@ DwarfPointerToMemberType::DwarfPointerToMemberType(
DIEPointerToMemberType* entry, DwarfCompoundType* containingType,
DwarfType* baseType)
:
DwarfType(typeContext, name),
DwarfType(typeContext, name, entry),
fEntry(entry),
fContainingType(containingType),
fBaseType(baseType)
+12 -8
View File
@@ -88,11 +88,14 @@ private:
class DwarfType : public virtual Type {
public:
DwarfType(DwarfTypeContext* typeContext,
const BString& name);
const BString& name, const DIEType* entry);
~DwarfType();
static bool GetTypeID(const DIEType* entry, BString& _id);
virtual image_id ImageID() const;
virtual const char* Name() const;
virtual const BString& ID() const;
virtual const BString& Name() const;
virtual target_size_t ByteSize() const;
virtual status_t ResolveObjectDataLocation(
@@ -118,6 +121,7 @@ public:
private:
DwarfTypeContext* fTypeContext;
BString fName;
BString fID;
target_size_t fByteSize;
};
@@ -162,11 +166,11 @@ private:
};
class DwarfEnumerationValue : public EnumerationValue {
class DwarfEnumeratorValue : public EnumeratorValue {
public:
DwarfEnumerationValue(DIEEnumerator* entry,
DwarfEnumeratorValue(DIEEnumerator* entry,
const BString& name, const BVariant& value);
~DwarfEnumerationValue();
~DwarfEnumeratorValue();
virtual const char* Name() const;
virtual BVariant Value() const;
@@ -396,17 +400,17 @@ public:
virtual Type* BaseType() const;
virtual int32 CountValues() const;
virtual EnumerationValue* ValueAt(int32 index) const;
virtual EnumeratorValue* ValueAt(int32 index) const;
virtual DIEType* GetDIEType() const;
bool AddValue(DwarfEnumerationValue* value);
bool AddValue(DwarfEnumeratorValue* value);
DIEEnumerationType* Entry() const
{ return fEntry; }
private:
typedef BObjectList<DwarfEnumerationValue> ValueList;
typedef BObjectList<DwarfEnumeratorValue> ValueList;
private:
DIEEnumerationType* fEntry;
@@ -17,13 +17,12 @@
struct GlobalTypeCache::TypeEntry {
BString name;
Type* type;
TypeEntry* fNext;
TypeEntry* fNextByName;
TypeEntry* fNextByID;
TypeEntry(const BString& name, Type* type)
TypeEntry(Type* type)
:
name(name),
type(type)
{
type->AcquireReference();
@@ -36,7 +35,7 @@ struct GlobalTypeCache::TypeEntry {
};
struct GlobalTypeCache::TypeEntryHashDefinition {
struct GlobalTypeCache::TypeEntryHashDefinitionByName {
typedef const BString KeyType;
typedef TypeEntry ValueType;
@@ -47,17 +46,43 @@ struct GlobalTypeCache::TypeEntryHashDefinition {
size_t Hash(const TypeEntry* value) const
{
return HashKey(value->name);
return HashKey(value->type->Name());
}
bool Compare(const BString& key, const TypeEntry* value) const
{
return key == value->name;
return key == value->type->Name();
}
TypeEntry*& GetLink(TypeEntry* value) const
{
return value->fNext;
return value->fNextByName;
}
};
struct GlobalTypeCache::TypeEntryHashDefinitionByID {
typedef const BString KeyType;
typedef TypeEntry ValueType;
size_t HashKey(const BString& key) const
{
return StringUtils::HashValue(key);
}
size_t Hash(const TypeEntry* value) const
{
return HashKey(value->type->ID());
}
bool Compare(const BString& key, const TypeEntry* value) const
{
return key == value->type->ID();
}
TypeEntry*& GetLink(TypeEntry* value) const
{
return value->fNextByID;
}
};
@@ -67,19 +92,23 @@ struct GlobalTypeCache::TypeEntryHashDefinition {
GlobalTypeCache::GlobalTypeCache()
:
fLock("global type lookup"),
fTypes(NULL)
fLock("global type cache"),
fTypesByName(NULL),
fTypesByID(NULL)
{
}
GlobalTypeCache::~GlobalTypeCache()
{
if (fTypesByName != NULL)
fTypesByName->Clear();
// release all cached type references
if (fTypes != NULL) {
TypeEntry* entry = fTypes->Clear(true);
if (fTypesByID != NULL) {
TypeEntry* entry = fTypesByID->Clear(true);
while (entry != NULL) {
TypeEntry* nextEntry = entry->fNext;
TypeEntry* nextEntry = entry->fNextByID;
delete entry;
entry = nextEntry;
}
@@ -90,48 +119,85 @@ GlobalTypeCache::~GlobalTypeCache()
status_t
GlobalTypeCache::Init()
{
// check lock
status_t error = fLock.InitCheck();
if (error != B_OK)
return error;
fTypes = new(std::nothrow) TypeTable;
if (fTypes == NULL)
// create name table
fTypesByName = new(std::nothrow) NameTable;
if (fTypesByName == NULL)
return B_NO_MEMORY;
return fTypes->Init();
error = fTypesByName->Init();
if (error != B_OK)
return error;
// create ID table
fTypesByID = new(std::nothrow) IDTable;
if (fTypesByID == NULL)
return B_NO_MEMORY;
error = fTypesByID->Init();
if (error != B_OK)
return error;
return B_OK;
}
Type*
GlobalTypeCache::GetType(const BString& name) const
{
TypeEntry* typeEntry = fTypes->Lookup(name);
TypeEntry* typeEntry = fTypesByName->Lookup(name);
return typeEntry != NULL ? typeEntry->type : NULL;
}
Type*
GlobalTypeCache::GetTypeByID(const BString& id) const
{
TypeEntry* typeEntry = fTypesByID->Lookup(id);
return typeEntry != NULL ? typeEntry->type : NULL;
}
status_t
GlobalTypeCache::AddType(const BString& name, Type* type)
GlobalTypeCache::AddType(Type* type)
{
TypeEntry* typeEntry = fTypes->Lookup(name);
if (typeEntry != NULL)
return B_BAD_VALUE;
const BString& id = type->ID();
const BString& name = type->Name();
typeEntry = new(std::nothrow) TypeEntry(name, type);
if (fTypesByID->Lookup(id) != NULL
|| (name.Length() > 0 && fTypesByID->Lookup(name) != NULL)) {
return B_BAD_VALUE;
}
TypeEntry* typeEntry = new(std::nothrow) TypeEntry(type);
if (typeEntry == NULL)
return B_NO_MEMORY;
fTypes->Insert(typeEntry);
fTypesByID->Insert(typeEntry);
if (name.Length() > 0)
fTypesByName->Insert(typeEntry);
return B_OK;
}
void
GlobalTypeCache::RemoveType(const BString& name)
GlobalTypeCache::RemoveType(Type* type)
{
if (TypeEntry* typeEntry = fTypes->Lookup(name)) {
fTypes->Remove(typeEntry);
delete typeEntry;
if (TypeEntry* typeEntry = fTypesByID->Lookup(type->ID())) {
if (typeEntry->type == type) {
fTypesByID->Remove(typeEntry);
if (type->Name().Length() > 0)
fTypesByName->Remove(typeEntry);
delete typeEntry;
}
}
}
@@ -141,10 +207,14 @@ GlobalTypeCache::RemoveTypes(image_id imageID)
{
AutoLocker<GlobalTypeCache> locker(this);
for (TypeTable::Iterator it = fTypes->GetIterator();
for (IDTable::Iterator it = fTypesByID->GetIterator();
TypeEntry* typeEntry = it.Next();) {
if (typeEntry->type->ImageID() == imageID) {
fTypes->RemoveUnchecked(typeEntry);
fTypesByID->RemoveUnchecked(typeEntry);
if (typeEntry->type->Name().Length() > 0)
fTypesByName->Remove(typeEntry);
delete typeEntry;
}
}
@@ -17,6 +17,12 @@ class BString;
class Type;
enum global_type_cache_scope {
GLOBAL_TYPE_CACHE_SCOPE_GLOBAL,
GLOBAL_TYPE_CACHE_SCOPE_COMPILATION_UNIT
};
class GlobalTypeCache : public Referenceable {
public:
GlobalTypeCache();
@@ -29,21 +35,25 @@ public:
// cache must be locked
Type* GetType(const BString& name) const;
status_t AddType(const BString& name, Type* type);
void RemoveType(const BString& name);
Type* GetTypeByID(const BString& id) const;
status_t AddType(Type* type);
void RemoveType(Type* type);
// cache locked by method
void RemoveTypes(image_id imageID);
private:
struct TypeEntry;
struct TypeEntryHashDefinition;
struct TypeEntryHashDefinitionByName;
struct TypeEntryHashDefinitionByID;
typedef BOpenHashTable<TypeEntryHashDefinition> TypeTable;
typedef BOpenHashTable<TypeEntryHashDefinitionByName> NameTable;
typedef BOpenHashTable<TypeEntryHashDefinitionByID> IDTable;
private:
BLocker fLock;
TypeTable* fTypes;
NameTable* fTypesByName;
IDTable* fTypesByID;
};
+11 -9
View File
@@ -23,10 +23,10 @@ DataMember::~DataMember()
}
// #pragma mark - EnumerationValue
// #pragma mark - EnumeratorValue
EnumerationValue::~EnumerationValue()
EnumeratorValue::~EnumeratorValue()
{
}
@@ -81,7 +81,7 @@ Type::~Type()
Type*
Type::ResolveRawType() const
Type::ResolveRawType(bool nextOneOnly) const
{
return const_cast<Type*>(this);
}
@@ -133,9 +133,10 @@ ModifiedType::Kind() const
Type*
ModifiedType::ResolveRawType() const
ModifiedType::ResolveRawType(bool nextOneOnly) const
{
return BaseType();
Type* baseType = BaseType();
return nextOneOnly ? baseType : baseType->ResolveRawType(true);
}
@@ -155,9 +156,10 @@ TypedefType::Kind() const
Type*
TypedefType::ResolveRawType() const
TypedefType::ResolveRawType(bool nextOneOnly) const
{
return BaseType();
Type* baseType = BaseType();
return nextOneOnly ? baseType : baseType->ResolveRawType(true);
}
@@ -191,11 +193,11 @@ EnumerationType::Kind() const
}
EnumerationValue*
EnumeratorValue*
EnumerationType::ValueFor(const BVariant& value) const
{
// TODO: Optimize?
for (int32 i = 0; EnumerationValue* enumValue = ValueAt(i); i++) {
for (int32 i = 0; EnumeratorValue* enumValue = ValueAt(i); i++) {
if (enumValue->Value() == value)
return enumValue;
}
+12 -9
View File
@@ -45,6 +45,7 @@ enum {
class ArrayIndexPath;
class BString;
class Type;
class ValueLocation;
@@ -66,9 +67,9 @@ public:
};
class EnumerationValue : public Referenceable {
class EnumeratorValue : public Referenceable {
public:
virtual ~EnumerationValue();
virtual ~EnumeratorValue();
virtual const char* Name() const = 0;
virtual BVariant Value() const = 0;
@@ -100,11 +101,13 @@ public:
virtual ~Type();
virtual image_id ImageID() const = 0;
virtual const char* Name() const = 0;
virtual const BString& ID() const = 0;
virtual const BString& Name() const = 0;
virtual type_kind Kind() const = 0;
virtual target_size_t ByteSize() const = 0;
virtual Type* ResolveRawType() const;
// strips modifiers and typedefs
virtual Type* ResolveRawType(bool nextOneOnly) const;
// strips modifiers and typedefs (only one,
// if requested)
virtual status_t ResolveObjectDataLocation(
const ValueLocation& objectLocation,
@@ -158,7 +161,7 @@ public:
virtual uint32 Modifiers() const = 0;
virtual Type* BaseType() const = 0;
virtual Type* ResolveRawType() const;
virtual Type* ResolveRawType(bool nextOneOnly) const;
};
@@ -169,7 +172,7 @@ public:
virtual type_kind Kind() const;
virtual Type* BaseType() const = 0;
virtual Type* ResolveRawType() const;
virtual Type* ResolveRawType(bool nextOneOnly) const;
};
@@ -194,8 +197,8 @@ public:
// may return NULL
virtual int32 CountValues() const = 0;
virtual EnumerationValue* ValueAt(int32 index) const = 0;
virtual EnumerationValue* ValueFor(const BVariant& value) const;
virtual EnumeratorValue* ValueAt(int32 index) const = 0;
virtual EnumeratorValue* ValueFor(const BVariant& value) const;
};
@@ -13,6 +13,7 @@
#include "Types.h"
class CpuState;
class FunctionInstance;
class Image;
class StackFrame;
@@ -21,6 +22,8 @@ class Thread;
class TypeComponentPath;
class UserBreakpoint;
class UserInterfaceListener;
class ValueNode;
class ValueNodeContainer;
class Variable;
@@ -59,10 +62,9 @@ public:
virtual void FunctionSourceCodeRequested(
FunctionInstance* function) = 0;
virtual void ImageDebugInfoRequested(Image* image) = 0;
virtual void StackFrameValueRequested(Thread* thread,
StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path) = 0;
// called with team locked
virtual void ValueNodeValueRequested(CpuState* cpuState,
ValueNodeContainer* container,
ValueNode* valueNode) = 0;
virtual void ThreadActionRequested(thread_id threadID,
uint32 action) = 0;
@@ -211,24 +211,6 @@ TeamWindow::MessageReceived(BMessage* message)
break;
}
case MSG_STACK_FRAME_VALUE_RETRIEVED:
{
void* _stackFrame;
void* _variable;
void* _path;
if (message->FindPointer("stackFrame", &_stackFrame) == B_OK
&& message->FindPointer("variable", &_variable) == B_OK
&& message->FindPointer("path", &_path) == B_OK) {
StackFrame* stackFrame = (StackFrame*)_stackFrame;
Variable* variable = (Variable*)_variable;
TypeComponentPath* path = (TypeComponentPath*)_path;
_HandleStackFrameValueRetrieved(stackFrame, variable, path);
path->ReleaseReference();
variable->ReleaseReference();
stackFrame->ReleaseReference();
}
}
case MSG_IMAGE_DEBUG_INFO_CHANGED:
{
int32 imageID;
@@ -339,10 +321,10 @@ TeamWindow::ClearBreakpointRequested(target_addr_t address)
void
TeamWindow::StackFrameValueRequested(::Thread* thread, StackFrame* stackFrame,
Variable* variable, TypeComponentPath* path)
TeamWindow::ValueNodeValueRequested(CpuState* cpuState,
ValueNodeContainer* container, ValueNode* valueNode)
{
fListener->StackFrameValueRequested(thread, stackFrame, variable, path);
fListener->ValueNodeValueRequested(cpuState, container, valueNode);
}
@@ -405,22 +387,6 @@ TeamWindow::FunctionSourceCodeChanged(Function* function)
}
void
TeamWindow::StackFrameValueRetrieved(StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path)
{
BMessage message(MSG_STACK_FRAME_VALUE_RETRIEVED);
if (message.AddPointer("stackFrame", stackFrame) == B_OK
&& message.AddPointer("variable", variable) == B_OK
&& message.AddPointer("path", path) == B_OK
&& PostMessage(&message) == B_OK) {
stackFrame->AcquireReference();
variable->AcquireReference();
path->AcquireReference();
}
}
void
TeamWindow::_Init()
{
@@ -906,17 +872,6 @@ TeamWindow::_HandleStackTraceChanged(thread_id threadID)
}
void
TeamWindow::_HandleStackFrameValueRetrieved(StackFrame* stackFrame,
Variable* variable, TypeComponentPath* path)
{
if (stackFrame != fActiveStackFrame)
return;
fVariablesView->StackFrameValueRetrieved(stackFrame, variable, path);
}
void
TeamWindow::_HandleImageDebugInfoChanged(image_id imageID)
{
@@ -89,9 +89,9 @@ private:
virtual void ClearBreakpointRequested(target_addr_t address);
// VariablesView::Listener
virtual void StackFrameValueRequested(::Thread* thread,
StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path);
virtual void ValueNodeValueRequested(CpuState* cpuState,
ValueNodeContainer* container,
ValueNode* valueNode);
// Team::Listener
virtual void ThreadStateChanged(
@@ -108,11 +108,6 @@ private:
// Function::Listener
virtual void FunctionSourceCodeChanged(Function* function);
// StackFrame::Listener
virtual void StackFrameValueRetrieved(StackFrame* stackFrame,
Variable* variable,
TypeComponentPath* path);
void _Init();
void _SetActiveThread(::Thread* thread);
@@ -130,9 +125,6 @@ private:
void _HandleThreadStateChanged(thread_id threadID);
void _HandleCpuStateChanged(thread_id threadID);
void _HandleStackTraceChanged(thread_id threadID);
void _HandleStackFrameValueRetrieved(
StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path);
void _HandleImageDebugInfoChanged(image_id imageID);
void _HandleSourceCodeChanged();
void _HandleUserBreakpointChanged(
File diff suppressed because it is too large Load Diff
@@ -11,9 +11,13 @@
#include "table/TreeTable.h"
class CpuState;
class SettingsMenu;
class StackFrame;
class Thread;
class TypeComponentPath;
class ValueNode;
class ValueNodeContainer;
class Variable;
class VariablesViewState;
class VariablesViewStateHistory;
@@ -32,41 +36,53 @@ public:
void SetStackFrame(Thread* thread,
StackFrame* stackFrame);
void StackFrameValueRetrieved(StackFrame* stackFrame,
Variable* variable,
TypeComponentPath* path);
virtual void MessageReceived(BMessage* message);
virtual void DetachedFromWindow();
private:
// TreeTableListener
virtual void TreeTableNodeExpandedChanged(TreeTable* table,
const TreeTablePath& path, bool expanded);
virtual void TreeTableCellMouseDown(TreeTable* table,
const TreeTablePath& path,
int32 columnIndex, BPoint screenWhere,
uint32 buttons);
private:
class ValueNode;
class ContainerListener;
class ModelNode;
class VariableValueColumn;
class VariableTableModel;
class ContextMenu;
class TableCellContextMenuTracker;
private:
void _Init();
void _RequestVariableValue(Variable* variable);
void _RequestNodeValue(ModelNode* node);
void _FinishContextMenu(bool force);
void _SaveViewState() const;
void _RestoreViewState();
status_t _AddViewStateDescendentNodeInfos(
VariablesViewState* viewState, void* parent,
TreeTablePath& path) const;
status_t _ApplyViewStateDescendentNodeInfos(
VariablesViewState* viewState, void* parent,
TreeTablePath& path);
// void _SaveViewState() const;
// void _RestoreViewState();
// status_t _AddViewStateDescendentNodeInfos(
// VariablesViewState* viewState, void* parent,
// TreeTablePath& path) const;
// status_t _ApplyViewStateDescendentNodeInfos(
// VariablesViewState* viewState, void* parent,
// TreeTablePath& path);
private:
Thread* fThread;
StackFrame* fStackFrame;
TreeTable* fVariableTable;
VariableTableModel* fVariableTableModel;
ContainerListener* fContainerListener;
VariablesViewState* fPreviousViewState;
VariablesViewStateHistory* fViewStateHistory;
TableCellContextMenuTracker* fTableCellContextMenuTracker;
Listener* fListener;
};
@@ -75,10 +91,9 @@ class VariablesView::Listener {
public:
virtual ~Listener();
virtual void StackFrameValueRequested(Thread* thread,
StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path) = 0;
// called with team locked
virtual void ValueNodeValueRequested(CpuState* cpuState,
ValueNodeContainer* container,
ValueNode* valueNode) = 0;
};
@@ -0,0 +1,41 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TableCellBoolRenderer.h"
#include "BoolValue.h"
#include "TableCellValueRendererUtils.h"
static inline const char*
bool_value_string(BoolValue* value)
{
return value->GetValue() ? "true" : "false";
}
void
TableCellBoolRenderer::RenderValue(Value* _value, BRect rect, BView* targetView)
{
BoolValue* value = dynamic_cast<BoolValue*>(_value);
if (value == NULL)
return;
TableCellValueRendererUtils::DrawString(targetView, rect,
bool_value_string(value), B_ALIGN_RIGHT, true);
}
float
TableCellBoolRenderer::PreferredValueWidth(Value* _value, BView* targetView)
{
BoolValue* value = dynamic_cast<BoolValue*>(_value);
if (value == NULL)
return 0;
return TableCellValueRendererUtils::PreferredStringWidth(targetView,
bool_value_string(value));
}
@@ -0,0 +1,23 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TABLE_CELL_BOOL_RENDERER_H
#define TABLE_CELL_BOOL_RENDERER_H
#include <Referenceable.h>
#include "TableCellValueRenderer.h"
class TableCellBoolRenderer : public TableCellValueRenderer {
public:
virtual void RenderValue(Value* value, BRect rect,
BView* targetView);
virtual float PreferredValueWidth(Value* value,
BView* targetView);
};
#endif // TABLE_CELL_BOOL_RENDERER_H
@@ -0,0 +1,61 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TableCellEnumerationRenderer.h"
#include "EnumerationValue.h"
#include "TableCellValueRendererUtils.h"
#include "Type.h"
TableCellEnumerationRenderer::TableCellEnumerationRenderer(Config* config)
:
TableCellIntegerRenderer(config)
{
}
void
TableCellEnumerationRenderer::RenderValue(Value* _value, BRect rect,
BView* targetView)
{
Config* config = GetConfig();
if (config != NULL && config->IntegerFormat() == INTEGER_FORMAT_DEFAULT) {
EnumerationValue* value = dynamic_cast<EnumerationValue*>(_value);
if (value == NULL)
return;
if (EnumeratorValue* enumValue
= value->GetType()->ValueFor(value->GetValue())) {
TableCellValueRendererUtils::DrawString(targetView, rect,
enumValue->Name(), B_ALIGN_RIGHT, true);
return;
}
}
TableCellIntegerRenderer::RenderValue(_value, rect, targetView);
}
float
TableCellEnumerationRenderer::PreferredValueWidth(Value* _value,
BView* targetView)
{
Config* config = GetConfig();
if (config != NULL && config->IntegerFormat() == INTEGER_FORMAT_DEFAULT) {
EnumerationValue* value = dynamic_cast<EnumerationValue*>(_value);
if (value == NULL)
return 0;
if (EnumeratorValue* enumValue
= value->GetType()->ValueFor(value->GetValue())) {
return TableCellValueRendererUtils::PreferredStringWidth(targetView,
enumValue->Name());
}
}
return TableCellIntegerRenderer::PreferredValueWidth(_value, targetView);
}
@@ -0,0 +1,25 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TABLE_CELL_ENUMERATION_RENDERER_H
#define TABLE_CELL_ENUMERATION_RENDERER_H
#include <Referenceable.h>
#include "TableCellIntegerRenderer.h"
class TableCellEnumerationRenderer : public TableCellIntegerRenderer {
public:
TableCellEnumerationRenderer(Config* config);
virtual void RenderValue(Value* value, BRect rect,
BView* targetView);
virtual float PreferredValueWidth(Value* value,
BView* targetView);
};
#endif // TABLE_CELL_ENUMERATION_RENDERER_H
@@ -0,0 +1,42 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TableCellFloatRenderer.h"
#include <stdio.h>
#include "FloatValue.h"
#include "TableCellValueRendererUtils.h"
void
TableCellFloatRenderer::RenderValue(Value* _value, BRect rect, BView* targetView)
{
FloatValue* value = dynamic_cast<FloatValue*>(_value);
if (value == NULL)
return;
char buffer[64];
snprintf(buffer, sizeof(buffer), "%g", value->GetValue());
TableCellValueRendererUtils::DrawString(targetView, rect, buffer,
B_ALIGN_RIGHT, true);
}
float
TableCellFloatRenderer::PreferredValueWidth(Value* _value, BView* targetView)
{
FloatValue* value = dynamic_cast<FloatValue*>(_value);
if (value == NULL)
return 0;
char buffer[64];
snprintf(buffer, sizeof(buffer), "%g", value->GetValue());
return TableCellValueRendererUtils::PreferredStringWidth(targetView,
buffer);
}
@@ -0,0 +1,23 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TABLE_CELL_FLOAT_RENDERER_H
#define TABLE_CELL_FLOAT_RENDERER_H
#include <Referenceable.h>
#include "TableCellValueRenderer.h"
class TableCellFloatRenderer : public TableCellValueRenderer {
public:
virtual void RenderValue(Value* value, BRect rect,
BView* targetView);
virtual float PreferredValueWidth(Value* value,
BView* targetView);
};
#endif // TABLE_CELL_FLOAT_RENDERER_H
@@ -0,0 +1,93 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TableCellIntegerRenderer.h"
#include <stdio.h>
#include <TypeConstants.h>
#include "TableCellValueRendererUtils.h"
#include "IntegerValue.h"
// #pragma mark - TableCellIntegerRenderer
TableCellIntegerRenderer::TableCellIntegerRenderer(Config* config)
:
fConfig(config)
{
if (fConfig != NULL)
fConfig->AcquireReference();
}
TableCellIntegerRenderer::~TableCellIntegerRenderer()
{
if (fConfig != NULL)
fConfig->ReleaseReference();
}
Settings*
TableCellIntegerRenderer::GetSettings() const
{
return fConfig != NULL ? fConfig->GetSettings() : NULL;
}
void
TableCellIntegerRenderer::RenderValue(Value* _value, BRect rect,
BView* targetView)
{
IntegerValue* value = dynamic_cast<IntegerValue*>(_value);
if (value == NULL)
return;
// format the value
integer_format format = fConfig != NULL
? fConfig->IntegerFormat() : INTEGER_FORMAT_DEFAULT;
char buffer[32];
if (!IntegerFormatter::FormatValue(value->GetValue(), format, buffer,
sizeof(buffer))) {
return;
}
// render
TableCellValueRendererUtils::DrawString(targetView, rect, buffer,
B_ALIGN_RIGHT, true);
}
float
TableCellIntegerRenderer::PreferredValueWidth(Value* _value, BView* targetView)
{
IntegerValue* value = dynamic_cast<IntegerValue*>(_value);
if (value == NULL)
return 0;
// format the value
integer_format format = fConfig != NULL
? fConfig->IntegerFormat() : INTEGER_FORMAT_DEFAULT;
char buffer[32];
if (!IntegerFormatter::FormatValue(value->GetValue(), format, buffer,
sizeof(buffer))) {
return 0;
}
// render
return TableCellValueRendererUtils::PreferredStringWidth(targetView,
buffer);
}
// #pragma mark - Config
TableCellIntegerRenderer::Config::~Config()
{
}
@@ -0,0 +1,47 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TABLE_CELL_INTEGER_RENDERER_H
#define TABLE_CELL_INTEGER_RENDERER_H
#include <Referenceable.h>
#include "IntegerFormatter.h"
#include "TableCellValueRenderer.h"
class TableCellIntegerRenderer : public TableCellValueRenderer {
public:
class Config;
public:
TableCellIntegerRenderer(Config* config);
virtual ~TableCellIntegerRenderer();
Config* GetConfig() const
{ return fConfig; }
virtual Settings* GetSettings() const;
virtual void RenderValue(Value* value, BRect rect,
BView* targetView);
virtual float PreferredValueWidth(Value* value,
BView* targetView);
private:
Config* fConfig;
};
class TableCellIntegerRenderer::Config : public BReferenceable {
public:
virtual ~Config();
virtual Settings* GetSettings() const = 0;
virtual integer_format IntegerFormat() const = 0;
};
#endif // TABLE_CELL_INTEGER_RENDERER_H
@@ -0,0 +1,37 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TableCellStringRenderer.h"
#include <String.h>
#include "TableCellValueRendererUtils.h"
#include "Value.h"
void
TableCellStringRenderer::RenderValue(Value* value, BRect rect,
BView* targetView)
{
BString string;
if (!value->ToString(string))
return;
TableCellValueRendererUtils::DrawString(targetView, rect, string,
B_ALIGN_LEFT, true);
}
float
TableCellStringRenderer::PreferredValueWidth(Value* value, BView* targetView)
{
BString string;
if (!value->ToString(string))
return 0;
return TableCellValueRendererUtils::PreferredStringWidth(targetView,
string);
}
@@ -0,0 +1,23 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TABLE_CELL_STRING_RENDERER_H
#define TABLE_CELL_STRING_RENDERER_H
#include "TableCellValueRenderer.h"
#include <Referenceable.h>
class TableCellStringRenderer : public TableCellValueRenderer {
public:
virtual void RenderValue(Value* value, BRect rect,
BView* targetView);
virtual float PreferredValueWidth(Value* value,
BView* targetView);
};
#endif // TABLE_CELL_STRING_RENDERER_H
@@ -0,0 +1,19 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TableCellValueRenderer.h"
TableCellValueRenderer::~TableCellValueRenderer()
{
}
Settings*
TableCellValueRenderer::GetSettings() const
{
return NULL;
}
@@ -0,0 +1,33 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TABLE_CELL_VALUE_RENDERER_H
#define TABLE_CELL_VALUE_RENDERER_H
#include <Rect.h>
#include <Referenceable.h>
class BView;
class Settings;
class Value;
class TableCellValueRenderer : public BReferenceable {
public:
virtual ~TableCellValueRenderer();
virtual Settings* GetSettings() const;
// returns NULL, if no settings
virtual void RenderValue(Value* value, BRect rect,
BView* targetView) = 0;
virtual float PreferredValueWidth(Value* value,
BView* targetView) = 0;
};
#endif // TABLE_CELL_VALUE_RENDERER_H
@@ -0,0 +1,68 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TableCellValueRendererUtils.h"
#include <Font.h>
#include <String.h>
#include <View.h>
static const float kTextMargin = 8;
/*static*/ void
TableCellValueRendererUtils::DrawString(BView* view, BRect rect,
const char* string, enum alignment alignment, bool truncate)
{
// get font height info
font_height fontHeight;
view->GetFontHeight(&fontHeight);
// truncate, if requested
BString truncatedString;
if (truncate) {
truncatedString = string;
view->TruncateString(&truncatedString, B_TRUNCATE_END,
rect.Width() - 2 * kTextMargin + 2);
string = truncatedString.String();
}
// compute horizontal position according to alignment
float x;
switch (alignment) {
default:
case B_ALIGN_LEFT:
x = rect.left + kTextMargin;
break;
case B_ALIGN_CENTER:
x = rect.left + (rect.Width() - view->StringWidth(string)) / 2;
break;
case B_ALIGN_RIGHT:
x = rect.right - kTextMargin - view->StringWidth(string);
break;
}
// compute vertical position (base line)
float y = rect.top
+ (rect.Height() - (fontHeight.ascent + fontHeight.descent
+ fontHeight.leading)) / 2
+ (fontHeight.ascent + fontHeight.descent) - 2;
// TODO: This is the computation BColumnListView (respectively
// BTitledColumn) is using, which I find somewhat weird.
view->DrawString(string, BPoint(x, y));
}
/*static*/ float
TableCellValueRendererUtils::PreferredStringWidth(BView* view,
const char* string)
{
return view->StringWidth(string) + 2 * kTextMargin;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TABLE_CELL_VALUE_RENDERER_UTILS_H
#define TABLE_CELL_VALUE_RENDERER_UTILS_H
#include <InterfaceDefs.h>
#include <Rect.h>
class BView;
class TableCellValueRendererUtils {
public:
static void DrawString(BView* view, BRect rect,
const char* string,
enum alignment alignment,
bool truncate = false);
static float PreferredStringWidth(BView* view,
const char* string);
};
#endif // TABLE_CELL_VALUE_RENDERER_UTILS_H
+12
View File
@@ -0,0 +1,12 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TypeHandler.h"
TypeHandler::~TypeHandler()
{
}
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TYPE_HANDLER_H
#define TYPE_HANDLER_H
#include <Referenceable.h>
class Type;
class ValueNode;
class ValueNodeChild;
class TypeHandler : public BReferenceable {
public:
virtual ~TypeHandler();
virtual float SupportsType(Type* type) = 0;
virtual status_t CreateValueNode(ValueNodeChild* nodeChild,
Type* type, ValueNode*& _node) = 0;
// returns a reference
};
#endif // TYPE_HANDLER_H
@@ -0,0 +1,214 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TypeHandlerRoster.h"
#include <new>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include "AddressValueNode.h"
#include "ArrayValueNode.h"
#include "CompoundValueNode.h"
#include "EnumerationValueNode.h"
#include "PointerToMemberValueNode.h"
#include "PrimitiveValueNode.h"
#include "Type.h"
#include "TypeHandler.h"
// #pragma mark - BasicTypeHandler
namespace {
template<typename TypeClass, typename NodeClass>
class BasicTypeHandler : public TypeHandler {
public:
virtual float SupportsType(Type* type)
{
return dynamic_cast<TypeClass*>(type) != NULL ? 0.5f : 0;
}
virtual status_t CreateValueNode(ValueNodeChild* nodeChild,
Type* type, ValueNode*& _node)
{
TypeClass* supportedType = dynamic_cast<TypeClass*>(type);
if (supportedType == NULL)
return B_BAD_VALUE;
ValueNode* node = new(std::nothrow) NodeClass(nodeChild, supportedType);
if (node == NULL)
return B_NO_MEMORY;
_node = node;
return B_OK;
}
};
} // unnamed namespace
// #pragma mark - TypeHandlerRoster
/*static*/ TypeHandlerRoster* TypeHandlerRoster::sDefaultInstance = NULL;
TypeHandlerRoster::TypeHandlerRoster()
:
fLock("type handler roster")
{
}
TypeHandlerRoster::~TypeHandlerRoster()
{
}
/*static*/ TypeHandlerRoster*
TypeHandlerRoster::Default()
{
return sDefaultInstance;
}
/*static*/ status_t
TypeHandlerRoster::CreateDefault()
{
if (sDefaultInstance != NULL)
return B_OK;
TypeHandlerRoster* roster = new(std::nothrow) TypeHandlerRoster;
if (roster == NULL)
return B_NO_MEMORY;
ObjectDeleter<TypeHandlerRoster> rosterDeleter(roster);
status_t error = roster->Init();
if (error != B_OK)
return error;
error = roster->RegisterDefaultHandlers();
if (error != B_OK)
return error;
sDefaultInstance = rosterDeleter.Detach();
return B_OK;
}
/*static*/ void
TypeHandlerRoster::DeleteDefault()
{
TypeHandlerRoster* roster = sDefaultInstance;
sDefaultInstance = NULL;
delete roster;
}
status_t
TypeHandlerRoster::Init()
{
return fLock.InitCheck();
}
status_t
TypeHandlerRoster::RegisterDefaultHandlers()
{
TypeHandler* handler;
Reference<TypeHandler> handlerReference;
#undef REGISTER_HANDLER
#define REGISTER_HANDLER(name) \
handler = new(std::nothrow) \
BasicTypeHandler<name##Type, name##ValueNode>(); \
handlerReference.SetTo(handler, true); \
if (handler == NULL || !RegisterHandler(handler)) \
return B_NO_MEMORY;
REGISTER_HANDLER(Address);
REGISTER_HANDLER(Array);
REGISTER_HANDLER(Compound);
REGISTER_HANDLER(Enumeration);
REGISTER_HANDLER(PointerToMember);
REGISTER_HANDLER(Primitive);
return B_OK;
}
status_t
TypeHandlerRoster::FindTypeHandler(ValueNodeChild* nodeChild, Type* type,
TypeHandler*& _handler)
{
// find the best-supporting handler
AutoLocker<BLocker> locker(fLock);
TypeHandler* bestHandler = NULL;
float bestSupport = 0;
for (int32 i = 0; TypeHandler* handler = fTypeHandlers.ItemAt(i); i++) {
float support = handler->SupportsType(type);
if (support > 0 && support > bestSupport) {
bestHandler = handler;
bestSupport = support;
}
}
if (bestHandler == NULL)
return B_ENTRY_NOT_FOUND;
bestHandler->AcquireReference();
_handler = bestHandler;
return B_OK;
}
status_t
TypeHandlerRoster::CreateValueNode(ValueNodeChild* nodeChild, Type* type,
ValueNode*& _node)
{
// find the best-supporting handler
while (true) {
TypeHandler* handler;
status_t error = FindTypeHandler(nodeChild, type, handler);
if (error == B_OK) {
// let the handler create the node
Reference<TypeHandler> handlerReference(handler, true);
return handler->CreateValueNode(nodeChild, type, _node);
}
// not found yet -- try to strip a modifier/typedef from the type
Type* nextType = type->ResolveRawType(true);
if (nextType == NULL || nextType == type)
return B_UNSUPPORTED;
type = nextType;
}
}
bool
TypeHandlerRoster::RegisterHandler(TypeHandler* handler)
{
if (!fTypeHandlers.AddItem(handler))
return false;
handler->AcquireReference();
return true;
}
void
TypeHandlerRoster::UnregisterHandler(TypeHandler* handler)
{
if (fTypeHandlers.RemoveItem(handler))
handler->RemoveReference();
}
@@ -0,0 +1,51 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TYPE_HANDLER_ROSTER_H
#define TYPE_HANDLER_ROSTER_H
#include <Locker.h>
#include <ObjectList.h>
class Type;
class TypeHandler;
class ValueNode;
class ValueNodeChild;
typedef BObjectList<TypeHandler> TypeHandlerList;
class TypeHandlerRoster {
public:
TypeHandlerRoster();
~TypeHandlerRoster();
static TypeHandlerRoster* Default();
static status_t CreateDefault();
static void DeleteDefault();
status_t Init();
status_t RegisterDefaultHandlers();
status_t FindTypeHandler(ValueNodeChild* nodeChild,
Type* type, TypeHandler*& _handler);
// returns a reference
status_t CreateValueNode(ValueNodeChild* nodeChild,
Type* type, ValueNode*& _node);
// returns a reference
bool RegisterHandler(TypeHandler* handler);
void UnregisterHandler(TypeHandler* handler);
private:
BLocker fLock;
TypeHandlerList fTypeHandlers;
static TypeHandlerRoster* sDefaultInstance;
};
#endif // TYPE_HANDLER_ROSTER_H
+12
View File
@@ -0,0 +1,12 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "Value.h"
Value::~Value()
{
}
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef VALUE_H
#define VALUE_H
#include <String.h>
#include <Variant.h>
class Value : public BReferenceable {
public:
virtual ~Value();
virtual bool ToString(BString& _string) const = 0;
virtual bool ToVariant(BVariant& _value) const = 0;
virtual bool operator==(const Value& other) const = 0;
inline bool operator!=(const Value& other) const
{ return !(*this == other); }
};
#endif // VALUE_H
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ValueHandler.h"
ValueHandler::~ValueHandler()
{
}
status_t
ValueHandler::CreateTableCellValueSettingsMenu(Value* value, Settings* settings,
SettingsMenu*& _menu)
{
_menu = NULL;
return B_OK;
}
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef VALUE_HANDLER_H
#define VALUE_HANDLER_H
#include <Referenceable.h>
class Settings;
class SettingsMenu;
class TableCellValueRenderer;
class Value;
class ValueFormatter;
class ValueHandler : public BReferenceable {
public:
virtual ~ValueHandler();
virtual float SupportsValue(Value* value) = 0;
virtual status_t GetValueFormatter(Value* value,
ValueFormatter*& _formatter) = 0;
// returns a reference
virtual status_t GetTableCellValueRenderer(Value* value,
TableCellValueRenderer*& _renderer) = 0;
// returns a reference
virtual status_t CreateTableCellValueSettingsMenu(Value* value,
Settings* settings, SettingsMenu*& _menu);
// may return NULL, otherwise a reference
};
#endif // VALUE_HANDLER_H
@@ -0,0 +1,188 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ValueHandlerRoster.h"
#include <new>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include "AddressValueHandler.h"
#include "BoolValueHandler.h"
#include "EnumerationValueHandler.h"
#include "FloatValueHandler.h"
#include "Value.h"
/*static*/ ValueHandlerRoster* ValueHandlerRoster::sDefaultInstance = NULL;
ValueHandlerRoster::ValueHandlerRoster()
:
fLock("value handler roster")
{
}
ValueHandlerRoster::~ValueHandlerRoster()
{
}
/*static*/ ValueHandlerRoster*
ValueHandlerRoster::Default()
{
return sDefaultInstance;
}
/*static*/ status_t
ValueHandlerRoster::CreateDefault()
{
if (sDefaultInstance != NULL)
return B_OK;
ValueHandlerRoster* roster = new(std::nothrow) ValueHandlerRoster;
if (roster == NULL)
return B_NO_MEMORY;
ObjectDeleter<ValueHandlerRoster> rosterDeleter(roster);
status_t error = roster->Init();
if (error != B_OK)
return error;
error = roster->RegisterDefaultHandlers();
if (error != B_OK)
return error;
sDefaultInstance = rosterDeleter.Detach();
return B_OK;
}
/*static*/ void
ValueHandlerRoster::DeleteDefault()
{
ValueHandlerRoster* roster = sDefaultInstance;
sDefaultInstance = NULL;
delete roster;
}
status_t
ValueHandlerRoster::Init()
{
return fLock.InitCheck();
}
status_t
ValueHandlerRoster::RegisterDefaultHandlers()
{
status_t error;
#undef REGISTER_HANDLER
#define REGISTER_HANDLER(name) \
{ \
name##ValueHandler* handler \
= new(std::nothrow) name##ValueHandler; \
if (handler == NULL) \
return B_NO_MEMORY; \
BReference<name##ValueHandler> handlerReference(handler, true); \
\
error = handler->Init(); \
if (error != B_OK) \
return error; \
\
if (!RegisterHandler(handler)) \
return B_NO_MEMORY; \
}
REGISTER_HANDLER(Address)
REGISTER_HANDLER(Bool)
REGISTER_HANDLER(Enumeration)
REGISTER_HANDLER(Float)
REGISTER_HANDLER(Integer)
return B_OK;
}
status_t
ValueHandlerRoster::FindValueHandler(Value* value, ValueHandler*& _handler)
{
// find the best-supporting handler
AutoLocker<BLocker> locker(fLock);
ValueHandler* bestHandler = NULL;
float bestSupport = 0;
for (int32 i = 0; ValueHandler* handler = fValueHandlers.ItemAt(i); i++) {
float support = handler->SupportsValue(value);
if (support > 0 && support > bestSupport) {
bestHandler = handler;
bestSupport = support;
}
}
if (bestHandler == NULL)
return B_ENTRY_NOT_FOUND;
bestHandler->AcquireReference();
_handler = bestHandler;
return B_OK;
}
status_t
ValueHandlerRoster::GetValueFormatter(Value* value,
ValueFormatter*& _formatter)
{
// get the best supporting value handler
ValueHandler* handler;
status_t error = FindValueHandler(value, handler);
if (error != B_OK)
return error;
BReference<ValueHandler> handlerReference(handler, true);
// create the formatter
return handler->GetValueFormatter(value, _formatter);
}
status_t
ValueHandlerRoster::GetTableCellValueRenderer(Value* value,
TableCellValueRenderer*& _renderer)
{
// get the best supporting value handler
ValueHandler* handler;
status_t error = FindValueHandler(value, handler);
if (error != B_OK)
return error;
BReference<ValueHandler> handlerReference(handler, true);
// create the renderer
return handler->GetTableCellValueRenderer(value, _renderer);
}
bool
ValueHandlerRoster::RegisterHandler(ValueHandler* handler)
{
if (!fValueHandlers.AddItem(handler))
return false;
handler->AcquireReference();
return true;
}
void
ValueHandlerRoster::UnregisterHandler(ValueHandler* handler)
{
if (fValueHandlers.RemoveItem(handler))
handler->RemoveReference();
}
@@ -0,0 +1,54 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef VALUE_HANDLER_ROSTER_H
#define VALUE_HANDLER_ROSTER_H
#include <Locker.h>
#include <ObjectList.h>
class TableCellValueRenderer;
class Value;
class ValueFormatter;
class ValueHandler;
typedef BObjectList<ValueHandler> ValueHandlerList;
class ValueHandlerRoster {
public:
ValueHandlerRoster();
~ValueHandlerRoster();
static ValueHandlerRoster* Default();
static status_t CreateDefault();
static void DeleteDefault();
status_t Init();
status_t RegisterDefaultHandlers();
status_t FindValueHandler(Value* value,
ValueHandler*& _handler);
// returns a reference
status_t GetValueFormatter(Value* value,
ValueFormatter*& _formatter);
// returns a reference
status_t GetTableCellValueRenderer(Value* value,
TableCellValueRenderer*& _renderer);
// returns a reference
bool RegisterHandler(ValueHandler* handler);
void UnregisterHandler(ValueHandler* handler);
private:
BLocker fLock;
ValueHandlerList fValueHandlers;
static ValueHandlerRoster* sDefaultInstance;
};
#endif // VALUE_HANDLER_ROSTER_H
+187
View File
@@ -0,0 +1,187 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ValueLoader.h"
#include "Architecture.h"
#include "BitBuffer.h"
#include "CpuState.h"
#include "Register.h"
#include "TeamMemory.h"
#include "Tracing.h"
#include "ValueLocation.h"
ValueLoader::ValueLoader(Architecture* architecture, TeamMemory* teamMemory,
CpuState* cpuState)
:
fArchitecture(architecture),
fTeamMemory(teamMemory),
fCpuState(cpuState)
{
// TODO: TeamMemory is not BReferenceable!
fArchitecture->AcquireReference();
if (fCpuState != NULL)
fCpuState->AcquireReference();
}
ValueLoader::~ValueLoader()
{
fArchitecture->ReleaseReference();
if (fCpuState != NULL)
fCpuState->ReleaseReference();
}
status_t
ValueLoader::LoadValue(ValueLocation* location, type_code valueType,
bool shortValueIsFine, BVariant& _value)
{
static const size_t kMaxPieceSize = 16;
uint64 totalBitSize = 0;
int32 count = location->CountPieces();
for (int32 i = 0; i < count; i++) {
ValuePieceLocation piece = location->PieceAt(i);
switch (piece.type) {
case VALUE_PIECE_LOCATION_INVALID:
case VALUE_PIECE_LOCATION_UNKNOWN:
return B_ENTRY_NOT_FOUND;
case VALUE_PIECE_LOCATION_MEMORY:
case VALUE_PIECE_LOCATION_REGISTER:
break;
}
if (piece.size > kMaxPieceSize) {
TRACE_LOCALS(" -> overly long piece size (%llu bytes)\n",
piece.size);
return B_UNSUPPORTED;
}
totalBitSize += piece.bitSize;
}
TRACE_LOCALS(" -> totalBitSize: %llu\n", totalBitSize);
if (totalBitSize == 0) {
TRACE_LOCALS(" -> no size\n");
return B_ENTRY_NOT_FOUND;
}
if (totalBitSize > 64) {
TRACE_LOCALS(" -> longer than 64 bits: unsupported\n");
return B_UNSUPPORTED;
}
uint64 valueBitSize = BVariant::SizeOfType(valueType) * 8;
if (!shortValueIsFine && totalBitSize < valueBitSize) {
TRACE_LOCALS(" -> too short for value type (%llu vs. %llu bits)\n",
totalBitSize, valueBitSize);
return B_BAD_VALUE;
}
// Load the data. Since the BitBuffer class we're using only supports big
// endian bit semantics, we convert all data to big endian before pushing
// them to the buffer. For later conversion to BVariant we need to make sure
// the final buffer has the size of the value type, so we pad the most
// significant bits with zeros.
BitBuffer valueBuffer;
if (totalBitSize < valueBitSize)
valueBuffer.AddZeroBits(valueBitSize - totalBitSize);
bool bigEndian = fArchitecture->IsBigEndian();
const Register* registers = fArchitecture->Registers();
for (int32 i = 0; i < count; i++) {
ValuePieceLocation piece = location->PieceAt(
bigEndian ? i : count - i - 1);
uint32 bytesToRead = piece.size;
uint32 bitSize = piece.bitSize;
uint8 bitOffset = piece.bitOffset;
switch (piece.type) {
case VALUE_PIECE_LOCATION_INVALID:
case VALUE_PIECE_LOCATION_UNKNOWN:
return B_ENTRY_NOT_FOUND;
case VALUE_PIECE_LOCATION_MEMORY:
{
target_addr_t address = piece.address;
TRACE_LOCALS(" piece %ld: memory address: %#llx, bits: %lu\n",
i, address, bitSize);
uint8 pieceBuffer[kMaxPieceSize];
ssize_t bytesRead = fTeamMemory->ReadMemory(address,
pieceBuffer, bytesToRead);
if (bytesRead < 0)
return bytesRead;
if ((uint32)bytesRead != bytesToRead)
return B_BAD_ADDRESS;
TRACE_LOCALS_ONLY(
TRACE_LOCALS(" -> read: ");
for (ssize_t k = 0; k < bytesRead; k++)
TRACE_LOCALS("%02x", pieceBuffer[k]);
TRACE_LOCALS("\n");
)
// convert to big endian
if (!bigEndian) {
for (int32 k = bytesRead / 2 - 1; k >= 0; k--) {
std::swap(pieceBuffer[k],
pieceBuffer[bytesRead - k - 1]);
}
}
valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset);
break;
}
case VALUE_PIECE_LOCATION_REGISTER:
{
TRACE_LOCALS(" piece %ld: register: %lu, bits: %lu\n", i,
piece.reg, bitSize);
if (fCpuState == NULL) {
WARNING("ValueLoader::LoadValue(): register piece, but no "
"CpuState\n");
return B_UNSUPPORTED;
}
BVariant registerValue;
if (!fCpuState->GetRegisterValue(registers + piece.reg,
registerValue)) {
return B_ENTRY_NOT_FOUND;
}
if (registerValue.Size() < bytesToRead)
return B_ENTRY_NOT_FOUND;
if (!bigEndian)
registerValue.SwapEndianess();
valueBuffer.AddBits(registerValue.Bytes(), bitSize, bitOffset);
break;
}
}
}
// If we don't have enough bits in the buffer apparently adding some failed.
if (valueBuffer.BitSize() < valueBitSize)
return B_NO_MEMORY;
// convert the bits into something we can work with
BVariant value;
status_t error = value.SetToTypedData(valueBuffer.Bytes(), valueType);
if (error != B_OK) {
TRACE_LOCALS(" -> failed to set typed data: %s\n", strerror(error));
return error;
}
// convert to host endianess
#if B_HOST_IS_LENDIAN
value.SwapEndianess();
#endif
_value = value;
return B_OK;
}
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef VALUE_LOADER_H
#define VALUE_LOADER_H
#include <String.h>
#include <Variant.h>
class Architecture;
class CpuState;
class TeamMemory;
class ValueLocation;
class ValueLoader {
public:
ValueLoader(Architecture* architecture,
TeamMemory* teamMemory, CpuState* cpuState);
// cpuState can be NULL
~ValueLoader();
Architecture* GetArchitecture() const
{ return fArchitecture; }
status_t LoadValue(ValueLocation* location,
type_code valueType, bool shortValueIsFine,
BVariant& _value);
private:
Architecture* fArchitecture;
TeamMemory* fTeamMemory;
CpuState* fCpuState;
};
#endif // VALUE_LOADER_H
+229
View File
@@ -0,0 +1,229 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ValueNode.h"
#include "Value.h"
#include "ValueLocation.h"
#include "ValueNodeContainer.h"
// #pragma mark - ValueNode
ValueNode::ValueNode(ValueNodeChild* nodeChild)
:
fContainer(NULL),
fNodeChild(nodeChild),
fLocation(NULL),
fValue(NULL),
fLocationResolutionState(VALUE_NODE_UNRESOLVED),
fChildrenCreated(false)
{
fNodeChild->AcquireReference();
}
ValueNode::~ValueNode()
{
SetLocationAndValue(NULL, NULL, VALUE_NODE_UNRESOLVED);
SetContainer(NULL);
fNodeChild->ReleaseReference();
}
const BString&
ValueNode::Name() const
{
return fNodeChild->Name();
}
void
ValueNode::SetContainer(ValueNodeContainer* container)
{
if (container == fContainer)
return;
if (fContainer != NULL)
fContainer->ReleaseReference();
fContainer = container;
if (fContainer != NULL)
fContainer->AcquireReference();
// propagate to children
int32 childCount = CountChildren();
for (int32 i = 0; i < childCount; i++)
ChildAt(i)->SetContainer(fContainer);
}
void
ValueNode::SetLocationAndValue(ValueLocation* location, Value* value,
status_t resolutionState)
{
if (fLocation != location) {
if (fLocation != NULL)
fLocation->ReleaseReference();
fLocation = location;
if (fLocation != NULL)
fLocation->AcquireReference();
}
if (fValue != value) {
if (fValue != NULL)
fValue->ReleaseReference();
fValue = value;
if (fValue != NULL)
fValue->AcquireReference();
}
fLocationResolutionState = resolutionState;
// notify listeners
if (fContainer != NULL)
fContainer->NotifyValueNodeValueChanged(this);
}
// #pragma mark - ValueNodeChild
ValueNodeChild::ValueNodeChild()
:
fContainer(NULL),
fNode(NULL),
fLocation(NULL),
fLocationResolutionState(VALUE_NODE_UNRESOLVED)
{
}
ValueNodeChild::~ValueNodeChild()
{
SetLocation(NULL, VALUE_NODE_UNRESOLVED);
SetNode(NULL);
SetContainer(NULL);
}
bool
ValueNodeChild::IsInternal() const
{
return false;
}
status_t
ValueNodeChild::CreateInternalNode(ValueNode*& _node)
{
return B_BAD_VALUE;
}
void
ValueNodeChild::SetContainer(ValueNodeContainer* container)
{
if (container == fContainer)
return;
if (fContainer != NULL)
fContainer->ReleaseReference();
fContainer = container;
if (fContainer != NULL)
fContainer->AcquireReference();
// propagate to node
if (fNode != NULL)
fNode->SetContainer(fContainer);
}
void
ValueNodeChild::SetNode(ValueNode* node)
{
if (node == fNode)
return;
ValueNode* oldNode = fNode;
Reference<ValueNode> oldNodeReference(oldNode, true);
if (fNode != NULL)
fNode->SetContainer(NULL);
fNode = node;
if (fNode != NULL) {
fNode->AcquireReference();
fNode->SetContainer(fContainer);
}
if (fContainer != NULL)
fContainer->NotifyValueNodeChanged(this, oldNode, fNode);
}
ValueLocation*
ValueNodeChild::Location() const
{
return fLocation;
}
void
ValueNodeChild::SetLocation(ValueLocation* location, status_t resolutionState)
{
if (fLocation != location) {
if (fLocation != NULL)
fLocation->ReleaseReference();
fLocation = location;
if (fLocation != NULL)
fLocation->AcquireReference();
}
fLocationResolutionState = resolutionState;
}
// #pragma mark - ChildlessValueNode
ChildlessValueNode::ChildlessValueNode(ValueNodeChild* nodeChild)
:
ValueNode(nodeChild)
{
fChildrenCreated = true;
}
status_t
ChildlessValueNode::CreateChildren()
{
return B_OK;
}
int32
ChildlessValueNode::CountChildren() const
{
return 0;
}
ValueNodeChild*
ChildlessValueNode::ChildAt(int32 index) const
{
return NULL;
}
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef VALUE_NODE_H
#define VALUE_NODE_H
#include <String.h>
#include <Referenceable.h>
class Type;
class Value;
class ValueLoader;
class ValueLocation;
class ValueNodeChild;
class ValueNodeContainer;
enum {
VALUE_NODE_UNRESOLVED = 1
};
class ValueNode : public BReferenceable {
public:
ValueNode(ValueNodeChild* nodeChild);
virtual ~ValueNode();
ValueNodeChild* NodeChild() const { return fNodeChild; }
virtual const BString& Name() const;
virtual Type* GetType() const = 0;
virtual status_t ResolvedLocationAndValue(
ValueLoader* valueLoader,
ValueLocation*& _location,
Value*& _value) = 0;
// returns references, a NULL value can be
// returned
// locking required
ValueNodeContainer* Container() const
{ return fContainer; }
void SetContainer(ValueNodeContainer* container);
bool ChildrenCreated() const
{ return fChildrenCreated; }
virtual status_t CreateChildren() = 0;
virtual int32 CountChildren() const = 0;
virtual ValueNodeChild* ChildAt(int32 index) const = 0;
status_t LocationAndValueResolutionState() const
{ return fLocationResolutionState; }
void SetLocationAndValue(ValueLocation* location,
Value* value, status_t resolutionState);
ValueLocation* Location() const { return fLocation; }
Value* GetValue() const { return fValue; }
// immutable after SetLocationAndValue()
protected:
ValueNodeContainer* fContainer;
ValueNodeChild* fNodeChild;
ValueLocation* fLocation;
Value* fValue;
status_t fLocationResolutionState;
bool fChildrenCreated;
};
class ValueNodeChild : public BReferenceable {
public:
ValueNodeChild();
virtual ~ValueNodeChild();
virtual const BString& Name() const = 0;
virtual Type* GetType() const = 0;
virtual ValueNode* Parent() const = 0;
virtual bool IsInternal() const;
virtual status_t CreateInternalNode(ValueNode*& _node);
virtual status_t ResolveLocation(ValueLoader* valueLoader,
ValueLocation*& _location) = 0;
// returns a reference
// locking required
ValueNodeContainer* Container() const
{ return fContainer; }
void SetContainer(ValueNodeContainer* container);
ValueNode* Node() const { return fNode; }
void SetNode(ValueNode* node);
status_t LocationResolutionState() const
{ return fLocationResolutionState; }
ValueLocation* Location() const;
// immutable after SetLocation()
void SetLocation(ValueLocation* location,
status_t resolutionState);
protected:
ValueNodeContainer* fContainer;
ValueNode* fNode;
ValueLocation* fLocation;
status_t fLocationResolutionState;
};
class ChildlessValueNode : public ValueNode {
public:
ChildlessValueNode(ValueNodeChild* nodeChild);
virtual status_t CreateChildren();
virtual int32 CountChildren() const;
virtual ValueNodeChild* ChildAt(int32 index) const;
};
#endif // VALUE_NODE_H
@@ -0,0 +1,166 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ValueNodeContainer.h"
#include <AutoLocker.h>
#include "ValueNode.h"
// #pragma mark - ValueNodeContainer
ValueNodeContainer::ValueNodeContainer()
:
fLock("value node container")
{
}
ValueNodeContainer::~ValueNodeContainer()
{
RemoveAllChildren();
}
status_t
ValueNodeContainer::Init()
{
return fLock.InitCheck();
}
int32
ValueNodeContainer::CountChildren() const
{
return fChildren.CountItems();
}
ValueNodeChild*
ValueNodeContainer::ChildAt(int32 index) const
{
return fChildren.ItemAt(index);
}
bool
ValueNodeContainer::AddChild(ValueNodeChild* child)
{
AutoLocker<ValueNodeContainer> locker(this);
if (!fChildren.AddItem(child))
return false;
child->AcquireReference();
child->SetContainer(this);
return true;
}
void
ValueNodeContainer::RemoveChild(ValueNodeChild* child)
{
if (child->Container() != this || !fChildren.RemoveItem(child))
return;
child->SetContainer(NULL);
child->RemoveReference();
}
void
ValueNodeContainer::RemoveAllChildren()
{
for (int32 i = 0; ValueNodeChild* child = ChildAt(i); i++) {
child->SetContainer(NULL);
child->RemoveReference();
}
fChildren.MakeEmpty();
}
bool
ValueNodeContainer::AddListener(Listener* listener)
{
return fListeners.AddItem(listener);
}
void
ValueNodeContainer::RemoveListener(Listener* listener)
{
fListeners.RemoveItem(listener);
}
void
ValueNodeContainer::NotifyValueNodeChanged(ValueNodeChild* nodeChild,
ValueNode* oldNode, ValueNode* newNode)
{
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
fListeners.ItemAt(i)->ValueNodeChanged(nodeChild, oldNode, newNode);
}
void
ValueNodeContainer::NotifyValueNodeChildrenCreated(ValueNode* node)
{
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
fListeners.ItemAt(i)->ValueNodeChildrenCreated(node);
}
void
ValueNodeContainer::NotifyValueNodeChildrenDeleted(ValueNode* node)
{
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
fListeners.ItemAt(i)->ValueNodeChildrenDeleted(node);
}
void
ValueNodeContainer::NotifyValueNodeValueChanged(ValueNode* node)
{
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
fListeners.ItemAt(i)->ValueNodeValueChanged(node);
}
// #pragma mark - ValueNodeContainer
ValueNodeContainer::Listener::~Listener()
{
}
void
ValueNodeContainer::Listener::ValueNodeChanged(ValueNodeChild* nodeChild,
ValueNode* oldNode, ValueNode* newNode)
{
}
void
ValueNodeContainer::Listener::ValueNodeChildrenCreated(ValueNode* node)
{
}
void
ValueNodeContainer::Listener::ValueNodeChildrenDeleted(ValueNode* node)
{
}
void
ValueNodeContainer::Listener::ValueNodeValueChanged(ValueNode* node)
{
}
@@ -0,0 +1,75 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef VALUE_NODE_CONTAINER_H
#define VALUE_NODE_CONTAINER_H
#include <Locker.h>
#include <ObjectList.h>
#include <Referenceable.h>
class ValueNode;
class ValueNodeChild;
class ValueNodeContainer : public BReferenceable {
public:
class Listener;
public:
ValueNodeContainer();
virtual ~ValueNodeContainer();
status_t Init();
inline bool Lock() { return fLock.Lock(); }
inline void Unlock() { fLock.Unlock(); }
int32 CountChildren() const;
ValueNodeChild* ChildAt(int32 index) const;
bool AddChild(ValueNodeChild* child);
void RemoveChild(ValueNodeChild* child);
void RemoveAllChildren();
bool AddListener(Listener* listener);
void RemoveListener(Listener* listener);
// container must be locked
void NotifyValueNodeChanged(
ValueNodeChild* nodeChild,
ValueNode* oldNode, ValueNode* newNode);
void NotifyValueNodeChildrenCreated(ValueNode* node);
void NotifyValueNodeChildrenDeleted(ValueNode* node);
void NotifyValueNodeValueChanged(ValueNode* node);
private:
typedef BObjectList<ValueNodeChild> NodeChildList;
typedef BObjectList<Listener> ListenerList;
private:
BLocker fLock;
NodeChildList fChildren;
ListenerList fListeners;
};
class ValueNodeContainer::Listener {
public:
virtual ~Listener();
// container is locked
virtual void ValueNodeChanged(ValueNodeChild* nodeChild,
ValueNode* oldNode, ValueNode* newNode);
virtual void ValueNodeChildrenCreated(ValueNode* node);
virtual void ValueNodeChildrenDeleted(ValueNode* node);
virtual void ValueNodeValueChanged(ValueNode* node);
};
#endif // VALUE_NODE_CONTAINER_H
@@ -0,0 +1,23 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "AddressValueHandler.h"
#include "AddressValue.h"
float
AddressValueHandler::SupportsValue(Value* value)
{
return dynamic_cast<AddressValue*>(value) ? 0.8f : 0;
}
integer_format
AddressValueHandler::DefaultIntegerFormat(IntegerValue* value)
{
return INTEGER_FORMAT_HEX_DEFAULT;
}
@@ -0,0 +1,21 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef ADDRESS_VALUE_HANDLER_H
#define ADDRESS_VALUE_HANDLER_H
#include "IntegerValueHandler.h"
class AddressValueHandler : public IntegerValueHandler {
public:
virtual float SupportsValue(Value* value);
protected:
virtual integer_format DefaultIntegerFormat(IntegerValue* value);
};
#endif // ADDRESS_VALUE_HANDLER_H
@@ -0,0 +1,62 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "BoolValueHandler.h"
#include <new>
#include "BoolValue.h"
#include "TableCellBoolRenderer.h"
BoolValueHandler::BoolValueHandler()
{
}
BoolValueHandler::~BoolValueHandler()
{
}
status_t
BoolValueHandler::Init()
{
return B_OK;
}
float
BoolValueHandler::SupportsValue(Value* value)
{
return dynamic_cast<BoolValue*>(value) != NULL ? 0.5f : 0;
}
status_t
BoolValueHandler::GetValueFormatter(Value* value,
ValueFormatter*& _formatter)
{
// TODO:...
return B_UNSUPPORTED;
}
status_t
BoolValueHandler::GetTableCellValueRenderer(Value* value,
TableCellValueRenderer*& _renderer)
{
if (dynamic_cast<BoolValue*>(value) == NULL)
return B_BAD_VALUE;
// create the renderer
TableCellValueRenderer* renderer = new(std::nothrow) TableCellBoolRenderer;
if (renderer == NULL)
return B_NO_MEMORY;
_renderer = renderer;
return B_OK;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef BOOL_VALUE_HANDLER_H
#define BOOL_VALUE_HANDLER_H
#include "ValueHandler.h"
class BoolValueHandler : public ValueHandler {
public:
BoolValueHandler();
~BoolValueHandler();
status_t Init();
virtual float SupportsValue(Value* value);
virtual status_t GetValueFormatter(Value* value,
ValueFormatter*& _formatter);
virtual status_t GetTableCellValueRenderer(Value* value,
TableCellValueRenderer*& _renderer);
};
#endif // BOOL_VALUE_HANDLER_H
@@ -0,0 +1,88 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "EnumerationValueHandler.h"
#include <new>
#include "EnumerationValue.h"
#include "TableCellEnumerationRenderer.h"
#include "Type.h"
EnumerationValueHandler::EnumerationValueHandler()
{
}
EnumerationValueHandler::~EnumerationValueHandler()
{
}
status_t
EnumerationValueHandler::Init()
{
return B_OK;
}
float
EnumerationValueHandler::SupportsValue(Value* value)
{
return dynamic_cast<EnumerationValue*>(value) != NULL ? 0.7f : 0;
}
integer_format
EnumerationValueHandler::DefaultIntegerFormat(IntegerValue* _value)
{
EnumerationValue* value = dynamic_cast<EnumerationValue*>(_value);
if (value != NULL && value->GetType()->ValueFor(value->GetValue()) != NULL)
return INTEGER_FORMAT_DEFAULT;
return IntegerValueHandler::DefaultIntegerFormat(_value);
}
status_t
EnumerationValueHandler::AddIntegerFormatSettingOptions(IntegerValue* _value,
OptionsSettingImpl* setting)
{
EnumerationValue* value = dynamic_cast<EnumerationValue*>(_value);
if (value != NULL
&& value->GetType()->ValueFor(value->GetValue()) != NULL) {
status_t error = AddIntegerFormatOption(setting, "name", "Enum Name",
INTEGER_FORMAT_DEFAULT);
if (error != B_OK)
return error;
}
return IntegerValueHandler::AddIntegerFormatSettingOptions(_value, setting);
}
status_t
EnumerationValueHandler::CreateTableCellValueRenderer(IntegerValue* _value,
TableCellIntegerRenderer::Config* config,
TableCellValueRenderer*& _renderer)
{
EnumerationValue* value = dynamic_cast<EnumerationValue*>(_value);
if (value != NULL
&& value->GetType()->ValueFor(value->GetValue()) != NULL) {
TableCellValueRenderer* renderer
= new(std::nothrow) TableCellEnumerationRenderer(config);
if (renderer == NULL)
return B_NO_MEMORY;
_renderer = renderer;
return B_OK;
}
return IntegerValueHandler::CreateTableCellValueRenderer(_value, config,
_renderer);
}
@@ -0,0 +1,33 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef ENUMERATION_VALUE_HANDLER_H
#define ENUMERATION_VALUE_HANDLER_H
#include "IntegerValueHandler.h"
class EnumerationValueHandler : public IntegerValueHandler {
public:
EnumerationValueHandler();
~EnumerationValueHandler();
status_t Init();
virtual float SupportsValue(Value* value);
protected:
virtual integer_format DefaultIntegerFormat(IntegerValue* value);
virtual status_t AddIntegerFormatSettingOptions(
IntegerValue* value,
OptionsSettingImpl* setting);
virtual status_t CreateTableCellValueRenderer(
IntegerValue* value,
TableCellIntegerRenderer::Config* config,
TableCellValueRenderer*& _renderer);
};
#endif // ENUMERATION_VALUE_HANDLER_H
@@ -0,0 +1,62 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "FloatValueHandler.h"
#include <new>
#include "FloatValue.h"
#include "TableCellFloatRenderer.h"
FloatValueHandler::FloatValueHandler()
{
}
FloatValueHandler::~FloatValueHandler()
{
}
status_t
FloatValueHandler::Init()
{
return B_OK;
}
float
FloatValueHandler::SupportsValue(Value* value)
{
return dynamic_cast<FloatValue*>(value) != NULL ? 0.5f : 0;
}
status_t
FloatValueHandler::GetValueFormatter(Value* value,
ValueFormatter*& _formatter)
{
// TODO:...
return B_UNSUPPORTED;
}
status_t
FloatValueHandler::GetTableCellValueRenderer(Value* value,
TableCellValueRenderer*& _renderer)
{
if (dynamic_cast<FloatValue*>(value) == NULL)
return B_BAD_VALUE;
// create the renderer
TableCellValueRenderer* renderer = new(std::nothrow) TableCellFloatRenderer;
if (renderer == NULL)
return B_NO_MEMORY;
_renderer = renderer;
return B_OK;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef FLOAT_VALUE_HANDLER_H
#define FLOAT_VALUE_HANDLER_H
#include "ValueHandler.h"
class FloatValueHandler : public ValueHandler {
public:
FloatValueHandler();
~FloatValueHandler();
status_t Init();
virtual float SupportsValue(Value* value);
virtual status_t GetValueFormatter(Value* value,
ValueFormatter*& _formatter);
virtual status_t GetTableCellValueRenderer(Value* value,
TableCellValueRenderer*& _renderer);
};
#endif // FLOAT_VALUE_HANDLER_H
@@ -0,0 +1,306 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "IntegerValueHandler.h"
#include <new>
#include <AutoDeleter.h>
#include "IntegerValue.h"
#include "Setting.h"
#include "Settings.h"
#include "SettingsDescription.h"
#include "SettingsMenu.h"
#include "TableCellIntegerRenderer.h"
static const char* const kFormatSettingID = "format";
// #pragma mark - FormatOption
class IntegerValueHandler::FormatOption : public SettingsOption {
public:
FormatOption(const char* id, const char* name, integer_format format)
:
fID(id),
fName(name),
fFormat(format)
{
}
virtual const char* ID() const
{
return fID;
}
virtual const char* Name() const
{
return fName;
}
integer_format Format() const
{
return fFormat;
}
private:
const char* fID;
const char* fName;
integer_format fFormat;
};
// #pragma mark - TableCellRendererConfig
class IntegerValueHandler::TableCellRendererConfig
: public TableCellIntegerRenderer::Config {
public:
TableCellRendererConfig()
:
fSettings(NULL),
fFormatSetting(NULL)
{
}
~TableCellRendererConfig()
{
if (fSettings != NULL)
fSettings->ReleaseReference();
}
status_t Init(SettingsDescription* settingsDescription)
{
fSettings = new(std::nothrow) Settings(settingsDescription);
if (fSettings == NULL)
return B_NO_MEMORY;
status_t error = fSettings->Init();
if (error != B_OK)
return error;
fFormatSetting = dynamic_cast<OptionsSetting*>(
settingsDescription->SettingByID(kFormatSettingID));
if (fFormatSetting == NULL)
return B_BAD_VALUE;
return B_OK;
}
virtual Settings* GetSettings() const
{
return fSettings;
}
virtual integer_format IntegerFormat() const
{
FormatOption* option = dynamic_cast<FormatOption*>(
fSettings->OptionValue(fFormatSetting));
return option != NULL ? option->Format() : INTEGER_FORMAT_DEFAULT;
}
private:
Settings* fSettings;
OptionsSetting* fFormatSetting;
};
// #pragma mark - IntegerValueHandler
IntegerValueHandler::IntegerValueHandler()
{
}
IntegerValueHandler::~IntegerValueHandler()
{
}
status_t
IntegerValueHandler::Init()
{
return B_OK;
}
float
IntegerValueHandler::SupportsValue(Value* value)
{
return dynamic_cast<IntegerValue*>(value) != NULL ? 0.5f : 0;
}
status_t
IntegerValueHandler::GetValueFormatter(Value* value,
ValueFormatter*& _formatter)
{
// TODO:...
return B_UNSUPPORTED;
}
status_t
IntegerValueHandler::GetTableCellValueRenderer(Value* _value,
TableCellValueRenderer*& _renderer)
{
IntegerValue* value = dynamic_cast<IntegerValue*>(_value);
if (value == NULL)
return B_BAD_VALUE;
// create a settings description
SettingsDescription* settingsDescription
= _CreateTableCellSettingsDescription(value);
if (settingsDescription == NULL)
return B_NO_MEMORY;
Reference<SettingsDescription> settingsDescriptionReference(
settingsDescription, true);
// create config
TableCellRendererConfig* config = new(std::nothrow) TableCellRendererConfig;
if (config == NULL)
return B_NO_MEMORY;
Reference<TableCellRendererConfig> configReference(config, true);
status_t error = config->Init(settingsDescription);
if (error != B_OK)
return error;
// create the renderer
return CreateTableCellValueRenderer(value, config, _renderer);
}
status_t
IntegerValueHandler::CreateTableCellValueSettingsMenu(Value* value,
Settings* settings, SettingsMenu*& _menu)
{
// get the format option
OptionsSetting* formatSetting = dynamic_cast<OptionsSetting*>(
settings->Description()->SettingByID(kFormatSettingID));
if (formatSetting == NULL)
return B_BAD_VALUE;
// create the settings menu
SettingsMenuImpl* menu = new(std::nothrow) SettingsMenuImpl(settings);
if (menu == NULL)
return B_NO_MEMORY;
ObjectDeleter<SettingsMenu> menuDeleter(menu);
// add the format option menu item
if (!menu->AddOptionsItem(formatSetting))
return B_NO_MEMORY;
_menu = menuDeleter.Detach();
return B_OK;
}
integer_format
IntegerValueHandler::DefaultIntegerFormat(IntegerValue* value)
{
return value->IsSigned() ? INTEGER_FORMAT_SIGNED : INTEGER_FORMAT_UNSIGNED;
}
status_t
IntegerValueHandler::AddIntegerFormatSettingOptions(IntegerValue* value,
OptionsSettingImpl* setting)
{
status_t error = AddIntegerFormatOption(setting, "signed", "Signed",
INTEGER_FORMAT_SIGNED);
if (error != B_OK)
return error;
error = AddIntegerFormatOption(setting, "unsigned", "Unsigned",
INTEGER_FORMAT_UNSIGNED);
if (error != B_OK)
return error;
error = AddIntegerFormatOption(setting, "hex", "Hexadecimal",
INTEGER_FORMAT_HEX_DEFAULT);
if (error != B_OK)
return error;
return B_OK;
}
status_t
IntegerValueHandler::CreateTableCellValueRenderer(IntegerValue* value,
TableCellIntegerRenderer::Config* config,
TableCellValueRenderer*& _renderer)
{
TableCellValueRenderer* renderer
= new(std::nothrow) TableCellIntegerRenderer(config);
if (renderer == NULL)
return B_NO_MEMORY;
_renderer = renderer;
return B_OK;
}
status_t
IntegerValueHandler::AddIntegerFormatOption(OptionsSettingImpl* setting,
const char* id, const char* name, integer_format format)
{
FormatOption* option = new(std::nothrow) FormatOption(id, name, format);
if (option == NULL || !setting->AddOption(option)) {
delete option;
return B_NO_MEMORY;
}
return B_OK;
}
SettingsDescription*
IntegerValueHandler::_CreateTableCellSettingsDescription(
IntegerValue* value)
{
// create description object
SettingsDescription* description = new(std::nothrow) SettingsDescription;
if (description == NULL)
return NULL;
Reference<SettingsDescription> descriptionReference(description, true);
// integer format setting
OptionsSettingImpl* setting = new(std::nothrow) OptionsSettingImpl(
kFormatSettingID, "Format");
if (setting == NULL)
return NULL;
Reference<OptionsSettingImpl> settingReference(setting, true);
// add options
if (AddIntegerFormatSettingOptions(value, setting) != B_OK)
return NULL;
// set default
integer_format defaultFormat = DefaultIntegerFormat(value);
SettingsOption* defaultOption = setting->OptionAt(0);
for (int32 i = 0;
FormatOption* option
= dynamic_cast<FormatOption*>(setting->OptionAt(i));
i++) {
if (option->Format() == defaultFormat) {
defaultOption = option;
break;
}
}
setting->SetDefaultOption(defaultOption);
// add setting
if (!description->AddSetting(setting))
return NULL;
return descriptionReference.Detach();
}
@@ -0,0 +1,58 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef INTEGER_VALUE_HANDLER_H
#define INTEGER_VALUE_HANDLER_H
#include "IntegerFormatter.h"
#include "TableCellIntegerRenderer.h"
#include "ValueHandler.h"
class IntegerValue;
class OptionsSettingImpl;
class SettingsDescription;
class IntegerValueHandler : public ValueHandler {
public:
IntegerValueHandler();
~IntegerValueHandler();
status_t Init();
virtual float SupportsValue(Value* value);
virtual status_t GetValueFormatter(Value* value,
ValueFormatter*& _formatter);
virtual status_t GetTableCellValueRenderer(Value* value,
TableCellValueRenderer*& _renderer);
virtual status_t CreateTableCellValueSettingsMenu(Value* value,
Settings* settings, SettingsMenu*& _menu);
protected:
virtual integer_format DefaultIntegerFormat(IntegerValue* value);
virtual status_t AddIntegerFormatSettingOptions(
IntegerValue* value,
OptionsSettingImpl* setting);
virtual status_t CreateTableCellValueRenderer(
IntegerValue* value,
TableCellIntegerRenderer::Config* config,
TableCellValueRenderer*& _renderer);
status_t AddIntegerFormatOption(
OptionsSettingImpl* setting, const char* id,
const char* name, integer_format format);
private:
class FormatOption;
class TableCellRendererConfig;
private:
SettingsDescription* _CreateTableCellSettingsDescription(
IntegerValue* value);
};
#endif // INTEGER_VALUE_HANDLER_H
@@ -0,0 +1,191 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "AddressValueNode.h"
#include <new>
#include "AddressValue.h"
#include "Architecture.h"
#include "Tracing.h"
#include "Type.h"
#include "ValueLoader.h"
#include "ValueLocation.h"
#include "ValueNodeContainer.h"
// #pragma mark - AddressValueNode
AddressValueNode::AddressValueNode(ValueNodeChild* nodeChild,
AddressType* type)
:
ValueNode(nodeChild),
fType(type),
fChild(NULL)
{
fType->AcquireReference();
}
AddressValueNode::~AddressValueNode()
{
if (fChild != NULL)
fChild->ReleaseReference();
fType->ReleaseReference();
}
Type*
AddressValueNode::GetType() const
{
return fType;
}
status_t
AddressValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
ValueLocation*& _location, Value*& _value)
{
// get the location
ValueLocation* location = NodeChild()->Location();
if (location == NULL)
return B_BAD_VALUE;
TRACE_LOCALS(" TYPE_ADDRESS\n");
// get the value type
type_code valueType;
if (valueLoader->GetArchitecture()->AddressSize() == 4) {
valueType = B_UINT32_TYPE;
TRACE_LOCALS(" -> 32 bit\n");
} else {
valueType = B_UINT64_TYPE;
TRACE_LOCALS(" -> 64 bit\n");
}
// load the value data
BVariant valueData;
status_t error = valueLoader->LoadValue(location, valueType, false,
valueData);
if (error != B_OK)
return error;
// create the type object
Value* value = new(std::nothrow) AddressValue(valueData);
if (value == NULL)
return B_NO_MEMORY;
location->AcquireReference();
_location = location;
_value = value;
return B_OK;
}
status_t
AddressValueNode::CreateChildren()
{
if (fChild != NULL)
return B_OK;
// construct name
BString name = "*";
name << Name();
// create the child
fChild = new(std::nothrow) AddressValueNodeChild(this, name,
fType->BaseType());
if (fChild == NULL)
return B_NO_MEMORY;
fChild->SetContainer(fContainer);
if (fContainer != NULL)
fContainer->NotifyValueNodeChildrenCreated(this);
return B_OK;
}
int32
AddressValueNode::CountChildren() const
{
return fChild != NULL ? 1 : 0;
}
ValueNodeChild*
AddressValueNode::ChildAt(int32 index) const
{
return index == 0 ? fChild : NULL;
}
// #pragma mark - AddressValueNodeChild
AddressValueNodeChild::AddressValueNodeChild(AddressValueNode* parent,
const BString& name, Type* type)
:
fParent(parent),
fName(name),
fType(type)
{
fType->AcquireReference();
}
AddressValueNodeChild::~AddressValueNodeChild()
{
fType->ReleaseReference();
}
const BString&
AddressValueNodeChild::Name() const
{
return fName;
}
Type*
AddressValueNodeChild::GetType() const
{
return fType;
}
ValueNode*
AddressValueNodeChild::Parent() const
{
return fParent;
}
status_t
AddressValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
ValueLocation*& _location)
{
// The parent's value is an address pointing to this component.
AddressValue* parentValue = dynamic_cast<AddressValue*>(
fParent->GetValue());
if (parentValue == NULL)
return B_BAD_VALUE;
// resolve the location
ValueLocation* location;
status_t error = fType->ResolveObjectDataLocation(parentValue->ToUInt64(),
location);
if (error != B_OK) {
TRACE_LOCALS("AddressValueNodeChild::ResolveLocation(): "
"ResolveObjectDataLocation() failed: %s\n", strerror(error));
return error;
}
_location = location;
return B_OK;
}
@@ -0,0 +1,61 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef ADDRESS_VALUE_NODE_H
#define ADDRESS_VALUE_NODE_H
#include "ValueNode.h"
class AddressValueNodeChild;
class AddressType;
class AddressValueNode : public ValueNode {
public:
AddressValueNode(ValueNodeChild* nodeChild,
AddressType* type);
virtual ~AddressValueNode();
virtual Type* GetType() const;
virtual status_t ResolvedLocationAndValue(
ValueLoader* valueLoader,
ValueLocation*& _location,
Value*& _value);
// locking required
virtual status_t CreateChildren();
virtual int32 CountChildren() const;
virtual ValueNodeChild* ChildAt(int32 index) const;
private:
AddressType* fType;
AddressValueNodeChild* fChild;
};
class AddressValueNodeChild : public ValueNodeChild {
public:
AddressValueNodeChild(AddressValueNode* parent,
const BString& name, Type* type);
virtual ~AddressValueNodeChild();
virtual const BString& Name() const;
virtual Type* GetType() const;
virtual ValueNode* Parent() const;
virtual status_t ResolveLocation(ValueLoader* valueLoader,
ValueLocation*& _location);
private:
AddressValueNode* fParent;
BString fName;
Type* fType;
};
#endif // ADDRESS_VALUE_NODE_H
@@ -0,0 +1,328 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ArrayValueNode.h"
#include <new>
#include "Architecture.h"
#include "ArrayIndexPath.h"
#include "IntegerValue.h"
#include "Tracing.h"
#include "Type.h"
#include "ValueLoader.h"
#include "ValueLocation.h"
#include "ValueNodeContainer.h"
// maximum number of array elements to show by default
static const uint64 kMaxArrayElementCount = 10;
// #pragma mark - AbstractArrayValueNode
AbstractArrayValueNode::AbstractArrayValueNode(ValueNodeChild* nodeChild,
ArrayType* type, int32 dimension)
:
ValueNode(nodeChild),
fType(type),
fDimension(dimension)
{
fType->AcquireReference();
}
AbstractArrayValueNode::~AbstractArrayValueNode()
{
fType->ReleaseReference();
for (int32 i = 0; AbstractArrayValueNodeChild* child = fChildren.ItemAt(i);
i++) {
child->RemoveReference();
}
}
Type*
AbstractArrayValueNode::GetType() const
{
return fType;
}
status_t
AbstractArrayValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
ValueLocation*& _location, Value*& _value)
{
// get the location
ValueLocation* location = NodeChild()->Location();
if (location == NULL)
return B_BAD_VALUE;
location->AcquireReference();
_location = location;
_value = NULL;
return B_OK;
}
status_t
AbstractArrayValueNode::CreateChildren()
{
if (!fChildren.IsEmpty())
return B_OK;
TRACE_LOCALS("TYPE_ARRAY\n");
int32 dimensionCount = fType->CountDimensions();
bool isFinalDimension = fDimension + 1 == dimensionCount;
ArrayDimension* dimension = fType->DimensionAt(fDimension);
uint64 elementCount = dimension->CountElements();
if (elementCount == 0 || elementCount > kMaxArrayElementCount)
elementCount = kMaxArrayElementCount;
// create children for the array elements
for (int32 i = 0; i < (int32)elementCount; i++) {
BString name(Name());
name << '[' << i << ']';
if (name.Length() <= Name().Length())
return B_NO_MEMORY;
AbstractArrayValueNodeChild* child;
if (isFinalDimension) {
child = new(std::nothrow) ArrayValueNodeChild(this, name, i,
fType->BaseType());
} else {
child = new(std::nothrow) InternalArrayValueNodeChild(this, name, i,
fType);
}
if (child == NULL || !fChildren.AddItem(child)) {
delete child;
return B_NO_MEMORY;
}
child->SetContainer(fContainer);
}
if (fContainer != NULL)
fContainer->NotifyValueNodeChildrenCreated(this);
return B_OK;
}
int32
AbstractArrayValueNode::CountChildren() const
{
return fChildren.CountItems();
}
ValueNodeChild*
AbstractArrayValueNode::ChildAt(int32 index) const
{
return fChildren.ItemAt(index);
}
// #pragma mark - ArrayValueNode
ArrayValueNode::ArrayValueNode(ValueNodeChild* nodeChild, ArrayType* type)
:
AbstractArrayValueNode(nodeChild, type, 0)
{
}
ArrayValueNode::~ArrayValueNode()
{
}
// #pragma mark - InternalArrayValueNode
InternalArrayValueNode::InternalArrayValueNode(ValueNodeChild* nodeChild,
ArrayType* type, int32 dimension)
:
AbstractArrayValueNode(nodeChild, type, dimension)
{
}
InternalArrayValueNode::~InternalArrayValueNode()
{
}
// #pragma mark - AbstractArrayValueNodeChild
AbstractArrayValueNodeChild::AbstractArrayValueNodeChild(
AbstractArrayValueNode* parent, const BString& name, int64 elementIndex)
:
fParent(parent),
fName(name),
fElementIndex(elementIndex)
{
}
AbstractArrayValueNodeChild::~AbstractArrayValueNodeChild()
{
}
const BString&
AbstractArrayValueNodeChild::Name() const
{
return fName;
}
ValueNode*
AbstractArrayValueNodeChild::Parent() const
{
return fParent;
}
// #pragma mark - ArrayValueNodeChild
ArrayValueNodeChild::ArrayValueNodeChild(AbstractArrayValueNode* parent,
const BString& name, int64 elementIndex, Type* type)
:
AbstractArrayValueNodeChild(parent, name, elementIndex),
fType(type)
{
fType->AcquireReference();
}
ArrayValueNodeChild::~ArrayValueNodeChild()
{
fType->ReleaseReference();
}
Type*
ArrayValueNodeChild::GetType() const
{
return fType;
}
status_t
ArrayValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
ValueLocation*& _location)
{
// get the parent (== array) location
ValueLocation* parentLocation = fParent->Location();
if (parentLocation == NULL)
return B_BAD_VALUE;
// create an array index path
ArrayType* arrayType = fParent->GetArrayType();
int32 dimensionCount = arrayType->CountDimensions();
// add dummy indices first -- we'll replace them on our way back through
// our ancestors
ArrayIndexPath indexPath;
for (int32 i = 0; i < dimensionCount; i++) {
if (!indexPath.AddIndex(0))
return B_NO_MEMORY;
}
AbstractArrayValueNodeChild* child = this;
for (int32 i = dimensionCount - 1; i >= 0; i--) {
indexPath.SetIndexAt(i, child->ElementIndex());
child = dynamic_cast<AbstractArrayValueNodeChild*>(
child->ArrayParent()->NodeChild());
}
// resolve the element location
ValueLocation* location;
status_t error = arrayType->ResolveElementLocation(indexPath,
*parentLocation, location);
if (error != B_OK) {
TRACE_LOCALS("ArrayValueNodeChild::ResolveLocation(): "
"ResolveElementLocation() failed: %s\n", strerror(error));
return error;
}
_location = location;
return B_OK;
}
// #pragma mark - InternalArrayValueNodeChild
InternalArrayValueNodeChild::InternalArrayValueNodeChild(
AbstractArrayValueNode* parent, const BString& name, int64 elementIndex,
ArrayType* type)
:
AbstractArrayValueNodeChild(parent, name, elementIndex),
fType(type)
{
fType->AcquireReference();
}
InternalArrayValueNodeChild::~InternalArrayValueNodeChild()
{
fType->ReleaseReference();
}
Type*
InternalArrayValueNodeChild::GetType() const
{
return fType;
}
bool
InternalArrayValueNodeChild::IsInternal() const
{
return true;
}
status_t
InternalArrayValueNodeChild::CreateInternalNode(ValueNode*& _node)
{
ValueNode* node = new(std::nothrow) InternalArrayValueNode(this, fType,
fParent->Dimension() + 1);
if (node == NULL)
return B_NO_MEMORY;
_node = node;
return B_OK;
}
status_t
InternalArrayValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
ValueLocation*& _location)
{
// This is an internal child node for a non-final dimension -- just clone
// the parent's location.
ValueLocation* parentLocation = fParent->Location();
if (parentLocation == NULL)
return B_BAD_VALUE;
parentLocation->AcquireReference();
_location = parentLocation;
return B_OK;
}
@@ -0,0 +1,131 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef ARRAY_VALUE_NODE_H
#define ARRAY_VALUE_NODE_H
#include <ObjectList.h>
#include "ValueNode.h"
class AbstractArrayValueNodeChild;
class ArrayType;
class AbstractArrayValueNode : public ValueNode {
public:
AbstractArrayValueNode(
ValueNodeChild* nodeChild, ArrayType* type,
int32 dimension);
virtual ~AbstractArrayValueNode();
ArrayType* GetArrayType() const
{ return fType; }
int32 Dimension() const
{ return fDimension; }
virtual Type* GetType() const;
virtual status_t ResolvedLocationAndValue(
ValueLoader* valueLoader,
ValueLocation*& _location,
Value*& _value);
// locking required
virtual status_t CreateChildren();
virtual int32 CountChildren() const;
virtual ValueNodeChild* ChildAt(int32 index) const;
protected:
typedef BObjectList<AbstractArrayValueNodeChild> ChildList;
protected:
ArrayType* fType;
ChildList fChildren;
int32 fDimension;
};
// TODO: Are ArrayValueNode and InternalArrayValueNode still needed?
class ArrayValueNode : public AbstractArrayValueNode {
public:
ArrayValueNode(ValueNodeChild* nodeChild,
ArrayType* type);
virtual ~ArrayValueNode();
};
class InternalArrayValueNode : public AbstractArrayValueNode {
public:
InternalArrayValueNode(
ValueNodeChild* nodeChild,
ArrayType* type, int32 dimension);
virtual ~InternalArrayValueNode();
};
class AbstractArrayValueNodeChild : public ValueNodeChild {
public:
AbstractArrayValueNodeChild(
AbstractArrayValueNode* parent,
const BString& name, int64 elementIndex);
virtual ~AbstractArrayValueNodeChild();
AbstractArrayValueNode* ArrayParent() const { return fParent; }
int32 ElementIndex() const { return fElementIndex; }
virtual const BString& Name() const;
virtual ValueNode* Parent() const;
protected:
AbstractArrayValueNode* fParent;
BString fName;
int64 fElementIndex;
};
class ArrayValueNodeChild : public AbstractArrayValueNodeChild {
public:
ArrayValueNodeChild(
AbstractArrayValueNode* parent,
const BString& name, int64 elementIndex,
Type* type);
virtual ~ArrayValueNodeChild();
virtual Type* GetType() const;
virtual status_t ResolveLocation(ValueLoader* valueLoader,
ValueLocation*& _location);
private:
Type* fType;
};
class InternalArrayValueNodeChild : public AbstractArrayValueNodeChild {
public:
InternalArrayValueNodeChild(
AbstractArrayValueNode* parent,
const BString& name, int64 elementIndex,
ArrayType* type);
virtual ~InternalArrayValueNodeChild();
virtual Type* GetType() const;
virtual bool IsInternal() const;
virtual status_t CreateInternalNode(ValueNode*& _node);
virtual status_t ResolveLocation(ValueLoader* valueLoader,
ValueLocation*& _location);
private:
ArrayType* fType;
};
#endif // ARRAY_VALUE_NODE_H
@@ -0,0 +1,243 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "CompoundValueNode.h"
#include <new>
#include "Architecture.h"
#include "IntegerValue.h"
#include "Tracing.h"
#include "Type.h"
#include "ValueLoader.h"
#include "ValueLocation.h"
#include "ValueNodeContainer.h"
// #pragma mark - Child
class CompoundValueNode::Child : public ValueNodeChild {
public:
Child(CompoundValueNode* parent, const BString& name)
:
fParent(parent),
fName(name)
{
}
virtual const BString& Name() const
{
return fName;
}
virtual ValueNode* Parent() const
{
return fParent;
}
protected:
CompoundValueNode* fParent;
BString fName;
};
// #pragma mark - BaseTypeChild
class CompoundValueNode::BaseTypeChild : public Child {
public:
BaseTypeChild(CompoundValueNode* parent, BaseType* baseType)
:
Child(parent, baseType->GetType()->Name()),
fBaseType(baseType)
{
fBaseType->AcquireReference();
}
virtual ~BaseTypeChild()
{
fBaseType->ReleaseReference();
}
virtual Type* GetType() const
{
return fBaseType->GetType();
}
virtual status_t ResolveLocation(ValueLoader* valueLoader,
ValueLocation*& _location)
{
// The parent's location refers to the location of the complete
// object. We want to extract the location of a member.
ValueLocation* parentLocation = fParent->Location();
if (parentLocation == NULL)
return B_BAD_VALUE;
ValueLocation* location;
status_t error = fParent->fType->ResolveBaseTypeLocation(fBaseType,
*parentLocation, location);
if (error != B_OK) {
TRACE_LOCALS("CompoundValueNode::BaseTypeChild::ResolveLocation(): "
"ResolveBaseTypeLocation() failed: %s\n", strerror(error));
return error;
}
_location = location;
return B_OK;
}
private:
BaseType* fBaseType;
};
// #pragma mark - MemberChild
class CompoundValueNode::MemberChild : public Child {
public:
MemberChild(CompoundValueNode* parent, DataMember* member)
:
Child(parent, member->Name()),
fMember(member)
{
fMember->AcquireReference();
}
virtual ~MemberChild()
{
fMember->ReleaseReference();
}
virtual Type* GetType() const
{
return fMember->GetType();
}
virtual status_t ResolveLocation(ValueLoader* valueLoader,
ValueLocation*& _location)
{
// The parent's location refers to the location of the complete
// object. We want to extract the location of a member.
ValueLocation* parentLocation = fParent->Location();
if (parentLocation == NULL)
return B_BAD_VALUE;
ValueLocation* location;
status_t error = fParent->fType->ResolveDataMemberLocation(fMember,
*parentLocation, location);
if (error != B_OK) {
TRACE_LOCALS("CompoundValueNode::MemberChild::ResolveLocation(): "
"ResolveDataMemberLocation() failed: %s\n", strerror(error));
return error;
}
_location = location;
return B_OK;
}
private:
DataMember* fMember;
};
// #pragma mark - CompoundValueNode
CompoundValueNode::CompoundValueNode(ValueNodeChild* nodeChild,
CompoundType* type)
:
ValueNode(nodeChild),
fType(type)
{
fType->AcquireReference();
}
CompoundValueNode::~CompoundValueNode()
{
fType->ReleaseReference();
for (int32 i = 0; Child* child = fChildren.ItemAt(i); i++)
child->RemoveReference();
}
Type*
CompoundValueNode::GetType() const
{
return fType;
}
status_t
CompoundValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
ValueLocation*& _location, Value*& _value)
{
// get the location
ValueLocation* location = NodeChild()->Location();
if (location == NULL)
return B_BAD_VALUE;
location->AcquireReference();
_location = location;
_value = NULL;
return B_OK;
}
status_t
CompoundValueNode::CreateChildren()
{
if (!fChildren.IsEmpty())
return B_OK;
// base types
for (int32 i = 0; BaseType* baseType = fType->BaseTypeAt(i); i++) {
TRACE_LOCALS(" base %ld\n", i);
BaseTypeChild* child = new(std::nothrow) BaseTypeChild(this, baseType);
if (child == NULL || !fChildren.AddItem(child)) {
delete child;
return B_NO_MEMORY;
}
child->SetContainer(fContainer);
}
// members
for (int32 i = 0; DataMember* member = fType->DataMemberAt(i); i++) {
TRACE_LOCALS(" member %ld: \"%s\"\n", i, member->Name());
MemberChild* child = new(std::nothrow) MemberChild(this, member);
if (child == NULL || !fChildren.AddItem(child)) {
delete child;
return B_NO_MEMORY;
}
child->SetContainer(fContainer);
}
if (fContainer != NULL)
fContainer->NotifyValueNodeChildrenCreated(this);
return B_OK;
}
int32
CompoundValueNode::CountChildren() const
{
return fChildren.CountItems();
}
ValueNodeChild*
CompoundValueNode::ChildAt(int32 index) const
{
return fChildren.ItemAt(index);
}
@@ -0,0 +1,49 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef COMPOUND_VALUE_NODE_H
#define COMPOUND_VALUE_NODE_H
#include <ObjectList.h>
#include "ValueNode.h"
class CompoundType;
class CompoundValueNode : public ValueNode {
public:
CompoundValueNode(ValueNodeChild* nodeChild,
CompoundType* type);
virtual ~CompoundValueNode();
virtual Type* GetType() const;
virtual status_t ResolvedLocationAndValue(
ValueLoader* valueLoader,
ValueLocation*& _location,
Value*& _value);
// locking required
virtual status_t CreateChildren();
virtual int32 CountChildren() const;
virtual ValueNodeChild* ChildAt(int32 index) const;
private:
class Child;
class BaseTypeChild;
class MemberChild;
typedef BObjectList<Child> ChildList;
private:
CompoundType* fType;
ChildList fChildren;
};
#endif // ADDRESS_VALUE_NODE_H
@@ -0,0 +1,99 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "EnumerationValueNode.h"
#include <new>
#include "EnumerationValue.h"
#include "Tracing.h"
#include "Type.h"
#include "ValueLoader.h"
#include "ValueLocation.h"
EnumerationValueNode::EnumerationValueNode(ValueNodeChild* nodeChild,
EnumerationType* type)
:
ChildlessValueNode(nodeChild),
fType(type)
{
fType->AcquireReference();
}
EnumerationValueNode::~EnumerationValueNode()
{
fType->ReleaseReference();
}
Type*
EnumerationValueNode::GetType() const
{
return fType;
}
status_t
EnumerationValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
ValueLocation*& _location, Value*& _value)
{
// get the location
ValueLocation* location = NodeChild()->Location();
if (location == NULL)
return B_BAD_VALUE;
TRACE_LOCALS(" TYPE_ENUMERATION\n");
// get the value type
type_code valueType = 0;
// If a base type is known, try that.
if (PrimitiveType* baseType = dynamic_cast<PrimitiveType*>(
fType->BaseType())) {
valueType = baseType->TypeConstant();
if (!BVariant::TypeIsInteger(valueType))
valueType = 0;
}
// If we don't have a value type yet, guess it from the type size.
if (valueType == 0) {
// TODO: This is C source language specific!
switch (fType->ByteSize()) {
case 1:
valueType = B_INT8_TYPE;
break;
case 2:
valueType = B_INT16_TYPE;
break;
case 4:
default:
valueType = B_INT32_TYPE;
break;
case 8:
valueType = B_INT64_TYPE;
break;
}
}
// load the value data
BVariant valueData;
status_t error = valueLoader->LoadValue(location, valueType, true,
valueData);
if (error != B_OK)
return error;
// create the type object
Value* value = new(std::nothrow) EnumerationValue(fType, valueData);
if (value == NULL)
return B_NO_MEMORY;
location->AcquireReference();
_location = location;
_value = value;
return B_OK;
}
@@ -0,0 +1,33 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef ENUMERATION_VALUE_NODE_H
#define ENUMERATION_VALUE_NODE_H
#include "ValueNode.h"
class EnumerationType;
class EnumerationValueNode : public ChildlessValueNode {
public:
EnumerationValueNode(ValueNodeChild* nodeChild,
EnumerationType* type);
virtual ~EnumerationValueNode();
virtual Type* GetType() const;
virtual status_t ResolvedLocationAndValue(
ValueLoader* valueLoader,
ValueLocation*& _location,
Value*& _value);
private:
EnumerationType* fType;
};
#endif // ENUMERATION_VALUE_NODE_H
@@ -0,0 +1,79 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "PointerToMemberValueNode.h"
#include <new>
#include "Architecture.h"
#include "IntegerValue.h"
#include "Tracing.h"
#include "Type.h"
#include "ValueLoader.h"
#include "ValueLocation.h"
PointerToMemberValueNode::PointerToMemberValueNode(ValueNodeChild* nodeChild,
PointerToMemberType* type)
:
ChildlessValueNode(nodeChild),
fType(type)
{
fType->AcquireReference();
}
PointerToMemberValueNode::~PointerToMemberValueNode()
{
fType->ReleaseReference();
}
Type*
PointerToMemberValueNode::GetType() const
{
return fType;
}
status_t
PointerToMemberValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
ValueLocation*& _location, Value*& _value)
{
// get the location
ValueLocation* location = NodeChild()->Location();
if (location == NULL)
return B_BAD_VALUE;
TRACE_LOCALS(" TYPE_POINTER_TO_MEMBER\n");
// get the value type
type_code valueType;
if (valueLoader->GetArchitecture()->AddressSize() == 4) {
valueType = B_UINT32_TYPE;
TRACE_LOCALS(" -> 32 bit\n");
} else {
valueType = B_UINT64_TYPE;
TRACE_LOCALS(" -> 64 bit\n");
}
// load the value data
BVariant valueData;
status_t error = valueLoader->LoadValue(location, valueType, false,
valueData);
if (error != B_OK)
return error;
// create the type object
Value* value = new(std::nothrow) IntegerValue(valueData);
if (value == NULL)
return B_NO_MEMORY;
location->AcquireReference();
_location = location;
_value = value;
return B_OK;
}
@@ -0,0 +1,34 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef POINTER_TO_MEMBER_VALUE_NODE_H
#define POINTER_TO_MEMBER_VALUE_NODE_H
#include "ValueNode.h"
class PointerToMemberType;
class PointerToMemberValueNode : public ChildlessValueNode {
public:
PointerToMemberValueNode(
ValueNodeChild* nodeChild,
PointerToMemberType* type);
virtual ~PointerToMemberValueNode();
virtual Type* GetType() const;
virtual status_t ResolvedLocationAndValue(
ValueLoader* valueLoader,
ValueLocation*& _location,
Value*& _value);
private:
PointerToMemberType* fType;
};
#endif // POINTER_TO_MEMBER_VALUE_NODE_H
@@ -0,0 +1,91 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "PrimitiveValueNode.h"
#include <new>
#include "BoolValue.h"
#include "FloatValue.h"
#include "IntegerValue.h"
#include "Tracing.h"
#include "Type.h"
#include "ValueLoader.h"
#include "ValueLocation.h"
PrimitiveValueNode::PrimitiveValueNode(ValueNodeChild* nodeChild,
PrimitiveType* type)
:
ChildlessValueNode(nodeChild),
fType(type)
{
fType->AcquireReference();
}
PrimitiveValueNode::~PrimitiveValueNode()
{
fType->ReleaseReference();
}
Type*
PrimitiveValueNode::GetType() const
{
return fType;
}
status_t
PrimitiveValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
ValueLocation*& _location, Value*& _value)
{
// get the location
ValueLocation* location = NodeChild()->Location();
if (location == NULL)
return B_BAD_VALUE;
// get the value type
type_code valueType = fType->TypeConstant();
if (!BVariant::TypeIsNumber(valueType) && valueType != B_BOOL_TYPE) {
TRACE_LOCALS(" -> unknown type constant\n");
return B_UNSUPPORTED;
}
bool shortValueIsFine = BVariant::TypeIsInteger(valueType)
|| valueType == B_BOOL_TYPE;
TRACE_LOCALS(" TYPE_PRIMITIVE: '%c%c%c%c'\n",
int(valueType >> 24), int(valueType >> 16),
int(valueType >> 8), int(valueType));
// load the value data
BVariant valueData;
status_t error = valueLoader->LoadValue(location, valueType,
shortValueIsFine, valueData);
if (error != B_OK)
return error;
// create the type object
Value* value;
if (valueType == B_BOOL_TYPE)
value = new(std::nothrow) BoolValue(valueData.ToBool());
else if (BVariant::TypeIsInteger(valueType))
value = new(std::nothrow) IntegerValue(valueData);
else if (BVariant::TypeIsFloat(valueType))
value = new(std::nothrow) FloatValue(valueData.ToDouble());
else
return B_UNSUPPORTED;
if (value == NULL)
return B_NO_MEMORY;
location->AcquireReference();
_location = location;
_value = value;
return B_OK;
}
@@ -0,0 +1,33 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef PRIMITIVE_VALUE_NODE_H
#define PRIMITIVE_VALUE_NODE_H
#include "ValueNode.h"
class PrimitiveType;
class PrimitiveValueNode : public ChildlessValueNode {
public:
PrimitiveValueNode(ValueNodeChild* nodeChild,
PrimitiveType* type);
virtual ~PrimitiveValueNode();
virtual Type* GetType() const;
virtual status_t ResolvedLocationAndValue(
ValueLoader* valueLoader,
ValueLocation*& _location,
Value*& _value);
private:
PrimitiveType* fType;
};
#endif // PRIMITIVE_VALUE_NODE_H
@@ -0,0 +1,56 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "VariableValueNodeChild.h"
#include "Variable.h"
#include "ValueLocation.h"
VariableValueNodeChild::VariableValueNodeChild(Variable* variable)
:
fVariable(variable)
{
fVariable->AcquireReference();
SetLocation(fVariable->Location(), B_OK);
}
VariableValueNodeChild::~VariableValueNodeChild()
{
fVariable->ReleaseReference();
}
const BString&
VariableValueNodeChild::Name() const
{
return fVariable->Name();
}
Type*
VariableValueNodeChild::GetType() const
{
return fVariable->GetType();
}
ValueNode*
VariableValueNodeChild::Parent() const
{
return NULL;
}
status_t
VariableValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
ValueLocation*& _location)
{
_location = fVariable->Location();
_location->AcquireReference();
return B_OK;
}
@@ -0,0 +1,32 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef VARIABLE_VALUE_NODE_CHILD_H
#define VARIABLE_VALUE_NODE_CHILD_H
#include "ValueNode.h"
class Variable;
class VariableValueNodeChild : public ValueNodeChild {
public:
VariableValueNodeChild(Variable* variable);
virtual ~VariableValueNodeChild();
virtual const BString& Name() const;
virtual Type* GetType() const;
virtual ValueNode* Parent() const;
virtual status_t ResolveLocation(ValueLoader* valueLoader,
ValueLocation*& _location);
private:
Variable* fVariable;
};
#endif // VARIABLE_VALUE_NODE_CHILD_H
@@ -0,0 +1,39 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "AddressValue.h"
#include <stdio.h>
AddressValue::AddressValue(const BVariant& value)
:
IntegerValue(value)
{
}
AddressValue::~AddressValue()
{
}
bool
AddressValue::ToString(BString& _string) const
{
if (!fValue.IsInteger())
return false;
char buffer[32];
snprintf(buffer, sizeof(buffer), "%#llx", fValue.ToUInt64());
BString string(buffer);
if (string.Length() == 0)
return false;
_string = string;
return true;
}
@@ -0,0 +1,21 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef ADDRESS_VALUE_H
#define ADDRESS_VALUE_H
#include "IntegerValue.h"
class AddressValue : public IntegerValue {
public:
AddressValue(const BVariant& value);
virtual ~AddressValue();
virtual bool ToString(BString& _string) const;
};
#endif // ADDRESS_VALUE_H
@@ -0,0 +1,47 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "BoolValue.h"
BoolValue::BoolValue(bool value)
:
fValue(value)
{
}
BoolValue::~BoolValue()
{
}
bool
BoolValue::ToString(BString& _string) const
{
BString string = fValue ? "true" : "false";
if (string.Length() == 0)
return false;
_string = string;
return true;
}
bool
BoolValue::ToVariant(BVariant& _value) const
{
_value = fValue;
return true;
}
bool
BoolValue::operator==(const Value& other) const
{
const BoolValue* otherBool = dynamic_cast<const BoolValue*>(&other);
return otherBool != NULL ? fValue == otherBool->fValue : false;
}
@@ -0,0 +1,30 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef BOOL_VALUE_H
#define BOOL_VALUE_H
#include "Value.h"
class BoolValue : public Value {
public:
BoolValue(bool value);
virtual ~BoolValue();
bool GetValue() const
{ return fValue; }
virtual bool ToString(BString& _string) const;
virtual bool ToVariant(BVariant& _value) const;
virtual bool operator==(const Value& other) const;
private:
bool fValue;
};
#endif // BOOL_VALUE_H
@@ -0,0 +1,43 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "EnumerationValue.h"
#include "Type.h"
EnumerationValue::EnumerationValue(EnumerationType* type, const BVariant& value)
:
IntegerValue(value),
fType(type)
{
fType->AcquireReference();
}
EnumerationValue::~EnumerationValue()
{
fType->ReleaseReference();
}
bool
EnumerationValue::ToString(BString& _string) const
{
if (!fValue.IsInteger())
return false;
EnumeratorValue* enumValue = fType->ValueFor(fValue);
if (enumValue == NULL)
return IntegerValue::ToString(_string);
BString string(enumValue->Name());
if (string.Length() == 0)
return false;
_string = string;
return true;
}
@@ -0,0 +1,31 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef ENUMERATION_VALUE_H
#define ENUMERATION_VALUE_H
#include "IntegerValue.h"
class EnumerationType;
class EnumerationValue : public IntegerValue {
public:
EnumerationValue(EnumerationType* type,
const BVariant& value);
virtual ~EnumerationValue();
EnumerationType* GetType() const
{ return fType; }
virtual bool ToString(BString& _string) const;
private:
EnumerationType* fType;
};
#endif // ENUMERATION_VALUE_H
@@ -0,0 +1,52 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "FloatValue.h"
#include <stdio.h>
FloatValue::FloatValue(double value)
:
fValue(value)
{
}
FloatValue::~FloatValue()
{
}
bool
FloatValue::ToString(BString& _string) const
{
char buffer[128];
snprintf(buffer, sizeof(buffer), "%g", fValue);
BString string(buffer);
if (string.Length() == 0)
return false;
_string = string;
return true;
}
bool
FloatValue::ToVariant(BVariant& _value) const
{
_value = fValue;
return true;
}
bool
FloatValue::operator==(const Value& other) const
{
const FloatValue* otherInt = dynamic_cast<const FloatValue*>(&other);
return otherInt != NULL ? fValue == otherInt->fValue : false;
}
@@ -0,0 +1,30 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef FLOAT_VALUE_H
#define FLOAT_VALUE_H
#include "Value.h"
class FloatValue : public Value {
public:
FloatValue(double value);
virtual ~FloatValue();
double GetValue() const
{ return fValue; }
virtual bool ToString(BString& _string) const;
virtual bool ToVariant(BVariant& _value) const;
virtual bool operator==(const Value& other) const;
private:
double fValue;
};
#endif // FLOAT_VALUE_H
@@ -0,0 +1,64 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "IntegerValue.h"
IntegerValue::IntegerValue(const BVariant& value)
:
fValue(value)
{
}
IntegerValue::~IntegerValue()
{
}
bool
IntegerValue::IsSigned() const
{
bool isSigned;
return fValue.IsInteger(&isSigned) && isSigned;
}
bool
IntegerValue::ToString(BString& _string) const
{
bool isSigned;
if (!fValue.IsInteger(&isSigned))
return false;
BString string;
if (isSigned)
string << fValue.ToInt64();
else
string << fValue.ToUInt64();
if (string.Length() == 0)
return false;
_string = string;
return true;
}
bool
IntegerValue::ToVariant(BVariant& _value) const
{
_value = fValue;
return true;
}
bool
IntegerValue::operator==(const Value& other) const
{
const IntegerValue* otherInt = dynamic_cast<const IntegerValue*>(&other);
return otherInt != NULL ? fValue == otherInt->fValue : false;
}
@@ -0,0 +1,36 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef INTEGER_VALUE_H
#define INTEGER_VALUE_H
#include "Value.h"
class IntegerValue : public Value {
public:
IntegerValue(const BVariant& value);
virtual ~IntegerValue();
bool IsSigned() const;
int64 ToInt64() const
{ return fValue.ToInt64(); }
uint64 ToUInt64() const
{ return fValue.ToUInt64(); }
const BVariant& GetValue() const
{ return fValue; }
virtual bool ToString(BString& _string) const;
virtual bool ToVariant(BVariant& _value) const;
virtual bool operator==(const Value& other) const;
protected:
BVariant fValue;
};
#endif // INTEGER_VALUE_H