?? gsm_sms_store.c
字號:
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sms_store.cc
// *
// * Purpose: SMS functions, SMS store
// * (ETSI GSM 07.05)
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 20.5.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_sms_store.h>
#include <gsmlib/gsm_parser.h>
#include <gsmlib/gsm_me_ta.h>
#include <iostream>
using namespace std;
using namespace gsmlib;
// SMSStoreEntry members
SMSStoreEntry::SMSStoreEntry() :
_status(Unknown), _cached(false), _mySMSStore(NULL), _index(0)
{
}
SMSMessageRef SMSStoreEntry::message() const throw(GsmException)
{
if (! cached())
{
assert(_mySMSStore != NULL);
// these operations are at least "logically const"
SMSStoreEntry *thisEntry = const_cast<SMSStoreEntry*>(this);
_mySMSStore->readEntry(_index, thisEntry->_message, thisEntry->_status);
thisEntry->_cached = true;
}
return _message;
}
CBMessageRef SMSStoreEntry::cbMessage() const throw(GsmException)
{
assert(_mySMSStore != NULL);
// these operations are at least "logically const"
SMSStoreEntry *thisEntry = const_cast<SMSStoreEntry*>(this);
// don't cache CB message for now
thisEntry->_cached = false;
CBMessageRef result;
_mySMSStore->readEntry(_index, result);
return result;
}
SMSStoreEntry::SMSMemoryStatus SMSStoreEntry::status() const
throw(GsmException)
{
if (! cached())
{
assert(_mySMSStore != NULL);
// these operations are at least "logically const"
SMSStoreEntry *thisEntry = const_cast<SMSStoreEntry*>(this);
_mySMSStore->readEntry(_index, thisEntry->_message, thisEntry->_status);
thisEntry->_cached = true;
}
return _status;
}
bool SMSStoreEntry::empty() const throw(GsmException)
{
return message().isnull();
}
unsigned char SMSStoreEntry::send(Ref<SMSMessage> &ackPdu)
throw(GsmException)
{
return _mySMSStore->send(_index, ackPdu);
}
unsigned char SMSStoreEntry::send() throw(GsmException)
{
SMSMessageRef mref;
return send(mref);
}
bool SMSStoreEntry::cached() const
{
if (_mySMSStore == NULL)
return _cached;
else
return _cached && _mySMSStore->_useCache;
}
Ref<SMSStoreEntry> SMSStoreEntry::clone()
{
Ref<SMSStoreEntry> result = new SMSStoreEntry(_message->clone());
result->_status = _status;
result->_index = _index;
return result;
}
bool SMSStoreEntry::operator==(const SMSStoreEntry &e) const
{
if (_message.isnull() || e._message.isnull())
return _message.isnull() && e._message.isnull();
else
return _message->encode() == e._message->encode();
}
SMSStoreEntry::SMSStoreEntry(const SMSStoreEntry &e)
{
_message = e._message;
_status = e._status;
_cached = e._cached;
_mySMSStore = e._mySMSStore;
_index = e._index;
}
SMSStoreEntry &SMSStoreEntry::operator=(const SMSStoreEntry &e)
{
_message = e._message;
_status = e._status;
_cached = e._cached;
_mySMSStore = e._mySMSStore;
_index = e._index;
return *this;
}
// iterator members
SMSStoreEntry &SMSStoreIterator::operator*()
{
return (*_store)[_index];
}
SMSStoreEntry *SMSStoreIterator::operator->()
{
return &(*_store)[_index];
}
SMSStoreIterator::operator SMSStoreEntry*()
{
return &(*_store)[_index];
SMSStoreIterator &SMSStoreIterator::operator=(const SMSStoreIterator &i)
{
_index = i._index;
_store = i._store;
return *this;
}
const SMSStoreEntry &SMSStoreConstIterator::operator*()
{
return (*_store)[_index];
}
const SMSStoreEntry *SMSStoreConstIterator::operator->()
{
return &(*_store)[_index];
}
// SMSStore members
void SMSStore::readEntry(int index, SMSMessageRef &message,
SMSStoreEntry::SMSMemoryStatus &status)
throw(GsmException)
{
// select SMS store
_meTa.setSMSStore(_storeName, 1);
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Reading SMS entry " << index << endl;
#endif // NDEBUG
string pdu;
Ref<Parser> p;
try
{
p = new Parser(_at->chat("+CMGR=" + intToStr(index + 1), "+CMGR:",
pdu, false, true, true));
}
catch (GsmException &ge)
{
if (ge.getErrorCode() != SMS_INVALID_MEMORY_INDEX)
throw ge;
else
{
message = SMSMessageRef();
status = SMSStoreEntry::Unknown;
return;
}
}
if (pdu.length() == 0)
{
message = SMSMessageRef();
status = SMSStoreEntry::Unknown;
}
else
{
// add missing service centre address if required by ME
if (! _at->getMeTa().getCapabilities()._hasSMSSCAprefix)
pdu = "00" + pdu;
status = (SMSStoreEntry::SMSMemoryStatus)p->parseInt();
// ignore the rest of the line
message = SMSMessageRef(
SMSMessage::decode(pdu,
!(status == SMSStoreEntry::StoredUnsent ||
status == SMSStoreEntry::StoredSent),
_at.getptr()));
}
}
void SMSStore::readEntry(int index, CBMessageRef &message)
throw(GsmException)
{
// select SMS store
_meTa.setSMSStore(_storeName, 1);
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Reading CB entry " << index << endl;
#endif // NDEBUG
string pdu;
Ref<Parser> p;
try
{
p = new Parser(_at->chat("+CMGR=" + intToStr(index + 1), "+CMGR:",
pdu, false, true, true));
}
catch (GsmException &ge)
{
if (ge.getErrorCode() != SMS_INVALID_MEMORY_INDEX)
throw ge;
else
{
message = CBMessageRef();
return;
}
}
if (pdu.length() == 0)
message = CBMessageRef();
else
message = CBMessageRef(new CBMessage(pdu));
}
void SMSStore::writeEntry(int &index, SMSMessageRef message)
throw(GsmException)
{
// select SMS store
_meTa.setSMSStore(_storeName, 2);
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Writing SMS entry " << index << endl;
#endif
// compute length of pdu
string pdu = message->encode();
// set message status to "RECEIVED READ" for SMS_DELIVER, SMS_STATUS_REPORT
string statusString;
if (message->messageType() != SMSMessage::SMS_SUBMIT)
statusString = ",1";
Parser p(_at->sendPdu("+CMGW=" +
intToStr(pdu.length() / 2 -
message->getSCAddressLen()) + statusString,
"+CMGW:", pdu));
index = p.parseInt() - 1;
}
void SMSStore::eraseEntry(int index) throw(GsmException)
{
// Select SMS store
_meTa.setSMSStore(_storeName, 1);
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Erasing SMS entry " << index << endl;
#endif
_at->chat("+CMGD=" + intToStr(index + 1));
}
unsigned char SMSStore::send(int index, Ref<SMSMessage> &ackPdu)
throw(GsmException)
{
Parser p(_at->chat("+CMSS=" + intToStr(index + 1), "+CMSS:"));
unsigned char messageReference = p.parseInt();
if (p.parseComma(true))
{
string pdu = p.parseEol();
// add missing service centre address if required by ME
if (! _at->getMeTa().getCapabilities()._hasSMSSCAprefix)
pdu = "00" + pdu;
ackPdu = SMSMessage::decode(pdu);
}
else
ackPdu = SMSMessageRef();
return messageReference;
}
int SMSStore::doInsert(SMSMessageRef message)
throw(GsmException)
{
int index;
writeEntry(index, message);
// it is safer to force reading back the SMS from the ME
resizeStore(index + 1);
_store[index]->_cached = false;
return index;
}
SMSStore::SMSStore(string storeName, Ref<GsmAt> at, MeTa &meTa)
throw(GsmException) :
_storeName(storeName), _at(at), _meTa(meTa), _useCache(true)
{
// select SMS store
Parser p(_meTa.setSMSStore(_storeName, true));
p.parseInt(); // skip number of used mems
p.parseComma();
resizeStore(p.parseInt()); // ignore rest of line
}
void SMSStore::resizeStore(int newSize)
{
int oldSize = _store.size();
if (newSize > oldSize)
{
// cout << "*** Resizing from " << oldSize << " to " << newSize << endl;
_store.resize(newSize);
// initialize store entries
for (int i = oldSize; i < newSize; i++)
{
_store[i] = new SMSStoreEntry();
_store[i]->_index = i;
_store[i]->_cached = false;
_store[i]->_mySMSStore = this;
}
}
_capacity = newSize;
}
SMSStore::iterator SMSStore::begin()
{
return SMSStoreIterator(0, this);
}
SMSStore::const_iterator SMSStore::begin() const
{
return SMSStoreConstIterator(0, this);
}
SMSStore::iterator SMSStore::end()
{
return SMSStoreIterator(_capacity, this);
}
SMSStore::const_iterator SMSStore::end() const
{
return SMSStoreConstIterator(_capacity, this);
}
SMSStore::reference SMSStore::operator[](int n)
{
resizeStore(n + 1);
return *_store[n];
}
SMSStore::const_reference SMSStore::operator[](int n) const
{
const_cast<SMSStore*>(this)->resizeStore(n + 1);
return *_store[n];
}
SMSStore::reference SMSStore::front()
{
return *_store[0];
}
SMSStore::const_reference SMSStore::front() const
{
return *_store[0];
}
SMSStore::reference SMSStore::back()
{
return *_store.back();
}
SMSStore::const_reference SMSStore::back() const
{
return *_store.back();
}
int SMSStore::size() const throw(GsmException)
{
// select SMS store
Parser p(_meTa.setSMSStore(_storeName, 1, true));
return p.parseInt();
}
SMSStore::iterator SMSStore::insert(iterator position,
const SMSStoreEntry& x)
throw(GsmException)
{
int index = doInsert(x.message());
return SMSStoreIterator(index, this);
}
SMSStore::iterator SMSStore::insert(const SMSStoreEntry& x)
throw(GsmException)
{
int index = doInsert(x.message());
return SMSStoreIterator(index, this);
}
void SMSStore::insert (iterator pos, int n, const SMSStoreEntry& x)
throw(GsmException)
{
for (int i = 0; i < n; i++)
doInsert(x.message());
}
void SMSStore::insert (iterator pos, long n, const SMSStoreEntry& x)
throw(GsmException)
{
for (long i = 0; i < n; i++)
doInsert(x.message());
}
SMSStore::iterator SMSStore::erase(iterator position)
throw(GsmException)
{
eraseEntry(position->_index);
position->_cached = false;
return position + 1;
}
SMSStore::iterator SMSStore::erase(iterator first, iterator last)
throw(GsmException)
{
iterator i(0, this);
for (i = first; i != last; ++i)
erase(i);
return i;
}
void SMSStore::clear() throw(GsmException)
{
for (iterator i = begin(); i != end(); ++i)
erase(i);
}
SMSStore::~SMSStore()
{
for (vector<SMSStoreEntry*>::iterator i = _store.begin();
i != _store.end(); ++i)
delete *i;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -