• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

akregator

store.cpp

Go to the documentation of this file.
00001 // store.cpp --
00002 // $Id: store.cpp 789251 2008-03-23 19:01:07Z osterfeld $
00003 // This is part of Metakit, the homepage is http://www.equi4.com/metakit.html
00004 
00009 #include "header.h"
00010 #include "handler.h"  // 19990906
00011 #include "store.h"
00012 #include "field.h"
00013 #include "persist.h"
00014 #include "format.h"   // 19990906
00015 
00016 #include "mk4io.h"    // 19991104
00017 
00018 #if !q4_INLINE
00019 #include "store.inl"
00020 #endif 
00021 
00023 
00024 c4_Dependencies::c4_Dependencies() {
00025   _refs.SetSize(0, 3); // a little optimization
00026 }
00027 
00028 c4_Dependencies::~c4_Dependencies(){}
00029 
00030 void c4_Dependencies::Add(c4_Sequence *seq_) {
00031   for (int i = 0; i < _refs.GetSize(); ++i)
00032     d4_assert(_refs.GetAt(i) != seq_);
00033 
00034   _refs.Add(seq_);
00035 }
00036 
00037 bool c4_Dependencies::Remove(c4_Sequence *seq_) {
00038   int n = _refs.GetSize() - 1;
00039   d4_assert(n >= 0);
00040 
00041   for (int i = 0; i <= n; ++i)
00042   if (_refs.GetAt(i) == seq_) {
00043     _refs.SetAt(i, _refs.GetAt(n));
00044     _refs.SetSize(n);
00045     return n > 0;
00046   }
00047 
00048   d4_assert(0); // dependency not found
00049   return true;
00050 }
00051 
00053 
00054 c4_Notifier::~c4_Notifier() {
00055   if (_type > kNone && _origin->GetDependencies()) {
00056     c4_PtrArray &refs = _origin->GetDependencies()->_refs;
00057 
00058     for (int i = 0; i < refs.GetSize(); ++i) {
00059       c4_Sequence *seq = (c4_Sequence*)refs.GetAt(i);
00060       d4_assert(seq != 0);
00061 
00062       seq->PostChange(*this);
00063 
00064       if (_chain && _chain->_origin == seq) {
00065         c4_Notifier *next = _chain->_next;
00066         _chain->_next = 0;
00067 
00068         delete _chain;
00069 
00070         _chain = next;
00071       }
00072     }
00073   }
00074 
00075   d4_assert(!_chain);
00076   d4_assert(!_next);
00077 }
00078 
00079 void c4_Notifier::StartSetAt(int index_, c4_Cursor &cursor_) {
00080   _type = kSetAt;
00081   _index = index_;
00082   _cursor = &cursor_;
00083 
00084   Notify();
00085 }
00086 
00087 void c4_Notifier::StartInsertAt(int i_, c4_Cursor &cursor_, int n_) {
00088   _type = kInsertAt;
00089   _index = i_;
00090   _cursor = &cursor_;
00091   _count = n_;
00092 
00093   Notify();
00094 }
00095 
00096 void c4_Notifier::StartRemoveAt(int index_, int count_) {
00097   _type = kRemoveAt;
00098   _index = index_;
00099   _count = count_;
00100 
00101   Notify();
00102 }
00103 
00104 void c4_Notifier::StartMove(int from_, int to_) {
00105   _type = kMove;
00106   _index = from_;
00107   _count = to_;
00108 
00109   Notify();
00110 }
00111 
00112 void c4_Notifier::StartSet(int i_, int propId_, const c4_Bytes &buf_) {
00113   _type = kSet;
00114   _index = i_;
00115   _propId = propId_;
00116   _bytes = &buf_;
00117 
00118   Notify();
00119 }
00120 
00121 void c4_Notifier::Notify() {
00122   d4_assert(_origin->GetDependencies() != 0);
00123   c4_PtrArray &refs = _origin->GetDependencies()->_refs;
00124 
00125   int n = refs.GetSize();
00126   d4_assert(n > 0);
00127 
00128   c4_Notifier **rover = &_chain;
00129 
00130   for (int i = 0; i < n; ++i) {
00131     c4_Sequence *seq = (c4_Sequence*)refs.GetAt(i);
00132     d4_assert(seq != 0);
00133 
00134     c4_Notifier *ptr = seq->PreChange(*this);
00135     if (ptr) {
00136       d4_assert(ptr->_origin == seq);
00137 
00138       d4_assert(! *rover);
00139       *rover = ptr;
00140       rover = &ptr->_next;
00141     }
00142   }
00143 }
00144 
00146 
00186 c4_Storage::c4_Storage() {
00187   // changed to r/o, now that commits don't crash on it anymore
00188   Initialize(*d4_new c4_Strategy, true, 0);
00189 }
00190 
00191 c4_Storage::c4_Storage(c4_Strategy &strategy_, bool owned_, int mode_) {
00192   Initialize(strategy_, owned_, mode_);
00193   Persist()->LoadAll();
00194 }
00195 
00196 c4_Storage::c4_Storage(const char *fname_, int mode_) {
00197   c4_FileStrategy *strat = d4_new c4_FileStrategy;
00198   strat->DataOpen(fname_, mode_);
00199 
00200   Initialize(*strat, true, mode_);
00201   if (strat->IsValid())
00202     Persist()->LoadAll();
00203 }
00204 
00205 c4_Storage::c4_Storage(const c4_View &root_) {
00206   if (root_.Persist() != 0)
00207   // only restore if view was indeed persistent
00208     *(c4_View*)this = root_;
00209   else
00210   // if this was not possible, start with a fresh empty storage
00211     Initialize(*d4_new c4_Strategy, true, 0);
00212 }
00213 
00214 c4_Storage::~c4_Storage() {
00215   // cannot unmap here, because there may still be an autocommit pending
00216   //((c4_HandlerSeq*) _seq)->UnmapAll();
00217 }
00218 
00219 void c4_Storage::Initialize(c4_Strategy &strategy_, bool owned_, int mode_) {
00220   c4_Persist *pers = d4_new c4_Persist(strategy_, owned_, mode_);
00221   c4_HandlerSeq *seq = d4_new c4_HandlerSeq(pers);
00222   seq->DefineRoot();
00223   *(c4_View*)this = seq;
00224   pers->SetRoot(seq);
00225 }
00226 
00228 c4_ViewRef c4_Storage::View(const char *name_) {
00229   /*
00230   The easy solution would seem to be:
00231 
00232   c4_ViewProp prop (name_);
00233   return prop (Contents());
00234 
00235   But this does not work, because the return value would point to
00236   an object allocated on the stack.
00237 
00238   Instead, make sure the view *has* such a property, and use the
00239   one inside the c4_Handler for it (since this will stay around).
00240    */
00241 
00242   //  int n = _root->PropIndex(c4_ViewProp (name_));
00243 
00244   c4_ViewProp prop(name_);
00245   int n = AddProperty(prop);
00246   d4_assert(n >= 0);
00247 
00248   // the following is an expression of the form "property (rowref)"
00249   return NthProperty(n)(GetAt(0));
00250 }
00251 
00253 c4_View c4_Storage::GetAs(const char *description_) {
00254   d4_assert(description_ != 0);
00255 
00256   // Dec 2001: now that GetAs is being used so much more frequently, 
00257   // add a quick check to see whether restructuring is needed at all
00258   const char *q = strchr(description_, '[');
00259   if (q != 0) {
00260     c4_String vname(description_, q - description_);
00261     const char *d = Description(vname);
00262     if (d != 0) {
00263       c4_String desc(d);
00264       if (("[" + desc + "]").CompareNoCase(q) == 0)
00265         return View(vname);
00266     }
00267   }
00268 
00269   c4_Field *field = d4_new c4_Field(description_);
00270   d4_assert(field != 0);
00271 
00272   d4_assert(! *description_);
00273 
00274   c4_String name = field->Name();
00275   d4_assert(!name.IsEmpty());
00276 
00277   c4_Field &curr = Persist()->Root().Definition();
00278 
00279   c4_String newField = "," + field->Description();
00280   bool keep = newField.Find('[') >= 0;
00281 
00282   c4_String newDef;
00283 
00284   // go through all subfields
00285   for (int i = 0; i < curr.NumSubFields(); ++i) {
00286     c4_Field &of = curr.SubField(i);
00287     if (of.Name().CompareNoCase(name) == 0) {
00288       if (field->IsRepeating())
00289         newDef += newField;
00290       // else new is not a repeating entry, so drop this entire field
00291 
00292       newField.Empty(); // don't append it later on
00293       continue;
00294     }
00295 
00296     newDef += "," + of.Description(); // keep original field
00297   }
00298 
00299   if (keep)
00300   // added 19990824 ignore if deletion
00301     newDef += newField;
00302   // appends new definition if not found earlier
00303 
00304   delete field;
00305 
00306   const char *p = newDef;
00307   SetStructure(*p ? ++p: p); // skip the leading comma
00308 
00309   if (!keep)
00310   // 19990916: avoid adding an empty view again
00311     return c4_View();
00312 
00313   return View(name);
00314 }
00315 
00317 void c4_Storage::SetStructure(const char *description_) {
00318   d4_assert(description_ != 0);
00319 
00320   if (description_ != Description()) {
00321     c4_String s = "[" + c4_String(description_) + "]";
00322     description_ = s;
00323 
00324     c4_Field *field = d4_new c4_Field(description_);
00325     d4_assert(! *description_);
00326 
00327     d4_assert(field != 0);
00328     Persist()->Root().Restructure(*field, false);
00329   }
00330 }
00331 
00333 c4_Strategy &c4_Storage::Strategy()const {
00334   return Persist()->Strategy();
00335 }
00336 
00338 const char *c4_Storage::Description(const char *name_) {
00339   if (name_ == 0 ||  *name_ == 0)
00340     return c4_View::Description();
00341 
00342   c4_View v = View(name_);
00343   return v.Description();
00344 }
00345 
00347 bool c4_Storage::SetAside(c4_Storage &aside_) {
00348   c4_Persist *pers = Persist();
00349   bool f = pers->SetAside(aside_);
00350   // adjust our copy when the root view has been replaced
00351   *(c4_View*)this = &pers->Root();
00352   return f;
00353 }
00354 
00356 c4_Storage *c4_Storage::GetAside()const {
00357   return Persist()->GetAside();
00358 }
00359 
00361 bool c4_Storage::Commit(bool full_) {
00362   return Strategy().IsValid() && Persist()->Commit(full_);
00363 }
00364 
00369 bool c4_Storage::Rollback(bool full_) {
00370   c4_Persist *pers = Persist();
00371   bool f = Strategy().IsValid() && pers->Rollback(full_);
00372   // adjust our copy when the root view has been replaced
00373   *(c4_View*)this = &pers->Root();
00374   return f;
00375 }
00376 
00378 bool c4_Storage::AutoCommit(bool flag_) {
00379   return Persist()->AutoCommit(flag_);
00380 }
00381 
00383 bool c4_Storage::LoadFrom(c4_Stream &stream_) {
00384   c4_HandlerSeq *newRoot = c4_Persist::Load(&stream_);
00385   if (newRoot == 0)
00386     return false;
00387 
00388   // fix commit-after-load bug, by using a full view copy
00389   // this is inefficient, but avoids mapping/strategy problems
00390   c4_View temp(newRoot);
00391 
00392   SetSize(0);
00393   SetStructure(temp.Description());
00394   InsertAt(0, temp);
00395 
00396   return true;
00397 }
00398 
00400 void c4_Storage::SaveTo(c4_Stream &stream_) {
00401   c4_Persist::Save(&stream_, Persist()->Root());
00402 }
00403 
00404 t4_i32 c4_Storage::FreeSpace(t4_i32 *bytes_) {
00405   return Persist()->FreeBytes(bytes_);
00406 }
00407 
00409 
00410 c4_DerivedSeq::c4_DerivedSeq(c4_Sequence &seq_): _seq(seq_) {
00411   _seq.Attach(this);
00412 }
00413 
00414 c4_DerivedSeq::~c4_DerivedSeq() {
00415   _seq.Detach(this);
00416 }
00417 
00418 int c4_DerivedSeq::RemapIndex(int index_, const c4_Sequence *seq_)const {
00419   return seq_ == this ? index_ : _seq.RemapIndex(index_, seq_);
00420 }
00421 
00422 int c4_DerivedSeq::NumRows()const {
00423   return _seq.NumRows();
00424 }
00425 
00426 int c4_DerivedSeq::NumHandlers()const {
00427   return _seq.NumHandlers();
00428 }
00429 
00430 c4_Handler &c4_DerivedSeq::NthHandler(int colNum_)const {
00431   return _seq.NthHandler(colNum_);
00432 }
00433 
00434 const c4_Sequence *c4_DerivedSeq::HandlerContext(int colNum_)const {
00435   return _seq.HandlerContext(colNum_);
00436 }
00437 
00438 int c4_DerivedSeq::AddHandler(c4_Handler *handler_) {
00439   return _seq.AddHandler(handler_);
00440 }
00441 
00442 c4_Handler *c4_DerivedSeq::CreateHandler(const c4_Property &prop_) {
00443   return _seq.CreateHandler(prop_);
00444 }
00445 
00446 void c4_DerivedSeq::SetNumRows(int size_) {
00447   _seq.SetNumRows(size_);
00448 }
00449 
00450 c4_Notifier *c4_DerivedSeq::PreChange(c4_Notifier &nf_) {
00451   if (!GetDependencies())
00452     return 0;
00453 
00454   c4_Notifier *chg = d4_new c4_Notifier(this);
00455 
00456   switch (nf_._type) {
00457     case c4_Notifier::kSetAt: chg->StartSetAt(nf_._index,  *nf_._cursor);
00458     break;
00459 
00460     case c4_Notifier::kSet: chg->StartSet(nf_._index, nf_._propId,  *nf_._bytes)
00461       ;
00462     break;
00463 
00464     case c4_Notifier::kInsertAt: chg->StartInsertAt(nf_._index,  *nf_._cursor,
00465       nf_._count);
00466     break;
00467 
00468     case c4_Notifier::kRemoveAt: chg->StartRemoveAt(nf_._index, nf_._count);
00469     break;
00470 
00471     case c4_Notifier::kMove: chg->StartMove(nf_._index, nf_._count);
00472     break;
00473   }
00474 
00475   return chg;
00476 }
00477 
00479 
00480 c4_StreamStrategy::c4_StreamStrategy(t4_i32 buflen_): _stream(0), _buffer
00481   (d4_new t4_byte[buflen_]), _buflen(buflen_), _position(0) {
00482   _mapStart = _buffer;
00483   _dataSize = buflen_;
00484 }
00485 
00486 c4_StreamStrategy::c4_StreamStrategy(c4_Stream *stream_): _stream(stream_),
00487   _buffer(0), _buflen(0), _position(0){}
00488 
00489 c4_StreamStrategy::~c4_StreamStrategy() {
00490   _mapStart = 0;
00491   _dataSize = 0;
00492 
00493   if (_buffer != 0)
00494     delete [] _buffer;
00495 }
00496 
00497 bool c4_StreamStrategy::IsValid()const {
00498   return true;
00499 }
00500 
00501 int c4_StreamStrategy::DataRead(t4_i32 pos_, void *buffer_, int length_) {
00502   if (_buffer != 0) {
00503     d4_assert(pos_ <= _buflen);
00504     _position = pos_ + _baseOffset;
00505 
00506     if (length_ > _buflen - _position)
00507       length_ = _buflen - _position;
00508     if (length_ > 0)
00509       memcpy(buffer_, _buffer + _position, length_);
00510   } else {
00511     d4_assert(_position == pos_ + _baseOffset);
00512     length_ = _stream != 0 ? _stream->Read(buffer_, length_): 0;
00513   }
00514 
00515   _position += length_;
00516   return length_;
00517 }
00518 
00519 void c4_StreamStrategy::DataWrite(t4_i32 pos_, const void *buffer_, int length_)
00520   {
00521   if (_buffer != 0) {
00522     d4_assert(pos_ <= _buflen);
00523     _position = pos_ + _baseOffset;
00524 
00525     int n = length_;
00526     if (n > _buflen - _position)
00527       n = _buflen - _position;
00528     if (n > 0)
00529       memcpy(_buffer + _position, buffer_, n);
00530   } else {
00531     d4_assert(_position == pos_ + _baseOffset);
00532     if (_stream != 0 && !_stream->Write(buffer_, length_))
00533       ++_failure;
00534   }
00535 
00536   _position += length_;
00537 }
00538 
00539 t4_i32 c4_StreamStrategy::FileSize() {
00540   return _position;
00541 }
00542 

akregator

Skip menu "akregator"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal