//============================================================================= // File: mboxlist.cpp // Contents: Definitions for DwMailboxList // Maintainer: Doug Sauder // WWW: http://www.fwb.gulf.net/~dwsauder/mimepp.html // // Copyright (c) 1996, 1997 Douglas W. Sauder // All rights reserved. // // IN NO EVENT SHALL DOUGLAS W. SAUDER BE LIABLE TO ANY PARTY FOR DIRECT, // INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF // THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF DOUGLAS W. SAUDER // HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // DOUGLAS W. SAUDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT // NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A // PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" // BASIS, AND DOUGLAS W. SAUDER HAS NO OBLIGATION TO PROVIDE MAINTENANCE, // SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. // //============================================================================= #define DW_IMPLEMENTATION #include #include #include #include #include #include #include #include #include #include const char* const DwMailboxList::sClassName = "DwMailboxList"; DwMailboxList* (*DwMailboxList::sNewMailboxList)(const DwString&, DwMessageComponent*) = 0; DwMailboxList* DwMailboxList::NewMailboxList(const DwString& aStr, DwMessageComponent* aParent) { if (sNewMailboxList) { return sNewMailboxList(aStr, aParent); } else { return new DwMailboxList(aStr, aParent); } } DwMailboxList::DwMailboxList() { mFirstMailbox = 0; mClassId = kCidMailboxList; mClassName = sClassName; } DwMailboxList::DwMailboxList(const DwMailboxList& aList) : DwFieldBody(aList) { mFirstMailbox = 0; const DwMailbox* firstMailbox = aList.mFirstMailbox; if (firstMailbox) { CopyList(firstMailbox); } mClassId = kCidMailboxList; mClassName = sClassName; } DwMailboxList::DwMailboxList(const DwString& aStr, DwMessageComponent* aParent) : DwFieldBody(aStr, aParent) { mFirstMailbox = 0; mClassId = kCidMailboxList; mClassName = sClassName; } DwMailboxList::~DwMailboxList() { if (mFirstMailbox) { _DeleteAll(); } } const DwMailboxList& DwMailboxList::operator = (const DwMailboxList& aList) { if (this == &aList) return *this; DwFieldBody::operator = (aList); if (mFirstMailbox) { _DeleteAll(); } const DwMailbox* firstMailbox = aList.mFirstMailbox; if (firstMailbox) { CopyList(firstMailbox); } if (mParent && mIsModified) { mParent->SetModified(); } return *this; } DwMailbox* DwMailboxList::FirstMailbox() const { return mFirstMailbox; } void DwMailboxList::Add(DwMailbox* aMailbox) { assert(aMailbox != 0); if (aMailbox == 0) return; _AddMailbox(aMailbox); SetModified(); } void DwMailboxList::_AddMailbox(DwMailbox* aMailbox) { assert(aMailbox != 0); if (aMailbox == 0) return; if (!mFirstMailbox) { mFirstMailbox = aMailbox; } else { DwMailbox* mb = mFirstMailbox; while (mb->Next()) { mb = (DwMailbox*) mb->Next(); } mb->SetNext(aMailbox); } aMailbox->SetParent(this); } void DwMailboxList::Remove(DwMailbox* mailbox) { DwMailbox* mb = mFirstMailbox; if (mb == mailbox) { mFirstMailbox = (DwMailbox*) mb->Next(); return; } while (mb) { if (mb->Next() == mailbox) { mb->SetNext(mailbox->Next()); break; } } SetModified(); } void DwMailboxList::DeleteAll() { _DeleteAll(); SetModified(); } void DwMailboxList::_DeleteAll() { DwMailbox* mb = mFirstMailbox; while (mb) { DwMailbox* toDel = mb; mb = (DwMailbox*) mb->Next(); delete toDel; } mFirstMailbox = 0; } void DwMailboxList::Parse() { mIsModified = 0; // Mailboxes are separated by commas. Commas may also occur in a route. // (See RFC822 p. 27) if (mFirstMailbox) _DeleteAll(); DwMailboxListParser parser(mString); DwMailbox* mailbox; while (1) { switch (parser.MbType()) { case DwMailboxListParser::eMbError: case DwMailboxListParser::eMbEnd: goto LOOP_EXIT; case DwMailboxListParser::eMbMailbox: mailbox = DwMailbox::NewMailbox(parser.MbString(), this); mailbox->Parse(); if (mailbox->IsValid()) { _AddMailbox(mailbox); } else { delete mailbox; } break; case DwMailboxListParser::eMbNull: break; } ++parser; } LOOP_EXIT: return; } void DwMailboxList::Assemble() { if (!mIsModified) return; mString = ""; int count = 0; DwMailbox* mb = mFirstMailbox; while (mb) { mb->Assemble(); if (mb->IsValid()) { if (count > 0){ if (IsFolding()) { mString += "," DW_EOL " "; } else { mString += ", "; } } mString += mb->AsString(); ++count; } mb = (DwMailbox*) mb->Next(); } mIsModified = 0; } DwMessageComponent* DwMailboxList::Clone() const { return new DwMailboxList(*this); } void DwMailboxList::CopyList(const DwMailbox* aFirst) { const DwMailbox* mailbox = aFirst; while (mailbox) { DwMailbox* newMailbox = (DwMailbox*) mailbox->Clone(); Add(newMailbox); mailbox = (DwMailbox*) mailbox->Next(); } } #if defined (DW_DEBUG_VERSION) void DwMailboxList::PrintDebugInfo(std::ostream& aStrm, int aDepth) const { aStrm << "-------------- Debug info for DwMailboxList class --------------\n"; _PrintDebugInfo(aStrm); int depth = aDepth - 1; depth = (depth >= 0) ? depth : 0; if (aDepth == 0 || depth > 0) { DwMailbox* mbox = mFirstMailbox; while (mbox) { mbox->PrintDebugInfo(aStrm, depth); mbox = (DwMailbox*) mbox->Next(); } } } #else void DwMailboxList::PrintDebugInfo(std::ostream& , int ) const {} #endif // defined (DW_DEBUG_VERSION) #if defined (DW_DEBUG_VERSION) void DwMailboxList::_PrintDebugInfo(std::ostream& aStrm) const { DwFieldBody::_PrintDebugInfo(aStrm); aStrm << "Mailbox objects: "; DwMailbox* mbox = mFirstMailbox; if (mbox) { int count = 0; while (mbox) { if (count) aStrm << ' '; aStrm << mbox->ObjectId(); mbox = (DwMailbox*) mbox->Next(); ++count; } aStrm << '\n'; } else { aStrm << "(none)\n"; } } #else void DwMailboxList::_PrintDebugInfo(std::ostream& ) const {} #endif // defined (DW_DEBUG_VERSION) void DwMailboxList::CheckInvariants() const { #if defined (DW_DEBUG_VERSION) DwMailbox* mbox = mFirstMailbox; while (mbox) { mbox->CheckInvariants(); assert((DwMessageComponent*) this == mbox->Parent()); mbox = (DwMailbox*) mbox->Next(); } #endif // defined (DW_DEBUG_VERSION) } //------------------------------------------------------------------------- DwMailboxListParser::DwMailboxListParser(const DwString& aStr) : mTokenizer(aStr), mMbString(aStr) { mMbType = eMbError; ParseNextMailbox(); } DwMailboxListParser::~DwMailboxListParser() { } int DwMailboxListParser::Restart() { mTokenizer.Restart(); ParseNextMailbox(); return mMbType; } int DwMailboxListParser::operator ++ () { ParseNextMailbox(); return mMbType; } void DwMailboxListParser::ParseNextMailbox() { mMbString.SetFirst(mTokenizer); mMbType = eMbEnd; int type = mTokenizer.Type(); if (type == eTkNull) { return; } enum { eTopLevel, eInRouteAddr } state; state = eTopLevel; mMbType = eMbMailbox; int done = 0; while (!done) { if (type == eTkNull) { mMbString.ExtendTo(mTokenizer); break; } if (type == eTkSpecial) { int ch = mTokenizer.Token()[0]; switch (state) { case eTopLevel: switch (ch) { case ',': mMbString.ExtendTo(mTokenizer); done = 1; break; case '<': state = eInRouteAddr; break; } break; case eInRouteAddr: switch (ch) { case '>': state = eTopLevel; break; } break; } } ++mTokenizer; type = mTokenizer.Type(); } if (mMbString.Tokens().length() == 0) { mMbType = eMbNull; } }