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 25 PropertyObject::PropertyObject() 26 : fProperties(16) 27 { 28 } 29 30 // constructor 31 PropertyObject::PropertyObject(const PropertyObject& other) 32 : fProperties(16) 33 { 34 Assign(other); 35 } 36 37 // destructor 38 PropertyObject::~PropertyObject() 39 { 40 DeleteProperties(); 41 } 42 43 // #pragma mark - 44 45 // Archive 46 status_t 47 PropertyObject::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 73 status_t 74 PropertyObject::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 104 bool 105 PropertyObject::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 134 Property* 135 PropertyObject::PropertyAt(int32 index) const 136 { 137 return (Property*)fProperties.ItemAt(index); 138 } 139 140 // PropertyAtFast 141 Property* 142 PropertyObject::PropertyAtFast(int32 index) const 143 { 144 return (Property*)fProperties.ItemAtFast(index); 145 } 146 147 // CountProperties 148 int32 149 PropertyObject::CountProperties() const 150 { 151 return fProperties.CountItems(); 152 } 153 154 // #pragma mark - 155 156 // FindProperty 157 Property* 158 PropertyObject::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 170 bool 171 PropertyObject::HasProperty(Property* property) const 172 { 173 return fProperties.HasItem((void*)property); 174 } 175 176 // ContainsSameProperties 177 bool 178 PropertyObject::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 197 status_t 198 PropertyObject::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 218 void 219 PropertyObject::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 229 bool 230 PropertyObject::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 248 void 249 PropertyObject::ValueChanged(uint32 propertyID) 250 { 251 Notify(); 252 } 253 254 // #pragma mark - 255 256 // SetValue 257 bool 258 PropertyObject::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 270 bool 271 PropertyObject::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 283 bool 284 PropertyObject::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 295 int32 296 PropertyObject::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 306 bool 307 PropertyObject::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 318 int64 319 PropertyObject::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 329 bool 330 PropertyObject::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 341 float 342 PropertyObject::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 352 bool 353 PropertyObject::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 364 bool 365 PropertyObject::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