1241 lines
34 KiB
C++
1241 lines
34 KiB
C++
|
/*
|
||
|
Adept MobileRobots Robotics Interface for Applications (ARIA)
|
||
|
Copyright (C) 2004, 2005 ActivMedia Robotics LLC
|
||
|
Copyright (C) 2006, 2007, 2008, 2009, 2010 MobileRobots Inc.
|
||
|
Copyright (C) 2011, 2012, 2013 Adept Technology
|
||
|
|
||
|
This program is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
|
||
|
If you wish to redistribute ARIA under different terms, contact
|
||
|
Adept MobileRobots for information about a commercial version of ARIA at
|
||
|
robots@mobilerobots.com or
|
||
|
Adept MobileRobots, 10 Columbia Drive, Amherst, NH 03031; +1-603-881-7960
|
||
|
*/
|
||
|
#include "ArExport.h"
|
||
|
|
||
|
#include "ArMapUtils.h"
|
||
|
|
||
|
#include "ariaUtil.h"
|
||
|
#include "ArBasePacket.h"
|
||
|
#include "ArMapComponents.h"
|
||
|
#include "ArMD5Calculator.h"
|
||
|
|
||
|
#include <iterator>
|
||
|
|
||
|
//#define ARDEBUG_MAPUTILS
|
||
|
#ifdef ARDEBUG_MAPUTILS
|
||
|
#define IFDEBUG(code) {code;}
|
||
|
#else
|
||
|
#define IFDEBUG(code)
|
||
|
#endif
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// ArMapId
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
AREXPORT ArMapId::ArMapId() :
|
||
|
mySourceName(),
|
||
|
myFileName(),
|
||
|
myChecksum(NULL),
|
||
|
myChecksumLength(0),
|
||
|
myDisplayChecksum(NULL),
|
||
|
myDisplayChecksumLength(0),
|
||
|
mySize(0),
|
||
|
myTimestamp(-1)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
AREXPORT ArMapId::ArMapId(const char *sourceName,
|
||
|
const char *fileName,
|
||
|
const unsigned char *checksum,
|
||
|
size_t checksumLength,
|
||
|
long int size,
|
||
|
const time_t timestamp) :
|
||
|
mySourceName((sourceName != NULL) ? sourceName : ""),
|
||
|
myFileName((fileName != NULL) ? fileName : ""),
|
||
|
myChecksum(NULL),
|
||
|
myChecksumLength(0),
|
||
|
myDisplayChecksum(NULL),
|
||
|
myDisplayChecksumLength(0),
|
||
|
mySize(size),
|
||
|
myTimestamp(timestamp)
|
||
|
{
|
||
|
if (checksumLength > 0) {
|
||
|
setChecksum(checksum,
|
||
|
checksumLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AREXPORT ArMapId::ArMapId(const ArMapId &other) :
|
||
|
mySourceName(other.mySourceName),
|
||
|
myFileName(other.myFileName),
|
||
|
myChecksum(NULL),
|
||
|
myChecksumLength(0),
|
||
|
myDisplayChecksum(NULL),
|
||
|
myDisplayChecksumLength(0),
|
||
|
mySize(other.mySize),
|
||
|
myTimestamp(other.myTimestamp)
|
||
|
{
|
||
|
if (other.myChecksumLength > 0) {
|
||
|
setChecksum(other.myChecksum,
|
||
|
other.myChecksumLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AREXPORT ArMapId &ArMapId::operator=(const ArMapId &other)
|
||
|
{
|
||
|
if (&other != this) {
|
||
|
|
||
|
mySourceName = other.mySourceName;
|
||
|
myFileName = other.myFileName;
|
||
|
|
||
|
delete [] myChecksum;
|
||
|
myChecksum = NULL;
|
||
|
myChecksumLength = 0;
|
||
|
|
||
|
delete [] myDisplayChecksum;
|
||
|
myDisplayChecksum = NULL;
|
||
|
myDisplayChecksumLength = 0;
|
||
|
|
||
|
if (other.myChecksumLength > 0) {
|
||
|
setChecksum(other.myChecksum,
|
||
|
other.myChecksumLength);
|
||
|
}
|
||
|
|
||
|
|
||
|
mySize = other.mySize;
|
||
|
myTimestamp = other.myTimestamp;
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
AREXPORT ArMapId::~ArMapId()
|
||
|
{
|
||
|
delete [] myChecksum;
|
||
|
myChecksum = NULL;
|
||
|
myChecksumLength = 0;
|
||
|
|
||
|
delete [] myDisplayChecksum;
|
||
|
myDisplayChecksum = NULL;
|
||
|
myDisplayChecksumLength = 0;
|
||
|
}
|
||
|
|
||
|
AREXPORT bool ArMapId::isNull() const
|
||
|
{
|
||
|
// TODO Any need to check others?
|
||
|
bool b = (ArUtil::isStrEmpty(mySourceName.c_str()) &&
|
||
|
ArUtil::isStrEmpty(myFileName.c_str()));
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
AREXPORT void ArMapId::clear()
|
||
|
{
|
||
|
mySourceName = "";
|
||
|
myFileName = "";
|
||
|
|
||
|
delete [] myChecksum;
|
||
|
myChecksum = NULL;
|
||
|
myChecksumLength = 0;
|
||
|
|
||
|
delete [] myDisplayChecksum;
|
||
|
myDisplayChecksum = NULL;
|
||
|
myDisplayChecksumLength = 0;
|
||
|
|
||
|
mySize = 0;
|
||
|
myTimestamp = -1;
|
||
|
|
||
|
} // end method clear
|
||
|
|
||
|
|
||
|
AREXPORT const char *ArMapId::getSourceName() const
|
||
|
{
|
||
|
return mySourceName.c_str();
|
||
|
}
|
||
|
|
||
|
AREXPORT const char *ArMapId::getFileName() const
|
||
|
{
|
||
|
return myFileName.c_str();
|
||
|
}
|
||
|
|
||
|
AREXPORT const unsigned char *ArMapId::getChecksum() const
|
||
|
{
|
||
|
return myChecksum;
|
||
|
}
|
||
|
|
||
|
AREXPORT size_t ArMapId::getChecksumLength() const
|
||
|
{
|
||
|
return myChecksumLength;
|
||
|
}
|
||
|
|
||
|
AREXPORT const char *ArMapId::getDisplayChecksum() const
|
||
|
{
|
||
|
if ((myDisplayChecksum == NULL) && (myChecksumLength > 0)) {
|
||
|
|
||
|
myDisplayChecksumLength = ArMD5Calculator::DISPLAY_LENGTH;
|
||
|
myDisplayChecksum = new char[myDisplayChecksumLength];
|
||
|
|
||
|
ArMD5Calculator::toDisplay(myChecksum,
|
||
|
myChecksumLength,
|
||
|
myDisplayChecksum,
|
||
|
myDisplayChecksumLength);
|
||
|
|
||
|
}
|
||
|
|
||
|
return myDisplayChecksum;
|
||
|
}
|
||
|
|
||
|
AREXPORT long int ArMapId::getSize() const
|
||
|
{
|
||
|
return mySize;
|
||
|
}
|
||
|
|
||
|
AREXPORT time_t ArMapId::getTimestamp() const
|
||
|
{
|
||
|
return myTimestamp;
|
||
|
}
|
||
|
|
||
|
AREXPORT bool ArMapId::isSameFile(const ArMapId &other) const
|
||
|
{
|
||
|
if (ArUtil::strcasecmp(myFileName, other.myFileName) != 0) {
|
||
|
return false;
|
||
|
}
|
||
|
if (mySize != other.mySize) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// If both timestamps are specified, then the must be identical...
|
||
|
if ((myTimestamp != other.myTimestamp) &&
|
||
|
(isValidTimestamp()) &&
|
||
|
(other.isValidTimestamp())) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (myChecksumLength != other.myChecksumLength) {
|
||
|
return false;
|
||
|
}
|
||
|
if ((myChecksum != NULL) && (other.myChecksum != NULL)) {
|
||
|
return (memcmp(myChecksum, other.myChecksum, myChecksumLength) == 0);
|
||
|
}
|
||
|
return true; // ??
|
||
|
}
|
||
|
|
||
|
|
||
|
AREXPORT bool ArMapId::isVersionOfSameFile(const ArMapId &other) const
|
||
|
{
|
||
|
if ((ArUtil::strcasecmp(mySourceName, other.mySourceName) == 0) &&
|
||
|
(ArUtil::strcasecmp(myFileName, other.myFileName) == 0)) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
|
||
|
} // end method isVersionOfSameFile
|
||
|
|
||
|
AREXPORT bool ArMapId::isValidTimestamp() const
|
||
|
{
|
||
|
bool b = ((myTimestamp != -1) &&
|
||
|
(myTimestamp != 0));
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
AREXPORT void ArMapId::setSourceName(const char *sourceName)
|
||
|
{
|
||
|
if (sourceName != NULL) {
|
||
|
mySourceName = sourceName;
|
||
|
}
|
||
|
else {
|
||
|
mySourceName = "";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AREXPORT void ArMapId::setFileName(const char *fileName)
|
||
|
{
|
||
|
if (fileName != NULL) {
|
||
|
myFileName = fileName;
|
||
|
}
|
||
|
else {
|
||
|
myFileName = "";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AREXPORT void ArMapId::setChecksum(const unsigned char *checksum,
|
||
|
size_t checksumLen)
|
||
|
{
|
||
|
if (checksumLen < 0) {
|
||
|
checksumLen = 0;
|
||
|
}
|
||
|
if (checksumLen != myChecksumLength) {
|
||
|
delete [] myChecksum;
|
||
|
myChecksum = NULL;
|
||
|
myChecksumLength = 0;
|
||
|
}
|
||
|
if (checksumLen > 0) {
|
||
|
myChecksumLength = checksumLen;
|
||
|
myChecksum = new unsigned char[myChecksumLength];
|
||
|
memcpy(myChecksum, checksum, myChecksumLength);
|
||
|
}
|
||
|
// Clear this so that it is calculated if necessary....
|
||
|
delete [] myDisplayChecksum;
|
||
|
myDisplayChecksum = NULL;
|
||
|
myDisplayChecksumLength = 0;
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
AREXPORT void ArMapId::setSize(long int size)
|
||
|
{
|
||
|
mySize = size;
|
||
|
}
|
||
|
|
||
|
AREXPORT void ArMapId::setTimestamp(const time_t ×tamp)
|
||
|
{
|
||
|
IFDEBUG(ArLog::log(ArLog::Normal,
|
||
|
"ArMapId::setTimestamp() time = %i",
|
||
|
timestamp));
|
||
|
|
||
|
myTimestamp = timestamp;
|
||
|
}
|
||
|
|
||
|
/// Determines whether two IDs are equal.
|
||
|
AREXPORT bool operator==(const ArMapId & id1, const ArMapId & id2)
|
||
|
{
|
||
|
// The mirror opposite of operator!=
|
||
|
|
||
|
// Filename is compared last just because it takes longer
|
||
|
if (id1.mySize != id2.mySize) {
|
||
|
return false;
|
||
|
}
|
||
|
// A null timestamp (-1) can be "equal" to any other timestamp
|
||
|
if ((id1.isValidTimestamp()) &&
|
||
|
(id2.isValidTimestamp()) &&
|
||
|
(id1.myTimestamp != id2.myTimestamp)) {
|
||
|
return false;
|
||
|
}
|
||
|
if (id1.myChecksumLength != id2.myChecksumLength) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// TODO: Compare only if sources are not null (like timestamps)?
|
||
|
if (ArUtil::strcasecmp(id1.mySourceName, id2.mySourceName) != 0) {
|
||
|
return false;
|
||
|
}
|
||
|
if (ArUtil::strcasecmp(id1.myFileName, id2.myFileName) != 0) {
|
||
|
return false;
|
||
|
}
|
||
|
if ((id1.myChecksum != NULL) && (id2.myChecksum != NULL)) {
|
||
|
if (memcmp(id1.myChecksum, id2.myChecksum, id1.myChecksumLength) != 0) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
else if (id1.myChecksum != id2.myChecksum) {
|
||
|
// The above says that if one of them is null, then both of them
|
||
|
// must be null.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
|
||
|
} // end method operator==
|
||
|
|
||
|
/// Determines whether two IDs are not equal.
|
||
|
AREXPORT bool operator!=(const ArMapId & id1, const ArMapId & id2)
|
||
|
{
|
||
|
// The mirror opposite of operator==
|
||
|
|
||
|
// Filename is compared last just because it takes longer
|
||
|
if (id1.mySize != id2.mySize) {
|
||
|
return true;
|
||
|
}
|
||
|
// A null timestamp (-1) can be "equal" to any other timestamp
|
||
|
if ((id1.isValidTimestamp()) &&
|
||
|
(id2.isValidTimestamp()) &&
|
||
|
(id1.myTimestamp != id2.myTimestamp)) {
|
||
|
return true;
|
||
|
}
|
||
|
if (id1.myChecksumLength != id2.myChecksumLength) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// TODO: Compare only if sources are not null (like timestamps)?
|
||
|
if (ArUtil::strcasecmp(id1.mySourceName, id2.mySourceName) != 0) {
|
||
|
return true;
|
||
|
}
|
||
|
if (ArUtil::strcasecmp(id1.myFileName, id2.myFileName) != 0) {
|
||
|
return true;
|
||
|
}
|
||
|
if ((id1.myChecksum != NULL) && (id2.myChecksum != NULL)) {
|
||
|
if (memcmp(id1.myChecksum, id2.myChecksum, id1.myChecksumLength) != 0) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
else if (id1.myChecksum != id2.myChecksum) {
|
||
|
// The above says that if one of them is null, then both of them
|
||
|
// must be null.
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
|
||
|
} // end method operator!=
|
||
|
|
||
|
|
||
|
AREXPORT void ArMapId::log(const char *prefix) const
|
||
|
{
|
||
|
time_t idTime = getTimestamp();
|
||
|
|
||
|
char timeBuf[500];
|
||
|
|
||
|
struct tm *idTm = NULL;
|
||
|
|
||
|
if (idTime != -1) {
|
||
|
idTm = localtime(&idTime);
|
||
|
}
|
||
|
if (idTm != NULL) {
|
||
|
strftime(timeBuf, sizeof(timeBuf), "%c", idTm);
|
||
|
}
|
||
|
else {
|
||
|
snprintf(timeBuf, sizeof(timeBuf), "NULL");
|
||
|
}
|
||
|
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"%s%smap %s %s%s checksum = \"%s\" size = %i time = %s (%i)",
|
||
|
((prefix != NULL) ? prefix : ""),
|
||
|
((prefix != NULL) ? " " : ""),
|
||
|
getFileName(),
|
||
|
(!ArUtil::isStrEmpty(getSourceName()) ? "source " : ""),
|
||
|
(!ArUtil::isStrEmpty(getSourceName()) ? getSourceName() : ""),
|
||
|
getDisplayChecksum(),
|
||
|
getSize(),
|
||
|
timeBuf,
|
||
|
idTime);
|
||
|
|
||
|
}
|
||
|
|
||
|
AREXPORT bool ArMapId::fromPacket(ArBasePacket *packetIn,
|
||
|
ArMapId *mapIdOut)
|
||
|
{
|
||
|
if ((packetIn == NULL) || (mapIdOut == NULL)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
char sourceBuffer[512];
|
||
|
packetIn->bufToStr(sourceBuffer, sizeof(sourceBuffer));
|
||
|
|
||
|
char fileNameBuffer[512];
|
||
|
packetIn->bufToStr(fileNameBuffer, sizeof(fileNameBuffer));
|
||
|
|
||
|
ArUtil::fixSlashes(fileNameBuffer, sizeof(fileNameBuffer));
|
||
|
|
||
|
size_t checksumLength = packetIn->bufToUByte4();
|
||
|
|
||
|
unsigned char *checksum = NULL;
|
||
|
if (checksumLength > 0) {
|
||
|
checksum = new unsigned char[checksumLength];
|
||
|
packetIn->bufToData(checksum, checksumLength);
|
||
|
}
|
||
|
|
||
|
size_t fileSize = packetIn->bufToUByte4();
|
||
|
time_t fileTime = packetIn->bufToByte4();
|
||
|
|
||
|
IFDEBUG(ArLog::log(ArLog::Normal,
|
||
|
"ArMapId::fromPacket() time = %i",
|
||
|
fileTime));
|
||
|
|
||
|
*mapIdOut = ArMapId(sourceBuffer,
|
||
|
fileNameBuffer,
|
||
|
checksum,
|
||
|
checksumLength,
|
||
|
fileSize,
|
||
|
fileTime);
|
||
|
|
||
|
IFDEBUG(mapIdOut->log("ArMapId::fromPacket()"));
|
||
|
|
||
|
delete [] checksum;
|
||
|
|
||
|
return true;
|
||
|
|
||
|
} // end method fromPacket
|
||
|
|
||
|
|
||
|
AREXPORT bool ArMapId::toPacket(const ArMapId &mapId,
|
||
|
ArBasePacket *packetOut)
|
||
|
{
|
||
|
|
||
|
IFDEBUG(mapId.log("ArMapId::toPacket()"));
|
||
|
|
||
|
if (packetOut == NULL) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (!ArUtil::isStrEmpty(mapId.getSourceName())) {
|
||
|
packetOut->strToBuf(mapId.getSourceName());
|
||
|
}
|
||
|
else {
|
||
|
packetOut->strToBuf("");
|
||
|
}
|
||
|
|
||
|
if (!ArUtil::isStrEmpty(mapId.getFileName())) {
|
||
|
packetOut->strToBuf(mapId.getFileName());
|
||
|
}
|
||
|
else {
|
||
|
packetOut->strToBuf("");
|
||
|
}
|
||
|
|
||
|
packetOut->uByte4ToBuf(mapId.getChecksumLength());
|
||
|
if (mapId.getChecksumLength() > 0) {
|
||
|
packetOut->dataToBuf(mapId.getChecksum(), mapId.getChecksumLength());
|
||
|
}
|
||
|
packetOut->uByte4ToBuf(mapId.getSize());
|
||
|
packetOut->byte4ToBuf(mapId.getTimestamp());
|
||
|
|
||
|
IFDEBUG(ArLog::log(ArLog::Normal,
|
||
|
"ArMapId::toPacket() time = %i",
|
||
|
mapId.getTimestamp()));
|
||
|
|
||
|
return true;
|
||
|
|
||
|
} // end method toPacket
|
||
|
|
||
|
|
||
|
|
||
|
AREXPORT bool ArMapId::create(const char *mapFileName,
|
||
|
ArMapId *mapIdOut)
|
||
|
{
|
||
|
if (mapIdOut == NULL) {
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"Cannot create null map ID");
|
||
|
return false;
|
||
|
}
|
||
|
if (ArUtil::isStrEmpty(mapFileName)) {
|
||
|
ArLog::log(ArLog::Verbose,
|
||
|
"Returning null map ID for null file name");
|
||
|
mapIdOut->clear();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
struct stat mapFileStat;
|
||
|
if (stat(mapFileName, &mapFileStat) != 0)
|
||
|
{
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"Map file %s not not found", mapFileName);
|
||
|
mapIdOut->clear();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
unsigned char buffer[ArMD5Calculator::DIGEST_LENGTH];
|
||
|
bool isSuccess = ArMD5Calculator::calculateChecksum(mapFileName,
|
||
|
buffer,
|
||
|
sizeof(buffer));
|
||
|
|
||
|
if (!isSuccess) {
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"Error calculating checksum for map file %s",
|
||
|
mapFileName);
|
||
|
mapIdOut->clear();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
mapIdOut->setFileName(mapFileName);
|
||
|
mapIdOut->setChecksum(buffer, sizeof(buffer));
|
||
|
mapIdOut->setSize(mapFileStat.st_size);
|
||
|
mapIdOut->setTimestamp(mapFileStat.st_mtime);
|
||
|
|
||
|
return true;
|
||
|
|
||
|
} // end method create
|
||
|
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// ArMapFileLineSet
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// ArMapFileLineGroup
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
void ArMapFileLineGroup::log()
|
||
|
{
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"#%-3i : %s",
|
||
|
myParentLine.getLineNum(),
|
||
|
myParentLine.getLineText());
|
||
|
for (std::vector<ArMapFileLine>::iterator iter = myChildLines.begin();
|
||
|
iter != myChildLines.end();
|
||
|
iter++) {
|
||
|
ArMapFileLine &fileLine = *iter;
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
" #%-3i : %s",
|
||
|
fileLine.getLineNum(),
|
||
|
fileLine.getLineText());
|
||
|
}
|
||
|
} // end method log
|
||
|
|
||
|
|
||
|
|
||
|
void ArMapFileLineSet::log(const char *prefix)
|
||
|
{
|
||
|
if (prefix != NULL) {
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
prefix);
|
||
|
}
|
||
|
|
||
|
int i = 0;
|
||
|
ArMapFileLineSet::iterator mIter = begin();
|
||
|
|
||
|
for (;((mIter != end()) && (i < 100));
|
||
|
mIter++, i++) {
|
||
|
ArMapFileLineGroup &group = *mIter;
|
||
|
group.log();
|
||
|
}
|
||
|
|
||
|
if (mIter != end()) {
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"..... (cont.)");
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"Size = %i", size());
|
||
|
|
||
|
}
|
||
|
} // end method log
|
||
|
|
||
|
|
||
|
ArMapFileLineSet::iterator ArMapFileLineSet::find(const ArMapFileLine &groupParent) {
|
||
|
for (iterator iter = begin(); iter != end(); iter++) {
|
||
|
ArMapFileLineGroup &group = *iter;
|
||
|
if ((group.getParentLine()->getLineNum() == groupParent.getLineNum()) &&
|
||
|
true) {
|
||
|
|
||
|
if (strcmp(group.getParentLine()->getLineText(),
|
||
|
groupParent.getLineText()) != 0) {
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"Line #i text does not match:",
|
||
|
group.getParentLine()->getLineNum());
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"\"%s\"",
|
||
|
group.getParentLine()->getLineText());
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"\"%s\"",
|
||
|
groupParent.getLineText());
|
||
|
|
||
|
}
|
||
|
//(strcmp(group.getParentLine()->getLineText(),
|
||
|
// groupParent.getLineText()) == 0)) {
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"Found #%i : %s",
|
||
|
groupParent.getLineNum(),
|
||
|
groupParent.getLineText());
|
||
|
return iter;
|
||
|
}
|
||
|
}
|
||
|
return end();
|
||
|
}
|
||
|
|
||
|
bool ArMapFileLineSet::calculateChanges(ArMapFileLineSet &origLines,
|
||
|
ArMapFileLineSet &newLines,
|
||
|
ArMapFileLineSet *deletedLinesOut,
|
||
|
ArMapFileLineSet *addedLinesOut,
|
||
|
bool isCheckChildren)
|
||
|
{
|
||
|
if ((deletedLinesOut == NULL) || (addedLinesOut == NULL)) {
|
||
|
return false;
|
||
|
}
|
||
|
ArMapFileLineGroupCompare compare;
|
||
|
ArMapFileLineGroupLineNumCompare compareLineNums;
|
||
|
|
||
|
std::sort(origLines.begin(), origLines.end(), compare);
|
||
|
std::sort(newLines.begin(), newLines.end(), compare);
|
||
|
|
||
|
set_difference(origLines.begin(), origLines.end(),
|
||
|
newLines.begin(), newLines.end(),
|
||
|
std::inserter(*deletedLinesOut,
|
||
|
deletedLinesOut->begin()),
|
||
|
compare);
|
||
|
|
||
|
set_difference(newLines.begin(), newLines.end(),
|
||
|
origLines.begin(), origLines.end(),
|
||
|
std::inserter(*addedLinesOut,
|
||
|
addedLinesOut->begin()),
|
||
|
compare);
|
||
|
|
||
|
if (isCheckChildren) {
|
||
|
|
||
|
ArMapFileLineSet unchangedOrigLines;
|
||
|
ArMapFileLineSet unchangedNewLines;
|
||
|
|
||
|
set_difference(origLines.begin(), origLines.end(),
|
||
|
deletedLinesOut->begin(), deletedLinesOut->end(),
|
||
|
std::inserter(unchangedOrigLines,
|
||
|
unchangedOrigLines.begin()),
|
||
|
compare);
|
||
|
|
||
|
set_difference(newLines.begin(), newLines.end(),
|
||
|
addedLinesOut->begin(), addedLinesOut->end(),
|
||
|
std::inserter(unchangedNewLines,
|
||
|
unchangedNewLines.begin()),
|
||
|
compare);
|
||
|
|
||
|
ArMapFileLineCompare compareLine;
|
||
|
|
||
|
for (ArMapFileLineSet::iterator iterO = unchangedOrigLines.begin(),
|
||
|
iterN = unchangedNewLines.begin();
|
||
|
( (iterO != unchangedOrigLines.end()) &&
|
||
|
(iterN != unchangedNewLines.end()) );
|
||
|
iterO++, iterN++) {
|
||
|
|
||
|
ArMapFileLineGroup &origGroup = *iterO;
|
||
|
ArMapFileLineGroup &newGroup = *iterN;
|
||
|
|
||
|
std::sort(origGroup.getChildLines()->begin(),
|
||
|
origGroup.getChildLines()->end(),
|
||
|
compareLine);
|
||
|
std::sort(newGroup.getChildLines()->begin(),
|
||
|
newGroup.getChildLines()->end(),
|
||
|
compareLine);
|
||
|
|
||
|
ArMapFileLineSet tempDeletedLines;
|
||
|
ArMapFileLineSet tempAddedLines;
|
||
|
|
||
|
set_difference(origGroup.getChildLines()->begin(),
|
||
|
origGroup.getChildLines()->end(),
|
||
|
newGroup.getChildLines()->begin(),
|
||
|
newGroup.getChildLines()->end(),
|
||
|
std::inserter(tempDeletedLines,
|
||
|
tempDeletedLines.begin()),
|
||
|
compareLine);
|
||
|
|
||
|
set_difference(newGroup.getChildLines()->begin(),
|
||
|
newGroup.getChildLines()->end(),
|
||
|
origGroup.getChildLines()->begin(),
|
||
|
origGroup.getChildLines()->end(),
|
||
|
std::inserter(tempAddedLines,
|
||
|
tempAddedLines.begin()),
|
||
|
compareLine);
|
||
|
|
||
|
// TODO: Right now just sending the entire group -- but someday
|
||
|
// we may just want to send the lines that have changed within
|
||
|
// the group (plus the group heading).
|
||
|
if (!tempDeletedLines.empty() || !tempAddedLines.empty()) {
|
||
|
|
||
|
deletedLinesOut->push_back(origGroup);
|
||
|
addedLinesOut->push_back(newGroup);
|
||
|
|
||
|
} // end if child changes
|
||
|
|
||
|
} // end for each unchanged line
|
||
|
|
||
|
} // end if check children
|
||
|
|
||
|
std::sort(deletedLinesOut->begin(), deletedLinesOut->end(), compareLineNums);
|
||
|
std::sort(addedLinesOut->begin(), addedLinesOut->end(), compareLineNums);
|
||
|
|
||
|
return true;
|
||
|
|
||
|
} // end method calculateChanges
|
||
|
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// ArMapChangeDetails
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
void ArMapChangeDetails::createChildArgMap()
|
||
|
{
|
||
|
myInfoNameToMapOfChildArgsMap["MapInfo:"]["ArgDesc"] = true;
|
||
|
|
||
|
myInfoNameToMapOfChildArgsMap["TaskInfo:"]["ArgDesc"] = true;
|
||
|
|
||
|
myInfoNameToMapOfChildArgsMap["RouteInfo:"]["Task"] = true;
|
||
|
myInfoNameToMapOfChildArgsMap["RouteInfo:"]["GoalTask"] = true;
|
||
|
myInfoNameToMapOfChildArgsMap["RouteInfo:"]["MacroTask"] = true;
|
||
|
myInfoNameToMapOfChildArgsMap["RouteInfo:"]["_goto"] = true;
|
||
|
myInfoNameToMapOfChildArgsMap["RouteInfo:"]["_goalBefore"] = true;
|
||
|
myInfoNameToMapOfChildArgsMap["RouteInfo:"]["_goalAfter"] = true;
|
||
|
myInfoNameToMapOfChildArgsMap["RouteInfo:"]["_everyBefore"] = true;
|
||
|
myInfoNameToMapOfChildArgsMap["RouteInfo:"]["_everyAfter"] = true;
|
||
|
|
||
|
myInfoNameToMapOfChildArgsMap["SchedTaskInfo:"]["ArgDesc"] = true;
|
||
|
|
||
|
myInfoNameToMapOfChildArgsMap["SchedInfo:"]["Route"] = true;
|
||
|
myInfoNameToMapOfChildArgsMap["SchedInfo:"]["SchedTask"] = true;
|
||
|
|
||
|
} // end method createChildArgMap
|
||
|
|
||
|
ArMapChangeDetails::ArMapScanChangeDetails::ArMapScanChangeDetails() :
|
||
|
myChangedPoints(),
|
||
|
myChangedLineSegments(),
|
||
|
myChangedSummaryLines()
|
||
|
{
|
||
|
} // end constructor
|
||
|
|
||
|
ArMapChangeDetails::ArMapScanChangeDetails::~ArMapScanChangeDetails()
|
||
|
{
|
||
|
// TODO
|
||
|
|
||
|
} // end destructor
|
||
|
|
||
|
AREXPORT ArMapChangeDetails::ArMapChangeDetails() :
|
||
|
myMutex(),
|
||
|
myOrigMapId(),
|
||
|
myNewMapId(),
|
||
|
myInfoNameToMapOfChildArgsMap(),
|
||
|
myScanTypeList(),
|
||
|
myScanTypeToChangesMap(),
|
||
|
myNullScanTypeChanges(),
|
||
|
myChangedSupplementLines(),
|
||
|
myChangedObjectLines(),
|
||
|
myInfoToChangeMaps()
|
||
|
{
|
||
|
myMutex.setLogName("ArMapChangeDetails");
|
||
|
|
||
|
createChildArgMap();
|
||
|
|
||
|
} // end ctor
|
||
|
|
||
|
AREXPORT ArMapChangeDetails::ArMapChangeDetails
|
||
|
(const ArMapChangeDetails &other) :
|
||
|
myMutex(),
|
||
|
myOrigMapId(other.myOrigMapId),
|
||
|
myNewMapId(other.myNewMapId),
|
||
|
myInfoNameToMapOfChildArgsMap(),
|
||
|
myScanTypeList(other.myScanTypeList),
|
||
|
myScanTypeToChangesMap(),
|
||
|
myNullScanTypeChanges(),
|
||
|
myChangedSupplementLines(),
|
||
|
myChangedObjectLines(),
|
||
|
myInfoToChangeMaps()
|
||
|
{
|
||
|
myMutex.setLogName("ArMapChangeDetails");
|
||
|
|
||
|
createChildArgMap();
|
||
|
|
||
|
for (std::map<std::string, ArMapScanChangeDetails*>::const_iterator iter =
|
||
|
other.myScanTypeToChangesMap.begin();
|
||
|
iter != other.myScanTypeToChangesMap.end();
|
||
|
iter++) {
|
||
|
ArMapScanChangeDetails *otherScan = iter->second;
|
||
|
if (otherScan == NULL) {
|
||
|
continue;
|
||
|
}
|
||
|
myScanTypeToChangesMap[iter->first] = new ArMapScanChangeDetails(*otherScan);
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < CHANGE_TYPE_COUNT; i++) {
|
||
|
myChangedSupplementLines[i] = other.myChangedSupplementLines[i];
|
||
|
myChangedObjectLines[i] = other.myChangedObjectLines[i];
|
||
|
myInfoToChangeMaps[i] = other.myInfoToChangeMaps[i];
|
||
|
}
|
||
|
|
||
|
} // end copy ctor
|
||
|
|
||
|
AREXPORT ArMapChangeDetails &ArMapChangeDetails::operator=
|
||
|
(const ArMapChangeDetails &other)
|
||
|
{
|
||
|
if (this != &other) {
|
||
|
|
||
|
myOrigMapId = other.myOrigMapId;
|
||
|
myNewMapId = other.myNewMapId;
|
||
|
myScanTypeList = other.myScanTypeList;
|
||
|
|
||
|
ArUtil::deleteSetPairs(myScanTypeToChangesMap.begin(),
|
||
|
myScanTypeToChangesMap.end());
|
||
|
myScanTypeToChangesMap.clear();
|
||
|
|
||
|
for (std::map<std::string, ArMapScanChangeDetails*>::const_iterator iter =
|
||
|
other.myScanTypeToChangesMap.begin();
|
||
|
iter != other.myScanTypeToChangesMap.end();
|
||
|
iter++) {
|
||
|
ArMapScanChangeDetails *otherScan = iter->second;
|
||
|
if (otherScan == NULL) {
|
||
|
continue;
|
||
|
}
|
||
|
myScanTypeToChangesMap[iter->first] = new ArMapScanChangeDetails(*otherScan);
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < CHANGE_TYPE_COUNT; i++) {
|
||
|
myChangedSupplementLines[i] = other.myChangedSupplementLines[i];
|
||
|
myChangedObjectLines[i] = other.myChangedObjectLines[i];
|
||
|
myInfoToChangeMaps[i] = other.myInfoToChangeMaps[i];
|
||
|
}
|
||
|
|
||
|
}
|
||
|
return *this;
|
||
|
|
||
|
} // end operator=
|
||
|
|
||
|
|
||
|
AREXPORT ArMapChangeDetails::~ArMapChangeDetails()
|
||
|
{
|
||
|
ArUtil::deleteSetPairs(myScanTypeToChangesMap.begin(),
|
||
|
myScanTypeToChangesMap.end());
|
||
|
}
|
||
|
|
||
|
|
||
|
AREXPORT bool ArMapChangeDetails::getOrigMapId(ArMapId *mapIdOut)
|
||
|
{
|
||
|
if (mapIdOut == NULL) {
|
||
|
return false;
|
||
|
}
|
||
|
*mapIdOut = myOrigMapId;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
AREXPORT bool ArMapChangeDetails::getNewMapId(ArMapId *mapIdOut)
|
||
|
{
|
||
|
if (mapIdOut == NULL) {
|
||
|
return false;
|
||
|
}
|
||
|
*mapIdOut = myNewMapId;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
AREXPORT void ArMapChangeDetails::setOrigMapId(const ArMapId &mapId)
|
||
|
{
|
||
|
myOrigMapId = mapId;
|
||
|
myOrigMapId.log("ArMapChangeDetails::setOrigMapId");
|
||
|
}
|
||
|
|
||
|
AREXPORT void ArMapChangeDetails::setNewMapId(const ArMapId &mapId)
|
||
|
{
|
||
|
myNewMapId = mapId;
|
||
|
myNewMapId.log("ArMapChangeDetails::setNewMapId");
|
||
|
}
|
||
|
|
||
|
|
||
|
AREXPORT std::list<std::string> *ArMapChangeDetails::getScanTypes()
|
||
|
{
|
||
|
return &myScanTypeList;
|
||
|
}
|
||
|
|
||
|
AREXPORT std::vector<ArPose> *ArMapChangeDetails::getChangedPoints
|
||
|
(MapLineChangeType change,
|
||
|
const char *scanType)
|
||
|
{
|
||
|
ArMapScanChangeDetails *scanChange = getScanChangeDetails(scanType);
|
||
|
return &scanChange->myChangedPoints[change];
|
||
|
//return &myChangedPoints[change];
|
||
|
}
|
||
|
|
||
|
AREXPORT std::vector<ArLineSegment> *ArMapChangeDetails::getChangedLineSegments
|
||
|
(MapLineChangeType change,
|
||
|
const char *scanType)
|
||
|
{
|
||
|
ArMapScanChangeDetails *scanChange = getScanChangeDetails(scanType);
|
||
|
return &scanChange->myChangedLineSegments[change];
|
||
|
//return &myChangedLineSegments[change];
|
||
|
}
|
||
|
|
||
|
AREXPORT ArMapFileLineSet *ArMapChangeDetails::getChangedSummaryLines
|
||
|
(MapLineChangeType change,
|
||
|
const char *scanType)
|
||
|
{
|
||
|
ArMapScanChangeDetails *scanChange = getScanChangeDetails(scanType);
|
||
|
return &scanChange->myChangedSummaryLines[change];
|
||
|
//return &myChangedSummaryLines[change];
|
||
|
}
|
||
|
|
||
|
AREXPORT ArMapFileLineSet *ArMapChangeDetails::getChangedSupplementLines
|
||
|
(MapLineChangeType change)
|
||
|
{
|
||
|
return &myChangedSupplementLines[change];
|
||
|
}
|
||
|
|
||
|
AREXPORT ArMapFileLineSet *ArMapChangeDetails::getChangedObjectLines
|
||
|
(MapLineChangeType change)
|
||
|
{
|
||
|
return &myChangedObjectLines[change];
|
||
|
}
|
||
|
|
||
|
AREXPORT ArMapFileLineSet *ArMapChangeDetails::getChangedInfoLines
|
||
|
(const char *infoName,
|
||
|
MapLineChangeType change)
|
||
|
{
|
||
|
if (ArUtil::isStrEmpty(infoName)) {
|
||
|
ArLog::log(ArLog::Normal, "ArMapChangeDetails::getChangedInfoLines() null info name");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
std::map<std::string, ArMapFileLineSet>::iterator iter = myInfoToChangeMaps[change].find(infoName);
|
||
|
if (iter == myInfoToChangeMaps[change].end()) {
|
||
|
myInfoToChangeMaps[change][infoName] = ArMapFileLineSet();
|
||
|
iter = myInfoToChangeMaps[change].find(infoName);
|
||
|
}
|
||
|
return &(iter->second);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
AREXPORT bool ArMapChangeDetails::isChildArg(const char *infoName,
|
||
|
ArArgumentBuilder *arg) const
|
||
|
{
|
||
|
if ((arg == NULL) ||
|
||
|
(arg->getArgc() < 1)) {
|
||
|
return false;
|
||
|
}
|
||
|
const char *argText = arg->getArg(0);
|
||
|
|
||
|
return isChildArg(infoName, argText);
|
||
|
}
|
||
|
|
||
|
|
||
|
AREXPORT bool ArMapChangeDetails::isChildArg(const char *infoName,
|
||
|
const char *argText) const
|
||
|
{
|
||
|
if (ArUtil::isStrEmpty(infoName) || ArUtil::isStrEmpty(argText)) {
|
||
|
return false;
|
||
|
}
|
||
|
std::map<std::string, std::map<std::string, bool> >::const_iterator iter1 =
|
||
|
myInfoNameToMapOfChildArgsMap.find(infoName);
|
||
|
if (iter1 == myInfoNameToMapOfChildArgsMap.end()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
std::map<std::string, bool>::const_iterator iter2 = iter1->second.find(argText);
|
||
|
if (iter2 != iter1->second.end()) {
|
||
|
return iter2->second;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
|
||
|
} // end method isChildArg
|
||
|
|
||
|
ArMapChangeDetails::ArMapScanChangeDetails *ArMapChangeDetails::getScanChangeDetails
|
||
|
(const char *scanType)
|
||
|
{
|
||
|
ArMapScanChangeDetails *scanChanges = NULL;
|
||
|
|
||
|
if (scanType != NULL) {
|
||
|
|
||
|
std::map<std::string, ArMapScanChangeDetails*>::iterator iter =
|
||
|
myScanTypeToChangesMap.find(scanType);
|
||
|
if (iter != myScanTypeToChangesMap.end()) {
|
||
|
scanChanges = iter->second;
|
||
|
}
|
||
|
else {
|
||
|
/**
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"ArMapChangeDetails::getScanChangeDetails() adding details for scan type %s",
|
||
|
scanType);
|
||
|
**/
|
||
|
|
||
|
if (ArUtil::isStrEmpty(scanType)) {
|
||
|
ArLog::log(ArLog::Verbose,
|
||
|
"ArMapChangeDetails::getScanChangeDetails() adding empty scan type%s",
|
||
|
scanType);
|
||
|
}
|
||
|
|
||
|
scanChanges = new ArMapScanChangeDetails();
|
||
|
myScanTypeToChangesMap[scanType] = scanChanges;
|
||
|
|
||
|
myScanTypeList.push_back(scanType);
|
||
|
}
|
||
|
|
||
|
} // end if scanType not null
|
||
|
|
||
|
if (scanChanges == NULL) {
|
||
|
scanChanges = &myNullScanTypeChanges;
|
||
|
}
|
||
|
return scanChanges;
|
||
|
} // end method getScanChangeDetails
|
||
|
|
||
|
|
||
|
AREXPORT std::list<std::string> ArMapChangeDetails::findChangedInfoNames() const
|
||
|
{
|
||
|
std::list<std::string> changedInfoNames;
|
||
|
std::map<std::string, bool> infoNameToBoolMap;
|
||
|
|
||
|
for (int change = 0; change < CHANGE_TYPE_COUNT; change++) {
|
||
|
for (std::map<std::string, ArMapFileLineSet>::const_iterator iter = myInfoToChangeMaps[change].begin();
|
||
|
iter != myInfoToChangeMaps[change].end();
|
||
|
iter++) {
|
||
|
const ArMapFileLineSet &fileLineSet = iter->second;
|
||
|
if (!fileLineSet.empty()) {
|
||
|
infoNameToBoolMap[iter->first] = true;
|
||
|
}
|
||
|
}
|
||
|
} // end for each change type
|
||
|
|
||
|
for (std::map<std::string, bool>::const_iterator iter2 = infoNameToBoolMap.begin();
|
||
|
iter2 != infoNameToBoolMap.end();
|
||
|
iter2++) {
|
||
|
changedInfoNames.push_back(iter2->first);
|
||
|
} // end for each info type
|
||
|
|
||
|
return changedInfoNames;
|
||
|
|
||
|
} // end method getChangedInfoTypes
|
||
|
|
||
|
|
||
|
AREXPORT void ArMapChangeDetails::log()
|
||
|
{
|
||
|
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"");
|
||
|
|
||
|
for (int t = 0; t < CHANGE_TYPE_COUNT; t++) {
|
||
|
|
||
|
MapLineChangeType change = (MapLineChangeType) t;
|
||
|
|
||
|
switch (t) {
|
||
|
case DELETIONS:
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"---- DELETED MAP LINES --------------");
|
||
|
break;
|
||
|
case ADDITIONS:
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"---- ADDED MAP LINES ----------------");
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (std::list<std::string>::iterator iter2 = myScanTypeList.begin();
|
||
|
iter2 != myScanTypeList.end();
|
||
|
iter2++) {
|
||
|
|
||
|
const char *scanType = (*iter2).c_str();
|
||
|
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"%s Point Count: %i",
|
||
|
scanType,
|
||
|
getChangedPoints(change, scanType)->size());
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"%s Line Segment Count: %i",
|
||
|
scanType,
|
||
|
getChangedLineSegments(change, scanType)->size());
|
||
|
|
||
|
|
||
|
ArLog::log(ArLog::Normal,
|
||
|
"");
|
||
|
|
||
|
ArMapFileLineSet *changedSummaryLines = getChangedSummaryLines(change,
|
||
|
scanType);
|
||
|
if (!changedSummaryLines->empty()) {
|
||
|
std::string scanTypeSummary = scanType;
|
||
|
scanTypeSummary += " ";
|
||
|
scanTypeSummary += "Summary Lines";
|
||
|
|
||
|
changedSummaryLines->log(scanTypeSummary.c_str());
|
||
|
}
|
||
|
} // end for each scan type
|
||
|
|
||
|
if (!myChangedSupplementLines[t].empty()) {
|
||
|
myChangedSupplementLines[t].log("Map Supplement Lines");
|
||
|
}
|
||
|
|
||
|
if (!myChangedObjectLines[t].empty()) {
|
||
|
myChangedObjectLines[t].log("Map Object Lines");
|
||
|
}
|
||
|
|
||
|
for (std::map<std::string, ArMapFileLineSet>::iterator iter = myInfoToChangeMaps[t].begin();
|
||
|
iter != myInfoToChangeMaps[t].end();
|
||
|
iter++) {
|
||
|
ArMapFileLineSet &fileLineSet = iter->second;
|
||
|
if (!fileLineSet.empty()) {
|
||
|
fileLineSet.log(" ");
|
||
|
}
|
||
|
}
|
||
|
} // end for each change type
|
||
|
} // end method log
|
||
|
|
||
|
AREXPORT void ArMapChangeDetails::lock()
|
||
|
{
|
||
|
myMutex.lock();
|
||
|
}
|
||
|
|
||
|
AREXPORT void ArMapChangeDetails::unlock()
|
||
|
{
|
||
|
myMutex.unlock();
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------
|
||
|
// ArMapChangedHelper
|
||
|
// ------------------------------------------------------------------------------
|
||
|
|
||
|
AREXPORT ArMapChangedHelper::ArMapChangedHelper() :
|
||
|
myMapChangedLogLevel(ArLog::Verbose),
|
||
|
myMapChangedCBList(),
|
||
|
myPreMapChangedCBList()
|
||
|
{
|
||
|
myMapChangedCBList.setName("MapChangedHelper");
|
||
|
myPreMapChangedCBList.setName("PreMapChangedHelper");
|
||
|
}
|
||
|
|
||
|
AREXPORT ArMapChangedHelper::~ArMapChangedHelper()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
AREXPORT void ArMapChangedHelper::invokeMapChangedCallbacks(void)
|
||
|
{
|
||
|
ArLog::LogLevel level = myMapChangedLogLevel;
|
||
|
|
||
|
myPreMapChangedCBList.setLogLevel(level);
|
||
|
myPreMapChangedCBList.invoke();
|
||
|
|
||
|
myMapChangedCBList.setLogLevel(level);
|
||
|
myMapChangedCBList.invoke();
|
||
|
|
||
|
} // end method invokeMapChangedCallbacks
|
||
|
|
||
|
|
||
|
AREXPORT void ArMapChangedHelper::addMapChangedCB(ArFunctor *functor,
|
||
|
int position)
|
||
|
{
|
||
|
myMapChangedCBList.addCallback(functor, position);
|
||
|
} // end method addMapChangedCB
|
||
|
|
||
|
AREXPORT void ArMapChangedHelper::remMapChangedCB(ArFunctor *functor)
|
||
|
{
|
||
|
myMapChangedCBList.remCallback(functor);
|
||
|
|
||
|
} // end method remMapChangedCB
|
||
|
|
||
|
|
||
|
AREXPORT void ArMapChangedHelper::addPreMapChangedCB(ArFunctor *functor,
|
||
|
int position)
|
||
|
{
|
||
|
myPreMapChangedCBList.addCallback(functor, position);
|
||
|
} // end method addPreMapChangedCB
|
||
|
|
||
|
|
||
|
AREXPORT void ArMapChangedHelper::remPreMapChangedCB(ArFunctor *functor)
|
||
|
{
|
||
|
myPreMapChangedCBList.remCallback(functor);
|
||
|
|
||
|
} // end method remPreMapChangedCB
|
||
|
|
||
|
|
||
|
AREXPORT void ArMapChangedHelper::setMapChangedLogLevel(ArLog::LogLevel level)
|
||
|
{
|
||
|
myMapChangedLogLevel = level;
|
||
|
|
||
|
} // end method setMapChangedLogLevel
|
||
|
|
||
|
|
||
|
AREXPORT ArLog::LogLevel ArMapChangedHelper::getMapChangedLogLevel(void)
|
||
|
{
|
||
|
return myMapChangedLogLevel;
|
||
|
|
||
|
} // end method getMapChangedLogLevel
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|