//============================================================================= // File: addrlist.cpp // Contents: Definitions for DwAddressList // 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 #include const char* const DwAddressList::sClassName = "DwAddressList"; DwAddressList* (*DwAddressList::sNewAddressList)(const DwString&, DwMessageComponent*) = 0; DwAddressList* DwAddressList::NewAddressList(const DwString& aStr, DwMessageComponent* aParent) { if (sNewAddressList) { return sNewAddressList(aStr, aParent); } else { return new DwAddressList(aStr, aParent); } } DwAddressList::DwAddressList() { mFirstAddress = 0; mClassId = kCidAddressList; mClassName = sClassName; } DwAddressList::DwAddressList(const DwAddressList& aList) : DwFieldBody(aList) { mFirstAddress = 0; const DwAddress* addr = aList.mFirstAddress; if (addr) { CopyList(addr); } mClassId = kCidAddressList; mClassName = sClassName; } DwAddressList::DwAddressList(const DwString& aStr, DwMessageComponent* aParent) : DwFieldBody(aStr, aParent) { mFirstAddress = 0; mClassId = kCidAddressList; mClassName = sClassName; } DwAddressList::~DwAddressList() { if (mFirstAddress) { DeleteAll(); } } const DwAddressList& DwAddressList::operator = (const DwAddressList& aList) { if (this == &aList) return *this; DwFieldBody::operator = (aList); if (mFirstAddress) { DeleteAll(); } const DwAddress* addr = aList.mFirstAddress; if (addr) { CopyList(addr); } return *this; } DwMessageComponent* DwAddressList::Clone() const { return new DwAddressList(*this); } DwAddress* DwAddressList::FirstAddress() const { return mFirstAddress; } void DwAddressList::Add(DwAddress* aAddr) { aAddr->SetNext(0); aAddr->SetParent(this); if (!mFirstAddress) { mFirstAddress = aAddr; } else { DwAddress* addr = mFirstAddress; while (addr->Next()) { addr = (DwAddress*) addr->Next(); } addr->SetNext(aAddr); } SetModified(); } void DwAddressList::Remove(DwAddress* aAddr) { DwAddress* addr = mFirstAddress; if (addr == aAddr) { mFirstAddress = (DwAddress*) addr->Next(); aAddr->SetNext(0); return; } while (addr) { if (addr->Next() == aAddr) { addr->SetNext(aAddr->Next()); aAddr->SetNext(0); break; } } SetModified(); } void DwAddressList::DeleteAll() { DwAddress* addr = mFirstAddress; while (addr) { DwAddress* nextAddr = (DwAddress*) addr->Next(); delete addr; addr = nextAddr; } mFirstAddress = 0; } void DwAddressList::Parse() { mIsModified = 0; if (mFirstAddress) { DeleteAll(); } DwAddressListParser parser(mString); DwAddress* address; while (1) { switch (parser.AddrType()) { case DwAddressListParser::eAddrError: case DwAddressListParser::eAddrEnd: goto LOOP_EXIT; case DwAddressListParser::eAddrMailbox: address = DwMailbox::NewMailbox(parser.AddrString(), this); address->Parse(); if (address->IsValid()) { Add(address); } else { delete address; } break; case DwAddressListParser::eAddrGroup: address = DwGroup::NewGroup(parser.AddrString(), this); address->Parse(); if (address->IsValid()) { Add(address); } else { delete address; } break; case DwAddressListParser::eAddrNull: break; } ++parser; } LOOP_EXIT: return; } void DwAddressList::Assemble() { if (!mIsModified) return; mString = ""; int count = 0; DwAddress* addr = mFirstAddress; while (addr) { addr->Assemble(); if (addr->IsValid()) { if (count > 0){ if (IsFolding()) { mString += "," DW_EOL " "; } else { mString += ", "; } } mString += addr->AsString(); ++count; } addr = (DwAddress*) addr->Next(); } mIsModified = 0; } void DwAddressList::CopyList(const DwAddress* aFirstAddr) { const DwAddress* addr = aFirstAddr; while (addr) { DwAddress* newAddr = (DwAddress*) addr->Clone(); Add(newAddr); addr = (const DwAddress*) addr->Next(); } } #if defined (DW_DEBUG_VERSION) void DwAddressList::PrintDebugInfo(std::ostream& aStrm, int aDepth/*=0*/) const { aStrm << "-------------- Debug info for DwAddressList class --------------\n"; _PrintDebugInfo(aStrm); int depth = aDepth - 1; depth = (depth >= 0) ? depth : 0; if (aDepth == 0 || depth > 0) { DwAddress* addr = mFirstAddress; while (addr) { addr->PrintDebugInfo(aStrm, depth); addr = addr->Next(); } } } #else void DwAddressList::PrintDebugInfo(std::ostream&, int) const {} #endif // defined (DW_DEBUG_VERSION) #if defined (DW_DEBUG_VERSION) void DwAddressList::_PrintDebugInfo(std::ostream& aStrm) const { DwFieldBody::_PrintDebugInfo(aStrm); aStrm << "Address objects: "; DwAddress* addr = mFirstAddress; if (addr) { int count = 0; while (addr) { if (count > 0) aStrm << ' '; aStrm << addr->ObjectId(); addr = addr->Next(); ++count; } aStrm << '\n'; } else { aStrm << "(none)\n"; } } #else void DwAddressList::_PrintDebugInfo(std::ostream&) const {} #endif // defined (DW_DEBUG_VERSION) void DwAddressList::CheckInvariants() const { #if defined (DW_DEBUG_VERSION) DwAddress* addr = mFirstAddress; while (addr) { addr->CheckInvariants(); assert((DwMessageComponent*) this == addr->Parent()); addr = addr->Next(); } #endif // defined (DW_DEBUG_VERSION) } //------------------------------------------------------------------------- DwAddressListParser::DwAddressListParser(const DwString& aStr) : mTokenizer(aStr), mAddrString(aStr) { mAddrType = eAddrError; ParseNextAddress(); } DwAddressListParser::~DwAddressListParser() { } int DwAddressListParser::Restart() { mTokenizer.Restart(); ParseNextAddress(); return mAddrType; } int DwAddressListParser::operator ++ () { ParseNextAddress(); return mAddrType; } void DwAddressListParser::ParseNextAddress() { mAddrString.SetFirst(mTokenizer); mAddrType = eAddrEnd; int type = mTokenizer.Type(); if (type == eTkNull) { return; } enum { eTopLevel, eInGroup, eInRouteAddr } state; state = eTopLevel; // The type will be a mailbox, unless we discover otherwise mAddrType = eAddrMailbox; int done = 0; while (!done) { if (type == eTkNull) { mAddrString.ExtendTo(mTokenizer); break; } else if (type == eTkSpecial) { int ch = mTokenizer.Token()[0]; switch (state) { case eTopLevel: switch (ch) { case ',': mAddrString.ExtendTo(mTokenizer); done = 1; break; case '<': state = eInRouteAddr; break; case ':': mAddrType = eAddrGroup; state = eInGroup; break; } break; case eInRouteAddr: switch (ch) { case '>': state = eTopLevel; break; } break; case eInGroup: switch (ch) { case ';': state = eTopLevel; break; } break; } } ++mTokenizer; type = mTokenizer.Type(); } if (mAddrString.Tokens().length() == 0) { mAddrType = eAddrNull; } }