00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "DataSample.h"
00026
00027
00028 namespace cmlabs {
00029
00030
00031
00032
00033
00034 DataSample::DataSample(const JString& type, const JString& samplename) {
00035 id = createUniqueID();
00036 this->type = type;
00037 name = samplename;
00038 data = link = NULL;
00039 size = 0;
00040 width = height = 0;
00041 duration = 0;
00042 object = NULL;
00043 aux = NULL;
00044 markedForDeletion = false;
00045 sortfield = 0;
00046 channels = NULL;
00047 }
00048
00049 DataSample::DataSample(XMLNode* node) {
00050 id = createUniqueID();
00051 data = link = NULL;
00052 size = 0;
00053 width = height = 0;
00054 duration = 0;
00055 object = NULL;
00056 aux = NULL;
00057 markedForDeletion = false;
00058 sortfield = 0;
00059 channels = NULL;
00060 fromXML(node);
00061 }
00062
00063 DataSample::~DataSample() {
00064 markForDeletion();
00065
00066 if (data != NULL)
00067 delete [] data;
00068 data = NULL;
00069 if (object != NULL)
00070 delete(object);
00071 object = NULL;
00072 if (aux != NULL)
00073 delete(aux);
00074 aux = NULL;
00075
00076 params.removeAll();
00077 link = NULL;
00078 size = 0;
00079 width = 0;
00080 height = 0;
00081 }
00082
00083 bool DataSample::equals(const Object* o2) const {
00084 if (o2 == NULL) return false;
00085 if (!this->isSameClass(o2)) {
00086 return false;
00087 }
00088 return this->equals(*(DataSample*)o2);
00089 }
00090
00091
00092 bool DataSample::equals( const DataSample &s2 ) const {
00093 return ( this->sortfield == s2.sortfield );
00094 }
00095
00096 int DataSample::compare(const Object* o2) const {
00097 if ((o2 == NULL) || (!isSameClass(o2)))
00098 return 0;
00099 return compareTo(*(DataSample*) o2);
00100 }
00101
00102 int DataSample::compareTo( const DataSample &s2 ) const {
00103 if (this->sortfield == s2.sortfield)
00104 return 0;
00105 return (this->sortfield > s2.sortfield ? 1 : -1);
00106 }
00107
00108 JString DataSample::getType() {
00109 return type;
00110 }
00111
00112 bool DataSample::setType(const JString& type) {
00113 this->type = type;
00114 return true;
00115 }
00116
00117
00118 unsigned long DataSample::getPayloadSize() const {
00119 long payloadSize = id.length() + name.length() + type.length() + size +
00120 timestamp.getPayloadSize() + params.getPayloadSize();
00121
00122 if (channels != NULL) payloadSize += channels->getPayloadSize();
00123 if (object != NULL) payloadSize += object->getPayloadSize();
00124 if (aux != NULL) payloadSize += aux->getPayloadSize();
00125
00126 return payloadSize;
00127 }
00128
00129 Object* DataSample::clone() const {
00130 DataSample* sample = new DataSample();
00131 sample->name = name;
00132 sample->id = id;
00133 sample->type = type;
00134 sample->width = width;
00135 sample->height = height;
00136 sample->timestamp = timestamp;
00137 sample->params.copyAll(params);
00138 if (data != NULL)
00139 sample->setDataCopy(data, size, duration);
00140 if (object != NULL) {
00141 sample->setObject(object->clone());
00142 sample->setDuration(duration);
00143 }
00144 return (Object*) sample;
00145 }
00146
00147 DataSample* DataSample::cloneWithoutData() {
00148 DataSample* sample = new DataSample();
00149 sample->name = name;
00150 sample->timestamp = timestamp;
00151 sample->params.copyAll(params);
00152 sample->width = width;
00153 sample->height = height;
00154 sample->size = size;
00155 sample->duration = duration;
00156 return sample;
00157 }
00158
00159 JString DataSample::print() {
00160 if (object != NULL)
00161 return JString::format("%s: Object: %s %s", (char*) name, (char*) object->getClass(), (char*) timestamp.print());
00162 else
00163 return JString::format("%s: %d bytes %s", (char*) name, getDataSize(), (char*) timestamp.print());
00164 }
00165
00166
00167 bool DataSample::clearDataFields() {
00168 data = link = NULL;
00169 size = 0;
00170 if (object != NULL)
00171 delete(object);
00172 object = NULL;
00173 return true;
00174 }
00175
00176 bool DataSample::isLocked() {
00177 return (lockedBy.length() > 0);
00178 }
00179
00180 bool DataSample::lockBy(const JString& locker) {
00181 if (isLocked())
00182 return false;
00183 lockedBy = locker;
00184 return true;
00185 }
00186
00187 bool DataSample::isInUse() {
00188 if (users.getCount() == 0)
00189 return false;
00190
00191 Collection removes;
00192 JTime* t;
00193 JTime now;
00194 int n;
00195 for (n=0; n<users.getCount(); n++) {
00196 if ( (t = (JTime*) users.get(n)) != NULL ) {
00197 if (t->microDifference(now) < 0) {
00198 removes.add(users.getKey(n));
00199 }
00200 }
00201 }
00202 for (n=0; n<removes.getCount(); n++) {
00203
00204 users.remove(removes.get(n));
00205 }
00206
00207 if (users.getCount() > 0) {
00208
00209
00210 return true;
00211 }
00212 else
00213 return false;
00214 }
00215
00216 bool DataSample::setInUseBy(const JString& user, int timeout) {
00217 JTime t;
00218 if (timeout > 0)
00219 t = t + timeout;
00220 else
00221 t = t + 1000*20;
00222 users.put(user, t.clone());
00223
00224
00225
00226 return true;
00227 }
00228
00229 bool DataSample::removeInUseBy(const JString& user) {
00230 return users.remove(user);
00231 }
00232
00233
00234 JString DataSample::getName() {
00235 return name;
00236 }
00237
00238 JTime DataSample::getTimestamp() {
00239 return timestamp;
00240 }
00241
00242 JTime DataSample::getStartTime() {
00243 return timestamp;
00244 }
00245
00246 JTime DataSample::getEndTime() {
00247 return (timestamp + duration);
00248 }
00249
00250 Dictionary DataSample::getAllParameters() {
00251 return params;
00252 }
00253
00254 long DataSample::getDataMemUse() {
00255 if (link != NULL)
00256 return 0;
00257 else
00258 return size;
00259 }
00260
00261 long DataSample::getDataSize() {
00262 return size;
00263 }
00264
00265 char* DataSample::getDataLink() {
00266 if (size <= 0)
00267 return NULL;
00268 if (link != NULL)
00269 return link;
00270 else
00271 return data;
00272 }
00273
00274 char* DataSample::getDataCopy() {
00275 char* dat = getDataLink();
00276 if (dat == NULL)
00277 return NULL;
00278 char* copy = new char[size];
00279 memcpy(copy, dat, size);
00280 return copy;
00281 }
00282
00283
00284 JString DataSample::getParam(const JString& param) {
00285 return params.get(param);
00286 }
00287
00288
00289 int DataSample::getParamInt(const JString& param) {
00290 return params.get(param).toInt();
00291 }
00292
00293 double DataSample::getParamFloat(const JString& param) {
00294 return params.get(param).toDouble();
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 bool DataSample::setParam(const JString& param, const JString& value) {
00309 return params.put(param, value);
00310 }
00311
00312 bool DataSample::setParamInt(const JString& param, int value) {
00313 return params.put(param, JString(value));
00314 }
00315
00316 bool DataSample::setParamFloat(const JString& param, double value) {
00317 return params.put(param, JString(value));
00318 }
00319
00320 bool DataSample::setTimestamp(const JTime& time) {
00321 timestamp = time;
00322 return true;
00323 }
00324
00325 bool DataSample::setParameters(Dictionary& dict) {
00326 return params.copyAll(dict);
00327 }
00328
00329 bool DataSample::giveData(char* sampledata, long datasize, long durationMS) {
00330 if ( (datasize <= 0) || (sampledata == NULL) )
00331 return false;
00332
00333 if (data != NULL)
00334 delete [] data;
00335 data = NULL;
00336 if (object != NULL)
00337 delete(object);
00338 object = NULL;
00339
00340 size = datasize;
00341 data = sampledata;
00342 link = NULL;
00343 duration = durationMS;
00344 return true;
00345 }
00346
00347 bool DataSample::setDataCopy(char* sampledata, long datasize, long durationMS) {
00348 if ( (datasize <= 0) || (sampledata == NULL) )
00349 return false;
00350
00351 if (data != NULL)
00352 delete [] data;
00353 data = NULL;
00354 if (object != NULL)
00355 delete(object);
00356 object = NULL;
00357
00358 char* copy = new char[datasize];
00359 memcpy(copy, sampledata, datasize);
00360 return giveData(copy, datasize, durationMS);
00361 }
00362
00363 bool DataSample::setDataLink(char* sampledata, long datasize, long durationMS) {
00364 if ( (datasize <= 0) || (sampledata == NULL) )
00365 return false;
00366
00367 if (data != NULL)
00368 delete [] data;
00369 data = NULL;
00370 if (object != NULL)
00371 delete(object);
00372 object = NULL;
00373
00374 size = datasize;
00375 link = sampledata;
00376 data = NULL;
00377 duration = durationMS;
00378 return true;
00379 }
00380
00381 long DataSample::getDuration() {
00382 return duration;
00383 }
00384
00385 bool DataSample::setDuration(long durationMS) {
00386 duration = durationMS;
00387 return true;
00388 }
00389
00390 int DataSample::getWidth() {
00391 return width;
00392 }
00393
00394 int DataSample::getHeight() {
00395 return height;
00396 }
00397
00398 bool DataSample::setWidth(int w) {
00399 width = w;
00400 return true;
00401 }
00402
00403 bool DataSample::setHeight(int h) {
00404 height = h;
00405 return true;
00406 }
00407
00408
00409 Object* DataSample::getObject() {
00410 return object;
00411 }
00412
00413 bool DataSample::setObject(Object* obj) {
00414 if (object != NULL)
00415 delete(object);
00416 if (data != NULL)
00417 delete [] data;
00418 data = NULL;
00419 link = NULL;
00420 size = 0;
00421 object = obj;
00422 type = "Object";
00423 return true;
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433 long DataSample::getBinarySize(int chunk) {
00434
00435 if (chunk > 0) {
00436 if (object != NULL)
00437 return object->getBinarySize(chunk-1);
00438 else
00439 return 0;
00440 }
00441
00442 params.put("builtin:id", id);
00443 params.put("builtin:type", type);
00444 params.put("builtin:duration", JString(duration));
00445 params.put("builtin:timestamp", timestamp.asText());
00446 params.put("builtin:name", name);
00447 params.put("builtin:width", JString(width));
00448 params.put("builtin:height", JString(height));
00449 JString extra = params.printListLine("%sep%", "%equals%");
00450
00451 long objectSize = 0;
00452 if (object != NULL)
00453 objectSize = object->toXML().length()+1;
00454 return (4 + size + extra.length()+1 + objectSize);
00455
00456
00457
00458
00459
00460
00461 }
00462
00463
00464 int DataSample::getBinaryChunkCount() {
00465 if (object != NULL)
00466 return 1 + object->getBinaryChunkCount();
00467 else
00468 return 1;
00469 }
00470
00471 long DataSample::toBinaryBuffer(int chunk, char* buffer, int maxlen) {
00472
00473 if (chunk > 0) {
00474 if (object != NULL)
00475 return object->toBinaryBuffer(chunk-1, buffer, maxlen);
00476 else
00477 return 0;
00478 }
00479
00480 params.put("builtin:id", id);
00481 params.put("builtin:type", type);
00482 params.put("builtin:duration", JString(duration));
00483 params.put("builtin:timestamp", timestamp.asText());
00484 params.put("builtin:name", name);
00485 params.put("builtin:width", JString(width));
00486 params.put("builtin:height", JString(height));
00487
00488 JString extra = params.printListLine("%sep%", "%equals%");
00489
00490 char* ptr;
00491 JString xml;
00492 if (object != NULL) {
00493 xml = object->toXML();
00494 size = xml.length() + 1;
00495 ptr = (char*) xml;
00496 }
00497 else
00498 ptr = getDataLink();
00499
00500 long len = 4 + size + extra.length()+1;
00501 if (len > maxlen)
00502 return 0;
00503
00504 writeLongToBytes(buffer, size);
00505
00506 if ((ptr != NULL) && (size > 0))
00507 memcpy(buffer+4, ptr, size);
00508 memcpy(buffer+4+size, extra.charpoint(), extra.length()+1);
00509
00510 if (object != NULL) {
00511 size = 0;
00512 }
00513
00514 return len;
00515 }
00516
00517 bool DataSample::fromBinaryBuffer(int chunk, char* buffer, long len) {
00518
00519 if (chunk > 0) {
00520 if (object != NULL)
00521 return object->fromBinaryBuffer(chunk-1, buffer, len);
00522 else
00523 return false;
00524 }
00525
00526 if ((buffer == NULL) || (len <= 0))
00527 return false;
00528
00529 long binsize = getLongFromBytes(buffer);
00530
00531 JString extra = (char*)(buffer + 4 + binsize);
00532 if (extra.length() == 0)
00533 return false;
00534 params = extra.split("%sep%", "%equals%");
00535 if (params.getCount() < 3)
00536 return false;
00537
00538 long dur = params.get("builtin:duration").toLong();
00539 timestamp = JTime(params.get("builtin:timestamp"));
00540 id = params.get("builtin:id");
00541 type = params.get("builtin:type");
00542 name = params.get("builtin:name");
00543 width = params.get("builtin:width").toInt();
00544 height = params.get("builtin:height").toInt();
00545 params.remove("builtin:duration");
00546 params.remove("builtin:timestamp");
00547 params.remove("builtin:id");
00548 params.remove("builtin:type");
00549 params.remove("builtin:name");
00550 params.remove("builtin:width");
00551 params.remove("builtin:height");
00552
00553 if (binsize > 0)
00554 if (type.equalsIgnoreCase("Object")) {
00555 JString xml = (char*)(buffer + 4);
00556 duration = dur;
00557 return (this->setObject(Object::createObjectFromXML(xml)));
00558 }
00559 else
00560 return (this->setDataCopy(buffer + 4, binsize, dur));
00561 else {
00562 duration = dur;
00563 return true;
00564 }
00565 }
00566
00567
00568
00569
00570 long DataSample::getLongFromBytes(char* buffer) {
00571 long val = ( (unsigned char) buffer[0] + ( (unsigned char) buffer[1] << 8) + ( (unsigned char) buffer[2] << 16) + ( (unsigned char) buffer[3] << 24) );
00572
00573
00574 return val;
00575 }
00576
00577 bool DataSample::writeLongToBytes(char* buffer, long val) {
00578 buffer[0] = (unsigned char) val;
00579 buffer[1] = (unsigned char) (val >> 8);
00580 buffer[2] = (unsigned char) (val >> 16);
00581 buffer[3] = (unsigned char) (val >> 24);
00582 return true;
00583 }
00584
00585
00586
00587
00588 bool DataSample::readFromFile(const JString& filename) {
00589 int len;
00590 char* dat = JFile::readAFileBinary(filename, len);
00591 if (dat == NULL)
00592 return false;
00593 this->giveData(dat, len);
00594 return true;
00595 }
00596
00597 bool DataSample::writeToFile(const JString& filename) {
00598 if ( (data == NULL) || (size <= 0) )
00599 return false;
00600 return JFile::writeAFileBinary(filename, this->data, this->size);
00601 }
00602
00603
00604
00605 bool DataSample::markForDeletion() {
00606 markedForDeletion = true;
00607 if (channels != NULL) {
00608 channels->removeAllNoDelete();
00609 delete(channels);
00610 channels = NULL;
00611 }
00612 return true;
00613 }
00614
00615 bool DataSample::isMarkedForDeletion() {
00616 return markedForDeletion;
00617 }
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 HTMLPage* DataSample::toHTMLBitmap() {
00640 return NULL;
00641 }
00642
00643 JString DataSample::toHTML() {
00644 return JString::format("DataSample size %d bytes, time %s", size, (char*) timestamp.print());
00645 }
00646
00647
00648 JString DataSample::toXML() {
00649 return "<datasample />";
00650
00651
00652 }
00653
00654 bool DataSample::fromXML(XMLNode* node) {
00655
00656 if (node == NULL)
00657 return false;
00658
00659 if (!node->getTag().equalsIgnoreCase("datasample"))
00660 return false;
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 return true;
00685 }
00686
00687
00688 bool DataSample::unitTest() {
00689
00690
00691 ObjectDictionary* mainCol = new ObjectDictionary();
00692
00693 DataSample* sample;
00694 ObjectDictionary* subCol;
00695 char* data;
00696 int len = 100;
00697 int nMax = 3;
00698 int mMax = 3;
00699 Collection expectedSizes;
00700
00701 for (int n=0; n<nMax; n++) {
00702 subCol = new ObjectDictionary();
00703
00704 for (int m=0; m<mMax; m++) {
00705 data = new char[len*(m+1)];
00706 memset(data, m, len);
00707 sample = new DataSample();
00708 sample->giveData(data, len);
00709 expectedSizes.add(JString(sample->getBinarySize(0)));
00710 subCol->put(JString(m), sample);
00711 }
00712 mainCol->put(JString(n), subCol);
00713 }
00714
00715 int chunks = mainCol->getBinaryChunkCount();
00716 if (chunks != nMax * mMax) {
00717 this->addUnitTestLog(JString::format("Collection::getBinaryChunkCount() should be %d, was %d!", nMax * mMax, chunks));
00718 return false;
00719 }
00720
00721 long size, totalSize = 0;
00722 for (int e=0; e<expectedSizes.getCount(); e++) {
00723 size = mainCol->getBinarySize(e);
00724 if (size != expectedSizes.get(e).toLong()) {
00725 this->addUnitTestLog(JString::format("Collection::getBinarySize(%d) should be %ld, was %ld!",
00726 e, expectedSizes.get(e).toLong(), size));
00727 return false;
00728 }
00729 totalSize += size;
00730 }
00731
00732 int c;
00733 long pos = 0, delta;
00734 data = new char[totalSize];
00735 for (c=0; c<chunks; c++) {
00736 delta = mainCol->toBinaryBuffer(c, data+pos, expectedSizes.get(c).toLong());
00737 pos += delta;
00738 }
00739
00740 if (pos != totalSize) {
00741 this->addUnitTestLog(JString::format("Collection::toBinaryBuffer() should be %ld, was %ld!",
00742 totalSize, pos));
00743 return false;
00744 }
00745
00746 JString xml = mainCol->toXML();
00747
00748 ObjectDictionary* copyCol = new ObjectDictionary(xml);
00749
00750 int copyChunks = mainCol->getBinaryChunkCount();
00751 if (copyChunks != nMax * mMax) {
00752 this->addUnitTestLog(JString::format("Copy of Collection::getBinaryChunkCount() should be %d, was %d!", nMax * mMax, copyChunks));
00753 return false;
00754 }
00755
00756 pos = 0;
00757 for (c=0; c<copyChunks; c++) {
00758 if (!copyCol->fromBinaryBuffer(c, data+pos, expectedSizes.get(c).toLong())) {
00759 this->addUnitTestLog(JString::format("Collection::fromBinaryBuffer(%d) failed!", c));
00760 return false;
00761 }
00762 pos += expectedSizes.get(c).toLong();
00763 }
00764
00765 c = 0;
00766 for (int nn=0; nn<nMax; nn++) {
00767 if ( (subCol = (ObjectDictionary*)copyCol->get(nn)) == NULL) {
00768 this->addUnitTestLog(JString::format("Copy Collection did not contain subCol %d!", nn));
00769 return false;
00770 }
00771 if (subCol->getCount() != mMax) {
00772 this->addUnitTestLog(JString::format("Copy Sub Collection %d had count %, should have been %d!", nn, subCol->getCount(), mMax));
00773 return false;
00774 }
00775
00776 for (int mm=0; mm<mMax; mm++) {
00777 if ( (sample = (DataSample*) subCol->get(mm)) == NULL) {
00778 this->addUnitTestLog(JString::format("Copy Sub Collection %d did not contain sample %d!", nn, mm));
00779 return false;
00780 }
00781
00782 if (sample->data == NULL) {
00783 this->addUnitTestLog(JString::format("Copy Sub Collection %d sample %d has no data!", nn, mm));
00784 return false;
00785 }
00786
00787 long binsize = sample->getBinarySize(0);
00788 if (binsize != expectedSizes.get(c).toLong()) {
00789 this->addUnitTestLog(JString::format("Copy Sub Collection %d sample %d had size %ld, should have been %ld!", nn, mm, binsize, expectedSizes.get(c).toLong()));
00790 return false;
00791 }
00792 c++;
00793 }
00794 }
00795
00796 delete(mainCol);
00797 delete(subCol);
00798 delete [] data;
00799
00800 return true;
00801 }
00802
00803
00804 }