1/* 2 * Copyright 2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan A��mus <superstippi@gmx.de> 7 */ 8 9#include "PropertyObject.h" 10 11#include <stdio.h> 12 13#include <ByteOrder.h> 14#include <Message.h> 15#include <OS.h> 16 17#include "Int64Property.h" 18#include "Property.h" 19 20#ifndef DEBUG 21# define DEBUG 0 22#endif 23 24// constructor 25PropertyObject::PropertyObject() 26 : fProperties(16) 27{ 28} 29 30// constructor 31PropertyObject::PropertyObject(const PropertyObject& other) 32 : fProperties(16) 33{ 34 Assign(other); 35} 36 37// destructor 38PropertyObject::~PropertyObject() 39{ 40 DeleteProperties(); 41} 42 43// #pragma mark - 44 45// Archive 46status_t 47PropertyObject::Archive(BMessage* into) const 48{ 49 if (!into) 50 return B_BAD_VALUE; 51 52 status_t ret = B_OK; 53 54 int32 count = CountProperties(); 55 for (int32 i = 0; i < count; i++) { 56 Property* p = PropertyAtFast(i); 57 58 unsigned id = B_HOST_TO_BENDIAN_INT32(p->Identifier()); 59 char idString[5]; 60 sprintf(idString, "%.4s", (const char*)&id); 61 idString[4] = 0; 62 63 BString value; 64 p->GetValue(value); 65 ret = into->AddString(idString, value.String()); 66 if (ret < B_OK) 67 return ret; 68 } 69 return ret; 70} 71 72// Unarchive 73status_t 74PropertyObject::Unarchive(const BMessage* archive) 75{ 76 if (!archive) 77 return B_BAD_VALUE; 78 79 SuspendNotifications(true); 80 81 int32 count = CountProperties(); 82 for (int32 i = 0; i < count; i++) { 83 Property* p = PropertyAtFast(i); 84 85 unsigned id = B_HOST_TO_BENDIAN_INT32(p->Identifier()); 86 char idString[5]; 87 sprintf(idString, "%.4s", (const char*)&id); 88 idString[4] = 0; 89 90 const char* value; 91 if (archive->FindString(idString, &value) == B_OK) 92 if (p->SetValue(value)) 93 Notify(); 94 } 95 96 SuspendNotifications(false); 97 98 return B_OK; 99} 100 101// #pragma mark - 102 103// AddProperty 104bool 105PropertyObject::AddProperty(Property* property) 106{ 107 if (!property) 108 return false; 109 110#if DEBUG 111 if (FindProperty(property->Identifier())) { 112 debugger("PropertyObject::AddProperty() -" 113 "property with same ID already here!\n"); 114 return false; 115 } 116 117 // debugging 118 if (fProperties.HasItem((void*)property)) { 119 debugger("PropertyObject::AddProperty() - property id " 120 "changed unexpectedly\n"); 121 return false; 122 } 123#endif 124 125 if (fProperties.AddItem((void*)property)) { 126 Notify(); 127 return true; 128 } 129 130 return false; 131} 132 133// PropertyAt 134Property* 135PropertyObject::PropertyAt(int32 index) const 136{ 137 return (Property*)fProperties.ItemAt(index); 138} 139 140// PropertyAtFast 141Property* 142PropertyObject::PropertyAtFast(int32 index) const 143{ 144 return (Property*)fProperties.ItemAtFast(index); 145} 146 147// CountProperties 148int32 149PropertyObject::CountProperties() const 150{ 151 return fProperties.CountItems(); 152} 153 154// #pragma mark - 155 156// FindProperty 157Property* 158PropertyObject::FindProperty(uint32 propertyID) const 159{ 160 int32 count = fProperties.CountItems(); 161 for (int32 i = 0; i < count; i++) { 162 Property* p = (Property*)fProperties.ItemAtFast(i); 163 if (p->Identifier() == propertyID) 164 return p; 165 } 166 return NULL; 167} 168 169//HasProperty 170bool 171PropertyObject::HasProperty(Property* property) const 172{ 173 return fProperties.HasItem((void*)property); 174} 175 176// ContainsSameProperties 177bool 178PropertyObject::ContainsSameProperties(const PropertyObject& other) const 179{ 180 bool equal = false; 181 int32 count = CountProperties(); 182 if (count == other.CountProperties()) { 183 equal = true; 184 for (int32 i = 0; i < count; i++) { 185 Property* ownProperty = PropertyAtFast(i); 186 Property* otherProperty = other.PropertyAtFast(i); 187 if (ownProperty->Identifier() != otherProperty->Identifier()) { 188 equal = false; 189 break; 190 } 191 } 192 } 193 return equal; 194} 195 196// Assign 197status_t 198PropertyObject::Assign(const PropertyObject& other) 199{ 200 DeleteProperties(); 201 202 int32 count = other.fProperties.CountItems(); 203 for (int32 i = 0; i < count; i++) { 204 Property* p = (Property*)other.fProperties.ItemAtFast(i); 205 Property* clone = p->Clone(); 206 if (!AddProperty(clone)) { 207 delete clone; 208 fprintf(stderr, "PropertyObject::Assign() - no memory for " 209 "cloning properties!\n"); 210 return B_NO_MEMORY; 211 } 212 } 213 214 return B_OK; 215} 216 217// DeleteProperties 218void 219PropertyObject::DeleteProperties() 220{ 221 int32 count = fProperties.CountItems(); 222 for (int32 i = 0; i < count; i++) 223 delete (Property*)fProperties.ItemAtFast(i); 224 fProperties.MakeEmpty(); 225 Notify(); 226} 227 228// DeleteProperty 229bool 230PropertyObject::DeleteProperty(uint32 propertyID) 231{ 232 int32 count = fProperties.CountItems(); 233 for (int32 i = 0; i < count; i++) { 234 Property* p = (Property*)fProperties.ItemAtFast(i); 235 if (p->Identifier() == propertyID) { 236 if (fProperties.RemoveItem(i)) { 237 Notify(); 238 delete p; 239 return true; 240 } 241 break; 242 } 243 } 244 return false; 245} 246 247// ValueChanged 248void 249PropertyObject::ValueChanged(uint32 propertyID) 250{ 251 Notify(); 252} 253 254// #pragma mark - 255 256// SetValue 257bool 258PropertyObject::SetValue(uint32 propertyID, const char* value) 259{ 260 if (Property* p = FindProperty(propertyID)) { 261 if (p->SetValue(value)) { 262 ValueChanged(propertyID); 263 return true; 264 } 265 } 266 return false; 267} 268 269// GetValue 270bool 271PropertyObject::GetValue(uint32 propertyID, BString& value) const 272{ 273 if (Property* p = FindProperty(propertyID)) { 274 p->GetValue(value); 275 return true; 276 } 277 return false; 278} 279 280// #pragma mark - int32 281 282// SetValue 283bool 284PropertyObject::SetValue(uint32 propertyID, int32 value) 285{ 286 IntProperty* p = dynamic_cast<IntProperty*>(FindProperty(propertyID)); 287 if (p && p->SetValue(value)) { 288 ValueChanged(propertyID); 289 return true; 290 } 291 return false; 292} 293 294// Value 295int32 296PropertyObject::Value(uint32 propertyID, int32 defaultValue) const 297{ 298 if (IntProperty* p = dynamic_cast<IntProperty*>(FindProperty(propertyID))) 299 return p->Value(); 300 return defaultValue; 301} 302 303// #pragma mark - int64 304 305// SetValue 306bool 307PropertyObject::SetValue(uint32 propertyID, int64 value) 308{ 309 Int64Property* p = dynamic_cast<Int64Property*>(FindProperty(propertyID)); 310 if (p && p->SetValue(value)) { 311 ValueChanged(propertyID); 312 return true; 313 } 314 return false; 315} 316 317// Value 318int64 319PropertyObject::Value(uint32 propertyID, int64 defaultValue) const 320{ 321 if (Int64Property* p = dynamic_cast<Int64Property*>(FindProperty(propertyID))) 322 return p->Value(); 323 return defaultValue; 324} 325 326// #pragma mark - float 327 328// SetValue 329bool 330PropertyObject::SetValue(uint32 propertyID, float value) 331{ 332 FloatProperty* p = dynamic_cast<FloatProperty*>(FindProperty(propertyID)); 333 if (p && p->SetValue(value)) { 334 ValueChanged(propertyID); 335 return true; 336 } 337 return false; 338} 339 340// Value 341float 342PropertyObject::Value(uint32 propertyID, float defaultValue) const 343{ 344 if (FloatProperty* p = dynamic_cast<FloatProperty*>(FindProperty(propertyID))) 345 return p->Value(); 346 return defaultValue; 347} 348 349// #pragma mark - bool 350 351// SetValue 352bool 353PropertyObject::SetValue(uint32 propertyID, bool value) 354{ 355 BoolProperty* p = dynamic_cast<BoolProperty*>(FindProperty(propertyID)); 356 if (p && p->SetValue(value)) { 357 ValueChanged(propertyID); 358 return true; 359 } 360 return false; 361} 362 363// Value 364bool 365PropertyObject::Value(uint32 propertyID, bool defaultValue) const 366{ 367 if (BoolProperty* p = dynamic_cast<BoolProperty*>(FindProperty(propertyID))) 368 return p->Value(); 369 return defaultValue; 370} 371 372 373