* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "PropertyObject.h"
#include <stdio.h>
#include <ByteOrder.h>
#include <Message.h>
#include <OS.h>
#include "Int64Property.h"
#include "Property.h"
#ifndef DEBUG
# define DEBUG 0
#endif
PropertyObject::PropertyObject()
: fProperties(16)
{
}
PropertyObject::PropertyObject(const PropertyObject& other)
: fProperties(16)
{
Assign(other);
}
PropertyObject::~PropertyObject()
{
DeleteProperties();
}
status_t
PropertyObject::Archive(BMessage* into) const
{
if (!into)
return B_BAD_VALUE;
status_t ret = B_OK;
int32 count = CountProperties();
for (int32 i = 0; i < count; i++) {
Property* p = PropertyAtFast(i);
unsigned id = B_HOST_TO_BENDIAN_INT32(p->Identifier());
char idString[5];
sprintf(idString, "%.4s", (const char*)&id);
idString[4] = 0;
BString value;
p->GetValue(value);
ret = into->AddString(idString, value.String());
if (ret < B_OK)
return ret;
}
return ret;
}
status_t
PropertyObject::Unarchive(const BMessage* archive)
{
if (!archive)
return B_BAD_VALUE;
SuspendNotifications(true);
int32 count = CountProperties();
for (int32 i = 0; i < count; i++) {
Property* p = PropertyAtFast(i);
unsigned id = B_HOST_TO_BENDIAN_INT32(p->Identifier());
char idString[5];
sprintf(idString, "%.4s", (const char*)&id);
idString[4] = 0;
const char* value;
if (archive->FindString(idString, &value) == B_OK)
if (p->SetValue(value))
Notify();
}
SuspendNotifications(false);
return B_OK;
}
bool
PropertyObject::AddProperty(Property* property)
{
if (!property)
return false;
#if DEBUG
if (FindProperty(property->Identifier())) {
debugger("PropertyObject::AddProperty() -"
"property with same ID already here!\n");
return false;
}
if (fProperties.HasItem((void*)property)) {
debugger("PropertyObject::AddProperty() - property id "
"changed unexpectedly\n");
return false;
}
#endif
if (fProperties.AddItem((void*)property)) {
Notify();
return true;
}
return false;
}
Property*
PropertyObject::PropertyAt(int32 index) const
{
return (Property*)fProperties.ItemAt(index);
}
Property*
PropertyObject::PropertyAtFast(int32 index) const
{
return (Property*)fProperties.ItemAtFast(index);
}
int32
PropertyObject::CountProperties() const
{
return fProperties.CountItems();
}
Property*
PropertyObject::FindProperty(uint32 propertyID) const
{
int32 count = fProperties.CountItems();
for (int32 i = 0; i < count; i++) {
Property* p = (Property*)fProperties.ItemAtFast(i);
if (p->Identifier() == propertyID)
return p;
}
return NULL;
}
bool
PropertyObject::HasProperty(Property* property) const
{
return fProperties.HasItem((void*)property);
}
bool
PropertyObject::ContainsSameProperties(const PropertyObject& other) const
{
bool equal = false;
int32 count = CountProperties();
if (count == other.CountProperties()) {
equal = true;
for (int32 i = 0; i < count; i++) {
Property* ownProperty = PropertyAtFast(i);
Property* otherProperty = other.PropertyAtFast(i);
if (ownProperty->Identifier() != otherProperty->Identifier()) {
equal = false;
break;
}
}
}
return equal;
}
status_t
PropertyObject::Assign(const PropertyObject& other)
{
DeleteProperties();
int32 count = other.fProperties.CountItems();
for (int32 i = 0; i < count; i++) {
Property* p = (Property*)other.fProperties.ItemAtFast(i);
Property* clone = p->Clone();
if (!AddProperty(clone)) {
delete clone;
fprintf(stderr, "PropertyObject::Assign() - no memory for "
"cloning properties!\n");
return B_NO_MEMORY;
}
}
return B_OK;
}
void
PropertyObject::DeleteProperties()
{
int32 count = fProperties.CountItems();
for (int32 i = 0; i < count; i++)
delete (Property*)fProperties.ItemAtFast(i);
fProperties.MakeEmpty();
Notify();
}
bool
PropertyObject::DeleteProperty(uint32 propertyID)
{
int32 count = fProperties.CountItems();
for (int32 i = 0; i < count; i++) {
Property* p = (Property*)fProperties.ItemAtFast(i);
if (p->Identifier() == propertyID) {
if (fProperties.RemoveItem(i)) {
Notify();
delete p;
return true;
}
break;
}
}
return false;
}
void
PropertyObject::ValueChanged(uint32 propertyID)
{
Notify();
}
bool
PropertyObject::SetValue(uint32 propertyID, const char* value)
{
if (Property* p = FindProperty(propertyID)) {
if (p->SetValue(value)) {
ValueChanged(propertyID);
return true;
}
}
return false;
}
bool
PropertyObject::GetValue(uint32 propertyID, BString& value) const
{
if (Property* p = FindProperty(propertyID)) {
p->GetValue(value);
return true;
}
return false;
}
bool
PropertyObject::SetValue(uint32 propertyID, int32 value)
{
IntProperty* p = dynamic_cast<IntProperty*>(FindProperty(propertyID));
if (p && p->SetValue(value)) {
ValueChanged(propertyID);
return true;
}
return false;
}
int32
PropertyObject::Value(uint32 propertyID, int32 defaultValue) const
{
if (IntProperty* p = dynamic_cast<IntProperty*>(FindProperty(propertyID)))
return p->Value();
return defaultValue;
}
bool
PropertyObject::SetValue(uint32 propertyID, int64 value)
{
Int64Property* p = dynamic_cast<Int64Property*>(FindProperty(propertyID));
if (p && p->SetValue(value)) {
ValueChanged(propertyID);
return true;
}
return false;
}
int64
PropertyObject::Value(uint32 propertyID, int64 defaultValue) const
{
if (Int64Property* p = dynamic_cast<Int64Property*>(FindProperty(propertyID)))
return p->Value();
return defaultValue;
}
bool
PropertyObject::SetValue(uint32 propertyID, float value)
{
FloatProperty* p = dynamic_cast<FloatProperty*>(FindProperty(propertyID));
if (p && p->SetValue(value)) {
ValueChanged(propertyID);
return true;
}
return false;
}
float
PropertyObject::Value(uint32 propertyID, float defaultValue) const
{
if (FloatProperty* p = dynamic_cast<FloatProperty*>(FindProperty(propertyID)))
return p->Value();
return defaultValue;
}
bool
PropertyObject::SetValue(uint32 propertyID, bool value)
{
BoolProperty* p = dynamic_cast<BoolProperty*>(FindProperty(propertyID));
if (p && p->SetValue(value)) {
ValueChanged(propertyID);
return true;
}
return false;
}
bool
PropertyObject::Value(uint32 propertyID, bool defaultValue) const
{
if (BoolProperty* p = dynamic_cast<BoolProperty*>(FindProperty(propertyID)))
return p->Value();
return defaultValue;
}