Added Files:
atomicint.h counter.h kncircularmapping.h knconsistenthash.h
kncrashhandler.h kncrypt.h knerror.h knexportlibraryknutil.h
knhash.h knlog.h knmarkuputil.h knmemory.h knmutex.h
knnetwork.h knnewdelete.h knpattern.h knperfstatistics.h
knregex.h knrwlock.h knrwlogginglock.h knset.h knsett.h
knsleep.h knsmartref.h knstring.h knstringtokenizer.h
knstrops.h knsysutility.h kntclargs.h kntclerrors.h
kntclfile.h kntclinterp.h kntemplateuri.h kntime.h kntypes.h
knurl.h mtrand.h randomnumber.h shahash.h simplecache.h
simpleheap.h simpleiterator.h simplelist.h simplemap.h
simplenull.h simplequeue.h simpleset.h simplesynccache.h
simplesyncmap.h simplesyncvector.h simpletraits.h
simplevector.h uuidgenerator.h
Log Message:
Added this library to the AOLServer.com repository. It contains a number of C/C++ utilities, some of which integrate into AOLServer, and many of which standalone. A portion of the library is required for the knregistration module, which will be checked in next.
I believe this compiles fine in "native" AOLServer, but it has not been tested recently.
--- NEW FILE: atomicint.h ---
#ifndef ATOMICINT_H
#define ATOMICINT_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
/*
* Object supporting atomic integer operations.
*/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
class EXPORT_LIBRARY_KNUTIL AtomicInt
{
public:
/*
* Constructors/destructor.
*/
inline AtomicInt(int cnt=0) : m_cnt(cnt){};
inline AtomicInt(const AtomicInt &atom):m_cnt(atom.m_cnt){};
inline ~AtomicInt(){};
/*
* Set the object to an arbitrary value.
*/
inline AtomicInt &operator=(const AtomicInt &atom) {m_cnt = atom.m_cnt;return *this;};
inline AtomicInt &operator=(int cnt) {m_cnt = cnt;return *this;}
/*
* Increment/decrement the object by an arbitrary value.
*/
int operator+=(int cnt);
int operator-=(int cnt);
/*
* Prefix and postfix increment.
*/
int operator++();
int operator++(int);
/*
* Prefix and postfix decrement.
*/
int operator--();
int operator--(int);
/*
* Object returned as an integer.
*/
inline operator int() const { return m_cnt; }
/*
* Decrement the object, and return true if the result is 0.
*/
bool decrementAndTest();
/*
* Increment the object, without returning the result.
*/
void increment();
private:
int m_cnt;
};
#endif /* ATOMICINT_H */
--- NEW FILE: counter.h ---
#ifndef COUNTER_H
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define COUNTER_H
#include "knutil/knexportlibraryknutil.h"
#include "knutil/atomicint.h"
#include "knutil/knmutex.h"
class EXPORT_LIBRARY_KNUTIL Counter
{
public:
Counter(int c = 1);
~Counter();
AtomicInt count;
};
#endif /* COUNTER_H */
--- NEW FILE: kncircularmapping.h ---
#ifndef KN_CIRCULAR_MAPPING_H
#define KN_CIRCULAR_MAPPING_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include <limits.h>
#include <map>
#include <string>
#include <vector>
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knset.h"
class Bucket;
class ReplicaPoint;
class EXPORT_LIBRARY_KNUTIL KnCircularMapping
{
public:
KnCircularMapping();
virtual ~KnCircularMapping();
typedef unsigned int PointT;
// Add a bucket
bool addBucket(const char* bucketName, std::vector<PointT>& points, double weight);
bool addBucketsFromSet(const KnSet& bucketSet);
// Remove a bucket by name
bool removeBucket(const char* bucketName);
// Remove all buckets
void removeAllBuckets();
// Compute the bucket where the point should go
// and return the bucket's name
std::string assignPointToBucket(PointT point);
int bucketCount();
double getWeight(const std::string& bucketName);
double getTotalWeight();
bool existsBucket(const std::string& bucketName);
private:
typedef std::map<std::string, Bucket*> BucketMap;
typedef BucketMap::iterator BucketMapIterator;
typedef std::map<PointT, ReplicaPoint*> ReplicaMap;
typedef ReplicaMap::iterator ReplicaMapIterator;
typedef std::pair<ReplicaMapIterator, ReplicaMapIterator> ReplicaMapRange;
ReplicaPoint* findOrAddReplicaPoint(PointT point);
ReplicaPoint* findReplicaPoint(PointT point);
bool removeReplicaPoint(PointT point, Bucket* bucket);
Bucket* findBucketForPoint(PointT point);
BucketMap m_buckets;
ReplicaMap m_replicaMap;
double m_totalWeight;
};
#endif
--- NEW FILE: knconsistenthash.h ---
#ifndef KN_CONSISTENT_HASH_H
#define KN_CONSISTENT_HASH_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include <limits.h>
#include <string>
#include <map>
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knset.h"
#include "knutil/knrwlock.h"
#include "knutil/kncircularmapping.h"
#define DEFAULT_REPLICAS_PER_BUCKET 200
class EXPORT_LIBRARY_KNUTIL KnConsistentHash
{
public:
KnConsistentHash(int replicasPerBucket = DEFAULT_REPLICAS_PER_BUCKET, KnCircularMapping::PointT pointInterval = UINT_MAX);
virtual ~KnConsistentHash();
typedef unsigned int IDHash;
// Compute the hash for a bucket
virtual IDHash computeHash(const char* identifier);
// Add a bucket given a hash computed from some unique data
virtual bool addBucket(const char* bucketName, IDHash bucketHash, double weight);
// or by the computing hash from bucket name
bool addBucket(const char* bucketName, double weight);
// Remove a bucket by name
bool removeBucket(const char* bucketName);
// Remove all buckets
void removeAllBuckets();
// Add buckets from a set where the keys are bucket names and the values are weights
bool addBucketsFromSet(const KnSet& bucketSet);
bool setBucketsFromSet(const KnSet& bucketSet);
int bucketCount();
// Given a resource identifier find the point on the circle it belongs to
virtual KnCircularMapping::PointT computePointForResource(const char* identifier);
// Compute the bucket where the point should go and return the bucket's name
std::string assignPointToBucket(KnCircularMapping::PointT point);
// Calculate the point and then assign the point to a bucket for a resource
std::string assignResourceToBucket(const char* identifier);
double getTotalWeight();
private:
bool addBucketUnsafe(const char* bucketName, IDHash bucketHash, double weight);
bool addBucketsFromSetUnsafe(const KnSet& bucketSet);
KnCircularMapping m_mapping;
KnRWLock m_bucketLock;
int m_replicasPerBucket;
KnCircularMapping::PointT m_pointInterval;
};
#endif
--- NEW FILE: kncrashhandler.h ---
#ifndef KNCRASHHANDLER_H
#define KNCRASHHANDLER_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
/**
* Register the KnowNow standard crash handler for this module
* (no-op under Unix or Linux right now). Returns false if could
* not register. Logs any error itself.
*/
extern EXPORT_LIBRARY_KNUTIL bool KnSetCrashHandler() ;
/**
* Set the crash handler's dump location and severity
*/
extern EXPORT_LIBRARY_KNUTIL bool KnSetCrashInfo(const char* location, const char* level) ;
#endif /* KNCRASHHANDLER_H */
--- NEW FILE: kncrypt.h ---
#ifndef KNCRYPT_H
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define KNCRYPT_H
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knstring.h"
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* Encrypt the specified key, perturbed by salt, into buf.
*/
EXPORT_LIBRARY_KNUTIL KnError KnCrypt(KnString &buf, const KnString &key, const KnString &salt);
#endif /* KNCRYPT_H */
--- NEW FILE: knerror.h ---
#ifndef KNERROR_H
#define KNERROR_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
/**
* Error state, and preferred return type.
*/
/**
* In 3.1.9, experimenting with moving to an Apache-style set of
* codes. All codes come from the HTTP error space, with 6xx codes below
* 655 reserved for KnowNow errors.
*
* We shift them left 8 bits, then add in any subcodes we care about.
* This assumes that enums are represented as at least 16 bit unsigned ints.
* To get an HTTP error code, shift right 8. To get a nice string, look
* them up as-is.
*
* This check-in requires recompiling the Modules to get the new constants
*
* Use KnError_Is(constant, code) to do comparisons; we'll figure out how
* to get it inlined, yet available to C modules, yet.
*
* I.e., if you just care if it's found or not, use
* KnError_Is(KnErrorNotFound, status)
* so you don't have to know the encodings.
*/
enum KnError
{
KnErrorSuccess = (200 << 8), ///< Operation succeeded
KnErrorUnauthorized = (401 << 8), ///< Operation requires credentials (401)
KnErrorForbidden = (403 << 8), ///< Credentials are not authorized (403)
KnErrorNotFound = (404 << 8), ///< Something (page) not found
KnErrorNotFound_Event = (404 << 8) + 1,
KnErrorNotFound_Route = (404 << 8) + 2,
KnErrorNotFound_Topic = (404 << 8) + 3,
KnErrorNotFound_Journal = (404 << 8) + 4,
KnErrorNotFound_Parent = (404 << 8) + 5,
KnErrorNotFound_SubTopic = (404 << 8) + 6,
KnErrorNotFound_Filter = (404 << 8) + 7,
KnErrorNotFound_User = (404 << 8) + 10,
KnErrorNotFound_Group = (404 << 8) + 11,
KnErrorFailure = (500 << 8) ///< Operation failed (500)
};
extern EXPORT_LIBRARY_KNUTIL const int KnError_AsHTTP( const KnError code ) ;
#ifdef __cplusplus
inline int KnError_Is(const KnError constant, const KnError code )
{
return (static_cast<unsigned int>(constant) & static_cast<unsigned int>(code)) == static_cast<unsigned int>(constant);
}
#else
#define KnError_Is(c,s) (c == (c & s))
#endif
#endif /* KNERROR_H */
--- NEW FILE: knexportlibraryknutil.h ---
/*
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
* Defines export/import declarations for windows interfaces for this dll.
* It is important to declare this as export when compiling modules in the dll
* and import for modules not in the dll.
*/
#ifndef KNEXPORTLIBRARYKNUTIL_H
#define KNEXPORTLIBRARYKNUTIL_H
#ifdef WIN32
#ifdef EXPORT_LIBRARY_KNUTIL_MODULE
#define EXPORT_LIBRARY_KNUTIL __declspec(dllexport)
#else
#define EXPORT_LIBRARY_KNUTIL __declspec(dllimport)
#endif
#else
#define EXPORT_LIBRARY_KNUTIL
#endif
#endif /* KNEXPORTLIBRARYKNUTIL_H */
--- NEW FILE: knhash.h ---
#ifndef KNHASH_H
#define KNHASH_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* General purpose hashing routine. The seed parameter can be
* any value, such as the previous hash result. Please see
* http://burtleburtle.net/bob/hash/evahash.html for theory.
*/
extern EXPORT_LIBRARY_KNUTIL uint32_t hash32(const void *buf, uint32_t len, uint32_t seed);
extern EXPORT_LIBRARY_KNUTIL uint64_t hash64(const void *buf, uint64_t len, uint64_t seed);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* KNHASH_H */
--- NEW FILE: knlog.h ---
#ifndef KNLOG_H
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define KNLOG_H
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knerror.h"
#include "knutil/knstring.h"
/***************************************************************/
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
/**@defgroup loggingAPI Logging API
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
*
* Log to the server.log file.
* @{
****************************************************************/
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* Logging levels. See KnLog for details on their use.
*/
enum KnLogSeverity
{
KnLogNotice, ///< Something somebody might care about
KnLogWarning, ///< Something somebody should do something about
KnLogError, ///< Something somebody should call KnowNow about
KnLogFatal, ///< Something that will cause a non-recoverable crash
KnLogBug, ///< Something that "asserts" a fault in the code
KnLogDebug, ///< Something only printed when Log_Debug is enabled
KnLogDev ///< Something conditional on a specific debug flag
};
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* Log a message to the router.
*/
extern EXPORT_LIBRARY_KNUTIL KnError KnLog(KnLogSeverity severity, const KnString &msg);
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* Log a printf-style message to the router.
*/
extern EXPORT_LIBRARY_KNUTIL KnError KnLog(KnLogSeverity severity, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
#endif
--- NEW FILE: knmarkuputil.h ---
//////////////////////////////////////////////////////
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
// knmarkuputil.h
//
// (c)2002-2006, KnowNow, Inc. All Rights Reserved.
#ifndef KNMARKUPUTIL_H
#define KNMARKUPUTIL_H
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knstring.h"
#include "knutil/simplemap.h"
typedef SimpleMap<char*, char*> EntityMap;
class EXPORT_LIBRARY_KNUTIL KnMarkupUtil
{
public:
KnMarkupUtil();
~KnMarkupUtil();
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* This expands whitespaces HTML tags from the source string and strip all other tags
*/
bool expandTagsAndStrip(const KnString& source, KnString& transformed);
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* This expands HTML entities from the source string
*/
bool expandHtmlEntities(const KnString& source, KnString& transformed);
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* This removes XML tags from the source string
*/
void stripTags(const KnString& source, KnString& transformed);
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* This removes all tags and HTML expands entities from the source string
*/
bool stripTagsAndExpandEntities(const KnString& source, KnString& transformed);
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* This expands HTML whitespaces tags, removes all other tags and expands HTML entities from the source string
*/
bool expandTagsAndEntities(const KnString& source, KnString& transformed);
// to enable this you will have to add some headers to .cpp and xalan\xerces libraries
// bool renderXmlHtml(const KnString* source, KnString* transformed);
private:
void buildHtlmEntity();
void buildHtlmTags();
EntityMap entityMap;
EntityMap tagMap;
};
#endif /* KNMARKUPUTIL_H */
--- NEW FILE: knmemory.h ---
#ifndef __KNMEMORY_H__
/**
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define __KNMEMORY_H__
/* Copyright (c) 2003 KnowNow, Inc. All rights reserved */
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
#include "knutil/knlog.h"
/**
* The KnMemory module retains memory allocation statistics for C++ code
* linked into the KnowNow server.
*
* Used as a very elementary "leak detector": we count on new and
* decrement on delete, so if everything is wrapped in objects that
* know how to unallocate themselves, we should get zero as we
* exit the KnowNow modules.
*
* Behind the scenes, this module integrates C++ memory allocation
* with the ns_malloc() / ns_free() memory allocation of AOLServer
* by implementing operator new() and operator delete().
*/
class EXPORT_LIBRARY_KNUTIL KnMemory
{
public:
static void increment();
static void decrement();
/** Get the amount of available virtual memory for
* this process (volatile). Expressed in bytes
*/
static size_t getMemoryAvail() ;
/** Get the balance of news against deletes
* May always return 0 in high-performance release configurations
*/
static size_t getBalance();
/** Log memory statistics
*
* If in high-performance release configuration, will print
* a message saying that allocations were not tracked.
*/
static void logStatistics(
KnLogSeverity severity = KnLogNotice //- What severity to log with
);
private:
// Not implemented; makes this a global routine container, since
// the class itself can not be instantiated.
KnMemory();
KnMemory(const KnMemory &);
~KnMemory();
KnMemory &operator=(const KnMemory &);
};
#endif // __KNMEMORY_H__
--- NEW FILE: knmutex.h ---
#ifndef KNMUTEX_H
#define KNMUTEX_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
/*
* Mutual exclusion abstraction.
*/
class EXPORT_LIBRARY_KNUTIL KnMutex
{
public:
KnMutex();
~KnMutex();
/*
* Controls locking/unlocking scope through object lifetime.
* If blocking is false, the object will not attempt to wait
* for an owned lock.
*/
class EXPORT_LIBRARY_KNUTIL KnLock
{
public:
KnLock(KnMutex &mutex, bool blocking=true);
~KnLock();
bool owner() const;
private:
// Not implemented
KnLock();
KnLock(const KnLock &);
KnLock &operator=(const KnLock &);
KnMutex &m_mutex;
bool m_owner;
};
friend class KnMutex::KnLock;
private:
// Not implemented
KnMutex(const KnMutex &);
KnMutex &operator=(const KnMutex &);
bool lock();
bool trylock();
bool unlock();
void *m_impl;
};
#endif /* KNMUTEX_H */
--- NEW FILE: knnetwork.h ---
#ifndef KNNETWORK_H
#define KNNETWORK_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include <vector>
#include <stack>
#include <algorithm>
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knsmartref.h"
#include "knutil/knstring.h"
#include "knutil/simplemap.h"
#include "knutil/knerror.h"
#include "knutil/knlog.h"
#include "knutil/knurl.h"
#include "knutil/knstrops.h"
#include "knutil/kntclinterp.h"
#include "knutil/knstringtokenizer.h"
/* Maintains a registered sets of URL urlspaces that can be used to
* normalize & manage URLs, DNS names, or addresses, comparing them for
* membership in particular sets. Sets are arranged in a forest for
* comparison, so, e.g., we can have:
*
* corpnet
* + extranet
* + liveserver federation
* + cluster
* + node
* <name>
* <name>...
*
* We do our own declarations of these so an individual node that
* belongs to more than one domain can still be recognized as having
* its own topicspace. We have to do this because our API supports
* operations over fully-qualified URIs -- and those URIs might be
* for any reachable name for the hosts in the cluster.
*/
/* These are the reserved network names. We also use the word
* "local" to mean "cluster", but this is somewhat more precise.
*/
class EXPORT_LIBRARY_KNUTIL KnNetworkClassName {
public:
static const KnString localhost ;
static const KnString node ;
static const KnString cluster ;
static const KnString federation ;
};
class EXPORT_LIBRARY_KNUTIL KnUrlSpaceName {
public:
static const KnString topic ;
};
/* Violation of our normal lexical convention:
* I'm directly marking each method with whether it's public
* etc., because I think that makes it easier to maintain the code.
* Follows Wilson (Imperfect C++)
*
* It's really irritating; in the end, I just hid the singleton
* behind static methods, so this could have just as easily just
* been a namespace, instead of a class. Did that because the
* easier-to-write edition (with lots of inlines & templates)
* literally blew up the VS7 compiler. OTOH, now we can
* more gradually expose the internal classes if we need them.
*/
class EXPORT_LIBRARY_KNUTIL KnNetwork {
// ---------------------
// Process initialization
// ---------------------
public:
static KnError configure(const KnSet& configSet, const KnString& urlSpace = KnStringConstants::slash_kn) ;
// ---------------------
// Network class queries
// ---------------------
public:
static bool isNode( const std::string& address ) {
KnString addr(address.c_str(),address.length());
return isNode(addr);
}
public:
static bool isNode( const KnString& address ) {
KnUrl url(address);
return isNode(url);
}
public:
static bool isNode( const KnUrl& url ) {
return isMember(url,KnNetworkClassName::node);
}
public:
static bool isLocal( const std::string& address ) {
KnString addr(address.c_str(),address.length());
return isLocal(addr);
}
public:
static bool isLocal( const KnString& address ) {
KnUrl url(address);
return isLocal(url);
}
public:
static bool isLocal( const KnUrl& url ) ;
public:
static bool isMember( const KnUrl& url, const KnString& network ) ;
public:
static KnError getHttpUri(KnString& root, const KnString& netName);
public:
static KnError getHttpsUri(KnString& root, const KnString& netName) ;
public:
static Tcl_Obj* listNetworks(Tcl_Interp *interp);
public:
/* Should take string for matching with */
static Tcl_Obj* listHosts(Tcl_Interp *interp);
// -------------------------
// Network class management
// -------------------------
public:
static KnError addNetwork(const KnString& newClass, const KnString& inClass, bool hasURI) ;
public:
static KnError addUrlToClass(const KnString& url, const KnString& netName) ;
/* ---------------------
* urlspace query
* -------------------- */
public:
static KnError inSpace( bool& yesno, const std::string& url, const KnString& space = KnUrlSpaceName::topic);
/* ---------------------
* urlspace management
* -------------------- */
public:
static Tcl_Obj* listUrlSpaces(Tcl_Interp *interp) ;
public:
// urlRoot must be relative, single initial /. Should *not* end
// in '/'. Considered adding KnUrlSpace class; seemed to heavy.
// Currently think there's no need to have lookup; urlspace name should == urlroot.
// but coded this way for another level of indirection. Hmm.
static KnError addUrlSpace(const KnString& urlSpace, const KnString& urlRoot) ;
public:
static const KnString* getUrlRoot(KnString& urlSpace) ;
public:
// Add just the prefix to the set of URL mappings; don't add the host.
// This is used for "mappings", where
// a reverse proxy has said that it is mapped to a specific prefix, but
// we don't know that the host part is actually reachable, nor that
// it is shared with any of the rest of our URLspace. E.g.
//
// proxy @ http://www.example.com maps
// /ess to locally name http://xyz.ex.com/kness/live
// /topics to local name http://xyz.ex.com/kn
// We want several things:
// is_topic http://xyz.ex.com/topics/foobar => true
// is_local http://xyz.ex.com/topics/foobar => true
// is_local http://xyz.ex.com/ess/foobar => true
// is_local http://xyz.ex.com/something/else => false
// normalize_topic http://xyz.ex.com/topics/foobar => /kn/foobar
// relative_path http://xyz.ex.com/ess/foobar => /kness/live/foobar
// relative_path http://xyz.ex.com/something/else =>
// http://xyz.ex.com/something/else
static KnError addMapping(const KnString& urlSpace, const KnString& prefix) ;
// ------------------------------
// Combined operations.
//
// Use these as the normal ways to record
// things we learn about how we're accessed
// ------------------------------
public:
// Topicspace should call this with urlspace == its urlroot. Perms and other
// AOLServer filters (as opposed to procs) usually should leave it null, since they
// don't necessarily know the root of the pattern they're manageing.
// should keep it 0, since it doesn't know what U
static KnError KnNetwork::addHostAlias(Ns_Conn *conn, const KnString *urlspace = 0) ;
public:
// Adds the location as a mapping for the urlspace name "urlspace",
// Also adds the host & port component of the URL to the network class class.
// Used as the replacement for typical
// KnProperties::addHostAlias(KnString prefix); it's a convenience entry point in
// the case where you know scheme & host part of the URL address this server.
//
// It's convenient, but not always correct; in some mapping scenarios, it's
// perfectly possible, for example, for us to want:
// is_local http://xyz.ex.com/kn/foobar => true
// is_local http://xyz.ex.com/some/thing => false
// We do this by only registering the mapping. See "addMapping"
static KnError addUrl( const KnString& urlspace, const KnString& prefix, const KnString& network = KnNetworkClassName::cluster ) ;
public:
// This is like addUrl, but it takes an url with no path, and extends it with the
// urlroot for the given urlspace before registering it as a mapping. Useful
// during configuration, where we know the addresses and want to factor the basic
// urlroot across all those addresses. Adds to the default network if none specified.
static KnError addHostWithPrefix( const KnString& urlSpace, const KnString& url, const KnString& network = KnStringConstants::empty) ;
/* ----------------------------------------*/
/* URL normalization & relativization */
/* ----------------------------------------*/
// Creates *canonicalized*, *normalized*,
// path-absolute URI IFF the given URL is known
// to be cluster-local & in some prefix associated
// with the urlspace. As part of canonicalizing,
// any matching prefix is _replaced_ with the first prefix
// registered for that urlspace. If no matching
// prefix is given, the canonical prefix is prepended.
//
// Note that KnProperties::formatLocation contains
// additional logic associated with any event replicated
// by the clustering code. I hope that can be deleted
// now (but see GS' comment regarding TD3095).
//
// Could certainly be made faster by removing some
// KnString uses and using std::string. But I'm out of time.
public:
static KnError formatTopicLocation(
KnString& location,
const KnString& urlSpace = KnUrlSpaceName::topic
);
public:
static KnError formatNonNetworkRelativeRef(KnString& location,size_t inputPfxLen) ;
// Accepts a string that should be a "path" (and tail and query & fragment) part
// with no "network" component (recall that there are "network relative refs" which
// look like '//user:info@host:port/pathpart'; those won't work here).
//
// Normalizes just the path & tail part, but treats '?' & '#' as legal
// characters inside components, rather than the termination of the path part.
// This is required for topicnames, since they've always worked that way
// and we have lots of existing topics with un-escaped '?' in their names.
//
// Treats the first inputPfxLen chars as "can't touch these".
public:
static KnError formatTopicRelativeRef(KnString& location,size_t inputPfxLen);
};
#endif /* KNNETWORK_H */
--- NEW FILE: knnewdelete.h ---
#ifndef KNNEWDELETE_H
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define KNNEWDELETE_H
#ifndef KNMODULE
/* You should define your module name before including this file.
* Right now, it's unused, but we may really want it in future.
*/
static unsigned int foo ( unsigned int bar ) { return 0 ; } ; // Generate a warning
#endif
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* This is some wierd code.
*
* Operator new & operator delete have single linkage scope.
*
* That means they only get as big as one DLL or one .so; you can't
* ensure that the same one is used in all dynamic libraries easily.
* See Matthew Wilson, Imperfect C++, p. 130
*
* So to get a global counter, we need to have (a) global counters
* (defined in knmemory.cpp), but local routines.
*
* This is now a pretty fair amount of CPU overhead per allocation.
* (though still constant time).
* We may need to optimize things a bit better in future.
*
* To do that, we #include this file once in all our modules.
* Yuck!!!
*
* -- ReC 05/08/03, updated 7 Apr 06
*/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
#include "knutil/atomicint.h"
#include "knutil/knmemory.h"
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* C++ wrapper for ns_malloc
*
* To get the benefits of using the ns_malloc routine (integrated error
* messages, clearing cache memory when approaching fullness), we override
* the C++ memory allocation system to use ns_malloc. Of course, ns_malloc
* eventually uses malloc underneath it, which gives us the opportunity to
* use ATS, Purify, or other allocation systems.
*
* We need to link this into all our C++ DLLs. We also need to examine our
* topic & event API; if we support new & deletion of refcounted structures
* in customer-written filters, we'll want to encourage them to use these
* wrappers.
*/
void * operator new ( size_t size )
{
#if 0
if (0 == nAllocs)
KnLog(KnLogNotice,"Registering KnowNow ns_malloc wrapper");
#endif
KnMemory::increment() ;
return ns_malloc(size) ;
}
void * operator new[] (size_t size)
{
KnMemory::increment() ;
return ns_malloc(size);
}
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* C++ wrapper for ns_free
*
* To get the benefits of using the ns_malloc routine (integrated error
* messages, clearing cache memory when approaching fullness), we override
* the C++ memory allocation system to use ns_malloc. Of course, ns_malloc
* eventually uses malloc underneath it, which gives us the opportunity to
* use ATS, Purify, or other allocation systems.
*/
void operator delete( void *pFreeThis )
{
ns_free(pFreeThis);
KnMemory::decrement() ;
}
void operator delete[]( void *pFreeThis )
{
ns_free(pFreeThis);
KnMemory::decrement() ;
}
#endif /* KNNEWDELETE_H */
--- NEW FILE: knpattern.h ---
#ifndef KN_PATTERN_H
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define KN_PATTERN_H
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knlog.h"
#include "knutil/knregex.h"
#include "knutil/knrwlock.h"
#include "knutil/knset.h"
#include "knutil/knsmartref.h"
#include "knutil/knstring.h"
#include <vector>
#include <list>
#include <map>
class EXPORT_LIBRARY_KNUTIL KnMatcher
{
public:
KnMatcher(const char* string);
~KnMatcher();
Tcl_Obj* getTclObj();
private:
Tcl_Obj* m_obj;
};
class EXPORT_LIBRARY_KNUTIL KnPattern
{
public:
KnPattern();
KnPattern( const KnString& name );
virtual ~KnPattern() {};
bool isValidRegex() const;
virtual bool match(const char* string) const;
virtual bool match(KnMatcher& matchObj) const;
virtual int getSubCount() const;
virtual bool matchSubs(const char *str, KnSet& result);
bool setRegexPattern(const char* pattern);
bool setRegexPattern(const KnString& pattern);
const KnString& getName() const;
const KnString& getRegexPattern() const;
const KnRegEx& getRegexMatcher() const;
protected:
bool lessSpecificThan(const KnPattern& rhs) const;
KnRegEx m_regex;
KnString m_name;
KnString m_regexPattern;
};
template<class Pattern, class Info>
class IKnPatterns
{
public:
IKnPatterns() {}
virtual ~IKnPatterns() {}
virtual bool findBestMatch( const char* string, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const = 0;
virtual bool findAllMatches( const char* string, std::vector<std::pair<KnSmartRef<Pattern>, KnSmartRef<Info> > >& matches) const = 0;
virtual bool findBestMatchSubs( const char* string, KnSet& subs, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const = 0;
virtual bool findAllMatchesSubs( const char* string, std::vector<std::pair< KnSet*, KnSmartRef<Info> > >& matches) const = 0;
virtual bool findByName( const KnString& name, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const = 0;
virtual bool removeByName( const KnString& name) = 0;
virtual void dump(KnLogSeverity severity = KnLogDev) = 0;
virtual void put(Pattern* pattern, Info* info) = 0;
virtual bool isEmpty() = 0;
};
// MapValue must be a subclass of IKnPatterns
template<class MapKey, class MapValue, class Pattern, class Info>
class KnPatternFinder
{
public:
class ScopedWriteable
{
public:
ScopedWriteable(KnPatternFinder<MapKey,MapValue,Pattern,Info>& pf)
: m_writeLock(pf.m_rwlock)
{
};
private:
KnRWLock::KnWriteLock m_writeLock;
};
friend class KnPatternFinder<MapKey,MapValue,Pattern,Info>::ScopedWriteable;
class ScopedReadable
{
public:
ScopedReadable(KnPatternFinder<MapKey,MapValue,Pattern,Info>& pf)
: m_readLock(pf.m_rwlock)
{
};
private:
KnRWLock::KnReadLock m_readLock;
};
friend class KnPatternFinder<MapKey,MapValue,Pattern,Info>::ScopedWriteable;
MapValue* get( const MapKey& mk) const
{
MapTypeIteratorConst it = m_map.find(mk);
if(it != m_map.end())
return it->second;
return NULL;
}
bool findBestMatch( const MapKey& mk, const char* string, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const
{
MapValue* mv = get(mk);
if(!mv)
return false;
return mv->findBestMatch(string,pattern,info);
}
bool findAllMatches( const MapKey& mk, const char* string, std::vector<std::pair<KnSmartRef<Pattern>, KnSmartRef<Info> > >& matches) const
{
MapValue* mv = get(mk);
if(!mv)
return false;
return mv->findAllMatches(string,matches);
}
bool findBestMatchSubs( const MapKey& mk, const char* string, KnSet& subs, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const
{
MapValue* mv = get(mk);
if(!mv)
return false;
return mv->findBestMatchSubs(string,subs,pattern,info);
}
virtual bool findAllMatchesSubs( const MapKey& mk, const char* string, std::vector<std::pair< KnSet*, KnSmartRef<Info> > >& matches) const
{
MapValue* mv = get(mk);
if(!mv)
return false;
return mv->findAllMatchesSubs(string,matches);
}
bool findByName( const MapKey& mk, const KnString& name, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const
{
MapValue* mv = get(mk);
if(!mv)
return false;
return mv->findByName(name,pattern,info);
}
// remove first found with that name
bool removeByName( const KnString& name)
{
MapValue* value;
bool result = false;
for(MapTypeIterator it = m_map.begin(); it != m_map.end(); )
{
value = it->second;
result = result || (value->removeByName(name));
if(value->isEmpty())
{
m_map.erase(it);
return result;
}
}
return result;
}
bool removeByName( const MapKey& mk, const KnString& name)
{
MapValue* mv = get(mk);
bool result = mv->removeByName(name);
if(mv->isEmpty())
m_map.erase(mk);
return result;
}
void dump(KnLogSeverity severity = KnLogDev) const
{
MapValue* value;
for(MapTypeIteratorConst it = m_map.begin(); it != m_map.end(); it++)
{
value = it->second;
value->dump(severity);
}
}
void dump( const MapKey& mk, KnLogSeverity severity = KnLogDev) const
{
MapValue* mv = get(mk);
mv->dump(severity);
}
void put( const MapKey& mk, Pattern* pattern, Info* info)
{
MapValue* mv = NULL;
MapTypeIterator it = m_map.find(mk);
if(it == m_map.end())
{
mv = new MapValue();
m_map[mk] = mv;
}
else
mv = it->second;
mv->put(pattern,info);
}
int size()
{
return m_map.size();
}
typedef typename std::map<MapKey, MapValue* > MapType;
typedef typename MapType::const_iterator MapTypeIteratorConst;
typedef typename MapType::iterator MapTypeIterator;
private:
KnRWLock m_rwlock;
MapType m_map;
};
template<class Pattern, class Info>
class KnPatternSet : public IKnPatterns<Pattern,Info>
{
public:
KnPatternSet()
{
}
virtual ~KnPatternSet()
{
}
bool isEmpty()
{
return m_patterns.size() == 0;
}
virtual bool findBestMatch( const char* string, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const
{
KnMatcher matcher(string);
for (PatternMapIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if (it->first->match(matcher))
{
pattern = it->first;
info = it->second;
return true;
}
}
return false;
}
virtual bool findAllMatches( const char* string, std::vector<std::pair<KnSmartRef<Pattern>, KnSmartRef<Info> > >& matches) const
{
KnMatcher matcher(string);
bool found = false;
for (PatternMapIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if (it->first->match(matcher))
{
matches.push_back(*it);
found = true;
}
}
return found;
}
virtual bool findBestMatchSubs( const char* string, KnSet& subs, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const
{
for (PatternMapIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if (it->first->matchSubs(string,subs))
{
pattern = it->first;
info = it->second;
return true;
}
}
return false;
}
virtual bool findAllMatchesSubs( const char* string, std::vector<std::pair< KnSet*, KnSmartRef<Info> > >& matches) const
{
bool found = false;
KnSet matched;
for (PatternMapIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if (it->first->matchSubs(string,matched))
{
matches.push_back(std::pair< KnSet*, KnSmartRef<Info> >(new KnSet(matched),it->second));
found = true;
}
}
return found;
}
bool findByName( const KnString& name, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const
{
for (PatternMapIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if (it->first->getName() == name)
{
pattern = it->first;
info = it->second;
return true;
}
}
return false;
}
bool removeByName( const KnString& name)
{
for (PatternMapIteratorNC it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if (it->first->getName() == name)
{
m_patterns.erase(it);
return true;
}
}
return false;
}
void dump(KnLogSeverity severity = KnLogDev)
{
for (PatternMapIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
KnLog(severity,"KnPatternSet: name=[%s] pattern=[%s]",it->first->getName().c_str(),it->first->getRegexPattern().c_str());
}
}
void put(Pattern* pattern, Info* info)
{
m_patterns[KnSmartRef<Pattern>(pattern)] = KnSmartRef<Info>(info);
}
struct PatternLess
{
bool operator()(const KnSmartRef<Pattern> lhs, const KnSmartRef<Pattern> rhs ) const
{
return lhs->lessSpecificThan(rhs.getConstRef());
}
};
typedef typename std::map<KnSmartRef<Pattern>, KnSmartRef<Info>, PatternLess > PatternMap;
typedef typename PatternMap::const_iterator PatternMapIterator;
typedef typename PatternMap::iterator PatternMapIteratorNC;
private:
PatternMap m_patterns;
};
template<class Pattern, class Info>
class KnPatternList : public IKnPatterns<Pattern,Info>
{
public:
KnPatternList()
{
}
virtual ~KnPatternList()
{
}
bool isEmpty()
{
return m_patterns.size();
}
virtual bool findBestMatch( const char* string, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const
{
KnMatcher matcher(string);
for (PatternListIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if(it->first->match(matcher))
{
pattern = it->first;
info = it->second;
return true;
}
}
return false;
}
virtual bool findAllMatches( const char* string, std::vector<std::pair<KnSmartRef<Pattern>, KnSmartRef<Info> > >& matches) const
{
KnMatcher matcher(string);
bool found = false;
for (PatternListIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if (it->first->match(matcher))
{
matches.push_back(*it);
found = true;
}
}
return found;
}
virtual bool findBestMatchSubs( const char* string, KnSet& subs, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const
{
for (PatternListIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if (it->first->matchSubs(string,subs))
{
pattern = it->first;
info = it->second;
return true;
}
}
return false;
}
virtual bool findAllMatchesSubs( const char* string, std::vector<std::pair< KnSet*, KnSmartRef<Info> > >& matches) const
{
bool found = false;
KnSet matched;
for (PatternListIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if (it->first->matchSubs(string,matched))
{
matches.push_back(std::pair< KnSet*, KnSmartRef<Info> >(new KnSet(matched),it->second));
found = true;
}
}
return found;
}
bool findByName( const KnString& name, KnSmartRef<Pattern>& pattern, KnSmartRef<Info>& info) const
{
for (PatternListIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if (it->first->getName() == name)
{
pattern = it->first;
info = it->second;
return true;
}
}
return false;
}
bool removeByName( const KnString& name)
{
for (PatternListIteratorNC it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
if (it->first->getName() == name)
{
m_patterns.erase(it);
return true;
}
}
return false;
}
void dump(KnLogSeverity severity = KnLogDev)
{
for (PatternListIterator it = m_patterns.begin(); it != m_patterns.end(); ++it)
{
KnLog(severity,"KnPatternSet: name=[%s] pattern=[%s]",it->first->getName().c_str(),it->first->getRegexPattern().c_str());
}
}
void put(Pattern* pattern, Info* info)
{
m_patterns.push_back(std::pair<KnSmartRef<Pattern>, KnSmartRef<Info> >(KnSmartRef<Pattern>(pattern),KnSmartRef<Info>(info)));
}
typedef typename std::list<std::pair<KnSmartRef<Pattern>, KnSmartRef<Info> > > PatternList;
typedef typename PatternList::const_iterator PatternListIterator;
typedef typename PatternList::iterator PatternListIteratorNC;
private:
PatternList m_patterns;
};
class EXPORT_LIBRARY_KNUTIL KnUrlPattern : public KnPattern
{
public:
KnUrlPattern( const KnString& name );
KnUrlPattern( const KnString& name, const KnString& urlPattern);
virtual ~KnUrlPattern() {}
bool lessSpecificThan(const KnUrlPattern& rhs) const;
protected:
KnUrlPattern(const KnUrlPattern &);
KnUrlPattern &operator=(const KnUrlPattern &);
class ComponentCounter {
public:
ComponentCounter(KnUrlPattern& pattern) :
m_pattern(pattern),
m_trailers(0),
m_hasCard(false),
m_hasAnyCards(false),
m_discard(false)
{
};
~ComponentCounter()
{
if (!m_discard)
{
m_pattern.m_trailers += m_trailers;
}
}
size_t countPathCard()
{
m_hasAnyCards = true;
m_hasCard = true;
m_trailers = 0 ;
return ++m_pattern.m_pathcards;
};
size_t countSubTopics()
{
return ++m_pattern.m_subtopics;
};
size_t countFileCard()
{
m_hasAnyCards = true;
m_hasCard = true;
m_trailers = 0 ;
return ++m_pattern.m_filecards;
};
size_t countComponent()
{
if (!m_hasCard)
{
if (!m_hasAnyCards)
{
++m_pattern.m_leaders;
}
++m_trailers;
}
m_hasCard = false ;
return m_trailers;
};
void discard(bool dis = true)
{
m_discard = dis ;
};
private:
ComponentCounter(const ComponentCounter &);
ComponentCounter &operator=(const ComponentCounter &);
KnUrlPattern& m_pattern;
size_t m_trailers;
bool m_hasCard;
bool m_hasAnyCards;
bool m_discard;
};
friend class ComponentCounter;
// These are methods used by the constructor, and would have
// been straight functions except it's easier to count the
// cards this way.
virtual bool escape( KnString& putItHer, char aChar);
virtual bool makePathRegex(KnString& putItHere, const KnString& part);
virtual bool makeNoPathRegex(KnString& putItHere, const KnString& part);
size_t m_filecards;
size_t m_pathcards;
size_t m_leaders;
size_t m_trailers;
size_t m_subtopics;
};
#endif
--- NEW FILE: knperfstatistics.h ---
#ifndef KN_PERFSTATISTICS_H
/**
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define KN_PERFSTATISTICS_H
/* Copyright 2006 KnowNow, Inc., Sunnyvale CA 94089 USA, All Rights Reserved */
#include "knutil/knexportlibraryknutil.h"
#include "knutil/atomicint.h"
#include "knutil/knerror.h"
#include "knutil/knmutex.h"
#include "knutil/knstring.h"
typedef long perftimer;
#define KN_ASSERT_PERFORMANCE(a) KN_ASSERT(a)
// #define KN_ASSERT_PERFORMANCE(a) ((void)(0))
class EXPORT_LIBRARY_KNUTIL Histogram
{
public:
const static int RESOLUTION=200;
Histogram(const int low,const int high);
void addInt(const int value, const long weight = 1);
void reset();
void setRange(const int low, const int high);
int percentile(const int percent);
void toString(KnString &result) const;
void writeToFile(FILE *fp) const;
private:
KnMutex mutex_;
int low_;
int range_;
long frequency_[RESOLUTION];
};
// Use this and "%lu" for printfs of perftimers. You'll get milliseconds
// since an unknown epoch
#define KNPF_TIMERCAST static_cast<unsigned long>(perftimer)
// This is ported from the Histogram and related performance classes in the
// Java TestHarness, and shares some of its weaknesses. In particular,
// the category type determines the min/max that the buckets can handle.
//
// If KN_ASSERT_PERFORMANCE is defined, we will fail (crash with dump)
// if a measurement is taken outside the range declared for the statistic.
class EXPORT_LIBRARY_KNUTIL KnPerfStatistic {
public:
enum KnCategoryType {
KnCategory_Performance, // 0 - 10000 ms (suitable for msec intervals)
KnCategory_PerformanceInSeconds // 0 - 1000000 ms (suitable for seconds to minutes)
};
KnPerfStatistic(
const KnString& name,
const KnString& displayName,
KnCategoryType catT);
~KnPerfStatistic();
// Use this pattern rather than ++ / -- since we don't have
// exception handling. I want this interface to able to handle
// licensing by statistic (resource count), so it needs to have
// an error return. KnErrorUnauthorized is returned if the statistic
// can not be incremented because of license restrictions.
KnError incr(perftimer amount = 1);
KnError decr(perftimer amount = 1) { return incr(-(amount)); };
KnError set(perftimer amount);
perftimer begin();
perftimer end(const perftimer start = 0);
const KnString& getKnId() const { return knId_ ; } ;
const KnString& getDisplayName() const { return displayName_ ; };
INT64 getTotal() const { return total_; };
perftimer getMin() const { return min_; };
perftimer getMax() const { return max_; };
int getUnit() const { return unit_; };
int getId() const { return id_; }
const Histogram * getHistogram() const { return histogram_; };
int getValue() const { return value_; };
static void writeToFile();
static void setSystemName(KnString systemName);
static void configure(int, int);
static void configureStatisticsRoll(bool, int, int);
static void setAssertPerformanceOutOfScale(bool value_);
static bool getAssertPerformanceOutOfScale();
#define PERFORMANCE_STATISTICS
#ifdef PERFORMANCE_STATISTICS
#define PERFORMANCE_STATISTICS_DECLARE(name) static KnPerfStatistic name(KnString(#name),KnString(#name),KnPerfStatistic::KnCategory_Performance)
#define PERFORMANCE_STATISTICS_DECLARE_WITH_CATEGORY(name,cat) static KnPerfStatistic name(KnString(#name),KnString(#name),cat)
#define PERFORMANCE_STATISTICS_BEGIN(name) name.begin()
#define PERFORMANCE_STATISTICS_END(name) name.end()
#define PERFORMANCE_STATISTICS_END_WITH_TIME(name, start) name.end(start)
#else
#define PERFORMANCE_STATISTICS_DECLARE(name)
#define PERFORMANCE_STATISTICS_BEGIN(name)
#define PERFORMANCE_STATISTICS_END(name)
#define PERFORMANCE_STATISTICS_END_WITH_TIME(name, start)
#endif
private:
static void toString(KnString &result);
static int find(KnString name);
static void insert(KnPerfStatistic *statistic);
static void writeToFile(FILE *fp);
KnString knId_;
KnString displayName_;
AtomicInt value_;
KnCategoryType category_;
int id_;
INT64 total_;
perftimer min_;
perftimer max_;
int unit_;
Histogram *histogram_;
perftimer start_;
const static int ALLSTATISTICSMAX = 100;
static KnPerfStatistic *allStatistics_[ALLSTATISTICSMAX];
static int allStatisticsCount_;
static KnString systemName_;
static int gCategoryPerformance;
static int gCategoryPerformanceInSeconds;
static bool gLogAssertPerformanceOutOfScale;
// configurable variables wihich controls statistics file rolling
static bool gStatisticsRoll;
static int gClampStatisticsRoll;
static int gMaxBackupStatistics;
};
#endif
--- NEW FILE: knregex.h ---
#ifndef KNREGEX_H
#define KNREGEX_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knstring.h"
#include <string>
#include "tcl.h"
/*
* Regular Expression class. Currently, an invalid expression will silently
* fail, causing match() to always return false.
*/
class EXPORT_LIBRARY_KNUTIL KnRegEx
{
public:
KnRegEx();
KnRegEx(const KnString& expr, bool caseSensitive = true);
KnRegEx(const char* expr, bool caseSensitive = true);
~KnRegEx();
bool setRegexPattern(const KnString& expr, bool caseSensitive = true);
bool setRegexPattern(const char* expr, bool caseSensitive = true);
void clear();
bool isValid() const;
/*
* Determine whether the regex matches the string.
*/
bool match(const KnString &str) const;
bool match(const char *str) const;
bool match(Tcl_Obj* matchObj) const;
/*
* Also compute the matched subexpressions
*/
bool matchSubs(const char *str);
/*
* Determine whether the regex matches a part of the string and return its indices
*/
bool find(const char *str, char*& matchStart, int& matchLen);
bool matchPrefix(const char *str, int& matchLen);
bool matchSuffix(const char *str, int& matchLen);
/*
* Get the range of the subexpression at specified index
* after a succesfull matchSubs
*/
bool getSubRange( int subIndex, char*& matchStart, int& matchLen) const;
private:
// Not implemented
KnRegEx(const KnRegEx &);
KnRegEx &operator=(const KnRegEx &);
void constructRegEx(const char* regex, bool caseSensitive);
Tcl_RegExp m_regex;
Tcl_Obj* m_patObj;
};
#endif /* KNREGEX_H */
--- NEW FILE: knrwlock.h ---
#ifndef KNRWLOCK_H
#define KNRWLOCK_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
/*
* Read/write lock abstraction.
*/
class EXPORT_LIBRARY_KNUTIL KnRWLock
{
public:
KnRWLock();
~KnRWLock();
/*
* Controls locking/unlocking scope through object lifetime.
*/
class EXPORT_LIBRARY_KNUTIL KnReadLock
{
public:
KnReadLock(KnRWLock &lock);
~KnReadLock();
private:
// Not implemented
KnReadLock();
KnReadLock(const KnReadLock &);
KnReadLock &operator=(const KnReadLock &);
KnRWLock &m_lock;
};
class EXPORT_LIBRARY_KNUTIL KnWriteLock
{
public:
KnWriteLock(KnRWLock &lock);
~KnWriteLock();
private:
// Not implemented
KnWriteLock();
KnWriteLock(const KnWriteLock &);
KnWriteLock &operator=(const KnWriteLock &);
KnRWLock &m_lock;
};
friend class KnRWLock::KnReadLock;
friend class KnRWLock::KnWriteLock;
private:
// Not implemented
KnRWLock(const KnRWLock &);
KnRWLock &operator=(const KnRWLock &);
bool lock(bool writer=false);
bool unlock();
void *m_impl;
};
#endif /* KNRWLOCK_H */
--- NEW FILE: knrwlogginglock.h ---
#ifndef LOGGING_AND_OPTIONAL_LOCK
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define LOGGING_AND_OPTIONAL_LOCK
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
#include "knutil/knlog.h"
class EXPORT_LIBRARY_KNUTIL KnRWLoggingLock
{
public:
KnRWLoggingLock(
const char *name = NULL,
bool locking = true,
bool logging = false,
KnLogSeverity loglevel = KnLogNotice
);
~KnRWLoggingLock();
bool setLevel( KnLogSeverity level ) ;
bool setLogging( bool ); // returns earlier setting
bool setLocking( bool ); // returns earlier setting
/*
* Controls locking/unlocking scope through object lifetime.
*/
class EXPORT_LIBRARY_KNUTIL KnReadLock
{
public:
KnReadLock(KnRWLoggingLock &lock);
~KnReadLock();
private:
// Not implemented
KnReadLock();
KnReadLock(const KnReadLock &);
KnReadLock &operator=(const KnReadLock &);
KnRWLoggingLock &m_lock;
};
class EXPORT_LIBRARY_KNUTIL KnWriteLock
{
public:
KnWriteLock(KnRWLoggingLock &lock);
~KnWriteLock();
private:
// Not implemented
KnWriteLock();
KnWriteLock(const KnWriteLock &);
KnWriteLock &operator=(const KnWriteLock &);
KnRWLoggingLock &m_lock;
};
friend class KnRWLoggingLock::KnReadLock;
friend class KnRWLoggingLock::KnWriteLock;
private:
// Not implemented
KnRWLoggingLock(const KnRWLoggingLock &);
KnRWLoggingLock &operator=(const KnRWLoggingLock &);
bool lock(bool writer=false);
bool unlock(bool writer=false); // Tell us which kind so we log nicely
struct KnLoggingLockImpl;
KnLoggingLockImpl *m_impl;
};
#endif
--- NEW FILE: knset.h ---
#ifndef KNSET_H
#define KNSET_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knstring.h"
#include "knutil/knlog.h"
#include "knutil/knsett.h"
#include "knutil/simplevector.h"
#include "knutil/simplesyncvector.h"
typedef EXPORT_LIBRARY_KNUTIL SimpleVector<KnSetElem *> SimpleVectorSetElem;
typedef EXPORT_LIBRARY_KNUTIL SimpleSyncVector<KnSetElem *> SimpleSyncVectorSetElem;
typedef EXPORT_LIBRARY_KNUTIL KnSetT<SimpleVectorSetElem> KnSet;
typedef EXPORT_LIBRARY_KNUTIL KnSetT<SimpleSyncVectorSetElem> KnSyncSet;
void EXPORT_LIBRARY_KNUTIL KnSetAssign(KnSyncSet& setSync, const KnSet& setNoSync);
void EXPORT_LIBRARY_KNUTIL KnSetAssign(KnSet& setNoSync, const KnSyncSet& setSync);
#endif /* KNSET_H */
--- NEW FILE: knsett.h ---
#ifndef KNSETT_H
#define KNSETT_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knstring.h"
#include "knutil/kntclinterp.h"
#include "ns.h"
#include <string>
// At least on Linux, lengths that exceed 64K definitely cause bad problems
// in vsnprintf (or maybe higher in the stack). Try clamping the length to be
// copied down to a reasonable number (Ns_serverLog [from KnLog] will clamp it further).
#define KNLOG_MAXKNLENGTH(len) ((len < 1024) ? len : 1024)
struct KnSetElem
{
KnString m_key;
KnString m_value;
};
inline bool operator==(const KnSetElem &m, const KnSetElem &n)
{
return m.m_key == n.m_key;
}
// At least on Linux, lengths that exceed 64K definitely cause bad problems
// in vsnprintf (or maybe higher in the stack). Try clamping the length to be
// copied down to a reasonable number (Ns_serverLog [from KnLog] will clamp it further).
#define KNLOG_MAXKNLENGTH(len) ((len < 1024) ? len : 1024)
template <class T>
class KnSetT
{
public:
KnSetT() {}
KnSetT(const KnSetT &kns)
{
copy(kns);
}
KnSetT(const Ns_Set *set)
{
if (set)
{
int i;
char *name;
char *value;
for (i = 0; i < set->size; ++i)
{
name = set->fields[i].name;
value = set->fields[i].value;
if ((name != NULL) && (value != NULL))
put(name, value);
}
}
}
~KnSetT()
{
clear();
}
/*
* Assignment.
*/
KnSetT &operator=(const KnSetT &kns)
{
if (this != &kns)
{
clear();
copy(kns);
}
return *this;
}
KnSetT &operator=(const Ns_Set *set)
{
int i;
char *name;
char *value;
for (i = 0; i < set->size; ++i)
{
name = set->fields[i].name;
value = set->fields[i].value;
if ((name != NULL) && (value != NULL))
put(name, value);
}
return *this;
}
size_t copyToNsSet(Ns_Set* nsSet) const
{
Ns_SetTrunc(nsSet,0);
size_t i = 0;
for (; i < m_set.size(); ++i)
{
Ns_SetPut(nsSet, const_cast<char*>(m_set[i]->m_key.c_str()), const_cast<char*>(m_set[i]->m_value.c_str()));
}
return i;
}
/*
* Iteration.
*/
const KnSetElem &operator[](size_t pos) const
{
return *(m_set[pos]);
}
/*
* Iteration.
*/
KnSetElem &operator[](size_t pos)
{
return *(m_set[pos]);
}
/*
* Remove all entries.
*/
void clear()
{
for (size_t i = m_set.size(); i-- > 0;)
{
remove(i);
}
}
/*
* Whether the set is empty.
*/
bool empty() const
{
return m_set.empty();
}
/*
* Return the first value corresponding to the given key, or 0.
*/
const KnString *get(const KnString &key) const
{
const KnSetElem *elem = getElem(key);
if (elem != 0)
return &elem->m_value;
return 0;
}
const KnString *get(const char *key) const
{
const KnSetElem *elem = getElem(key, strlen(key));
if (elem != 0)
return &elem->m_value;
return 0;
}
/*
* Parse the given query string into name/value pairs.
*/
void parse(const KnString &query)
{
parse(query.c_str());
}
void parse(const char *query)
{
char *eq = NULL;
char *sep = NULL;
char* copy = NULL;
char* query_copy = NULL;
Ns_DString key, value;
query_copy = new char[(strlen(query) + 2)];
memset(query_copy, 0, strlen(query) + 2);
strcpy(query_copy, query);
copy = query_copy;
for (; *copy != '\0'; copy = sep + 1)
{
/*
* Look for the next key/value pair.
*/
KnSetElem *elem = new KnSetElem();
if ((sep = strpbrk(copy, "&;\r\n")) == 0)
sep = copy + strlen(copy);
for (eq = copy; eq < sep && *eq != '='; ++eq)
{
continue;
}
*eq = '\0';
*sep = '\0';
/*
* Take out of x-www-form-urlencoded format.
*/
Ns_DStringInit(&key);
Ns_DStringInit(&value);
Ns_DecodeUrlWithEncoding(&key, copy, NULL);
if (eq++ != sep)
Ns_DecodeUrlWithEncoding(&value, eq, NULL);
elem->m_key = key.string;
elem->m_value = KnString(value.string, value.length);
/*
* Add to the set.
*/
m_set.append(elem);
Ns_DStringFree(&key);
Ns_DStringFree(&value);
if (*sep == '\r' || *sep == '\n')
break;
}
delete[] query_copy;
}
/*
* Append a new element.
*/
bool put(const KnString &key, const KnString &value)
{
KnSetElem *elem = new KnSetElem();
elem->m_key = key;
elem->m_value = value;
if (!m_set.append(elem))
{
delete elem;
elem = 0;
return false;
}
return true;
}
bool put(const KnString &key, const char *value)
{
KnSetElem *elem = new KnSetElem();
elem->m_key += key;
elem->m_value += value;
if (!m_set.append(elem))
{
delete elem;
elem = 0;
return false;
}
return true;
}
bool put(const char *key, const KnString &value)
{
KnSetElem *elem = new KnSetElem();
elem->m_key += key;
elem->m_value += value;
if (!m_set.append(elem))
{
delete elem;
elem = 0;
return false;
}
return true;
}
bool put(const char *key, const char *value)
{
KnSetElem *elem = new KnSetElem();
elem->m_key += key;
elem->m_value += value;
if (!m_set.append(elem))
{
delete elem;
elem = 0;
return false;
}
return true;
}
/*
* Remove the first element with the given key.
*/
void remove(const KnString &key)
{
for (size_t i = 0; i < m_set.size(); ++i)
{
if (m_set[i]->m_key.equals(key))
{
remove(i);
break;
}
}
}
void remove(const char *key)
{
size_t len = strlen(key);
for (size_t i = 0; i < m_set.size(); ++i)
{
if (m_set[i]->m_key.equals(key, len))
{
remove(i);
break;
}
}
}
/*
* Remove the element at position pos.
*/
void remove(size_t pos)
{
KnSetElem *elem = m_set[pos];
m_set.remove(pos);
delete elem;
elem = 0;
}
/*
* The number of entries stored.
*/
size_t size() const
{
return m_set.size();
}
/*
* Determine if the given key occurs multiple times.
*/
bool unique(const KnString &key) const
{
size_t count = 0;
for (size_t i = 0; i < m_set.size(); ++i)
{
if (m_set[i]->m_key.equals(key) && count++ > 0)
return false;
}
return true;
}
bool unique(const char *key) const
{
size_t count = 0;
size_t len = strlen(key);
for (size_t i = 0; i < m_set.size(); ++i)
{
if (m_set[i]->m_key.equals(key, len) && count++ > 0)
return false;
}
return true;
}
/*
* Replace an existing element, or append if not found.
*/
bool update(const KnString &key, const KnString &value)
{
KnSetElem *elem = getElem(key);
if (elem != 0)
{
if(!elem->m_value.equals(value))
elem->m_value = value;
return true;
}
return put(key, value);
}
bool update(const KnString &key, const char *value)
{
KnSetElem *elem = getElem(key);
if (elem != 0)
{
if(!elem->m_value.equals(value))
elem->m_value = value;
return true;
}
return put(key, value);
}
bool update(const char *key, const KnString &value)
{
KnSetElem *elem = getElem(key, strlen(key));
if (elem != 0)
{
if(!elem->m_value.equals(value))
elem->m_value = value;
return true;
}
return put(key, value);
}
bool update(const char *key, const char *value)
{
KnSetElem *elem = getElem(key, strlen(key));
if (elem != 0)
{
if(!elem->m_value.equals(value))
elem->m_value = value;
return true;
}
return put(key, value);
}
/*
* Replace any existing elements in this set with values
* from the other set, or append if not found. If multiple
* values of the same key appear in the lefthand side, only
* the first will get updated.
*/
bool mergeUpdate( const KnSetT& updates )
{
for (size_t i = 0; i < updates.size(); ++i)
{
// Failure means a put has failed. Not a good thing.
if (!update(updates[i].m_key,updates[i].m_value))
return false;
}
return true;
}
/*
* Dump the set to the log (using KnLog)
*/
void dump(
const KnString& prefix = KnStringConstants::whitespace,
const KnLogSeverity severity = KnLogDev
) const
{
for (size_t ix = 0; ix < m_set.size(); ++ix)
{
KnLog(severity,"%.*s%.*s: %.*s",
(int)KNLOG_MAXKNLENGTH(prefix.length()), prefix.c_str(),
(int)KNLOG_MAXKNLENGTH(m_set[ix]->m_key.length()), m_set[ix]->m_key.c_str(),
(int)KNLOG_MAXKNLENGTH(m_set[ix]->m_value.length()), m_set[ix]->m_value.c_str()
);
}
}
private:
/*
* Copy a set.
*/
void copy(const KnSetT &kns)
{
for (size_t i = 0; i < kns.size(); ++i)
{
put(kns[i].m_key, kns[i].m_value);
}
}
/*
* Find the first element with the given key, or 0.
*/
KnSetElem *getElem(const char *key, size_t len) const
{
for (size_t i = 0; i < m_set.size(); ++i)
{
if (m_set[i]->m_key.equals(key, len))
return m_set[i];
}
return 0;
}
/*
* Find the first element with the given key, or 0.
*/
KnSetElem *getElem(const KnString &key) const
{
for (size_t i = 0; i < m_set.size(); ++i)
{
if (m_set[i]->m_key.equals(key))
return m_set[i];
}
return 0;
}
T m_set;
};
#endif /* KNSETT_H */
--- NEW FILE: knsleep.h ---
#ifndef KNSLEEP_H
#define KNSLEEP_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
/**
* @file knsleep.h
*
* Implements a portable millisecond sleep wrapper.
*/
#include "knutil/knexportlibraryknutil.h"
extern EXPORT_LIBRARY_KNUTIL void KnSleep(long milliseconds) ;
#endif /* KNSLEEP_H */
--- NEW FILE: knsmartref.h ---
#ifndef KNSMARTREF_H
#define KNSMARTREF_H
/**
* Copyright (c) 2001-2005 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/counter.h"
#include "knutil/simplenull.h"
#include "knutil/simpletraits.h"
// We should add a policy here for whether to support null or not
template <class Body>
class KnSmartRef
{
public:
explicit KnSmartRef(Body* b = 0, Counter* counter = 0) : m_counter(0), ptr(0) {
if(b) {
if (counter)
{
counter->count.increment();
m_counter = counter;
} else
{
m_counter = new Counter();
}
ptr = b;
}
}
~KnSmartRef()
{
release();
}
KnSmartRef(const KnSmartRef& r)
{
acquire(r.m_counter);
ptr = r.ptr;
}
KnSmartRef& operator=(const KnSmartRef& r)
{
if (this != &r)
{
release();
acquire(r.m_counter);
ptr = r.ptr;
}
return *this;
}
const Body& getConstRef() const
{
return *ptr;
}
// Known to only be called from KnTopic::setProperties in order
// to avoid writing that method twice, since KnEvent::updateInternals
// *must* call with a bare reference or pointer (at least until we
// replace this with shared_ptr, which supports shared_ptr_to_this).
Body& getRef() const
{
return *ptr;
}
Body* get() const
{
return ptr;
}
Body* operator->() const
{
return ptr;
}
bool isNull() const
{
return (0 == m_counter || 0 == ptr);
}
void set(Body *b)
{
release();
ptr = NULL;
if(b)
{
m_counter = new Counter();
ptr = b;
}
}
template<class newType> // template function for
operator KnSmartRef<newType>() // implicit conversion ops.
{
return KnSmartRef<newType>(ptr, m_counter);
}
/*
template<class newType>
KnSmartRef<newType> dynamic_pointer_cast()
{
//We should use dynamic_cast instead of static_cast, but we are compiling without RTTI...
return KnSmartRef<newType>(static_cast<newType*>(ptr), m_counter);
}
*/
bool operator==(const KnSmartRef& r) const
{
return ptr == r.ptr;
}
bool operator!=(const KnSmartRef& r) const
{
return !(*this == r);
}
private:
Counter* m_counter;
Body* ptr;
void acquire(Counter *c)
{
if (NULL != c)
{
c->count.increment();
m_counter = c;
}
else
m_counter = NULL;
}
void release()
{
if (NULL == m_counter)
return;
Counter* l_counter;
Body* l_ptr;
l_counter = m_counter;
l_ptr = ptr;
m_counter = NULL;
ptr = NULL;
if(l_counter->count.decrementAndTest())
{
SAFE_DELETE(l_ptr);
SAFE_DELETE(l_counter);
}
}
};
template<class Body>
struct SimpleZeroTraits< KnSmartRef<Body> >
{
static inline KnSmartRef<Body> null()
{
return KnSmartRef<Body>(static_cast<Body *>(0));
}
};
template<class Body>
struct SimpleHashTraits< KnSmartRef<Body> >
{
static inline size_t get(const KnSmartRef<Body> &t)
{
return t->hashCode();
}
};
template<class Body>
struct SimpleCompareTraits< KnSmartRef<Body>, KnSmartRef<Body> >
{
static inline bool equals(const KnSmartRef<Body> &t, const KnSmartRef<Body> &u)
{
return t->operator==(u);
}
};
#endif /* KNSMARTREF_H */
--- NEW FILE: knstring.h ---
#ifndef KNSTRING_H
#define KNSTRING_H
/**
* Copyright (c) 2006 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
#include "knutil/atomicint.h"
#include "knutil/knerror.h"
#include "knutil/simpleset.h"
#include "knutil/simplenull.h"
// Use this and %lu. It'd be nice if we could string token paste
// a macro in for the format part, but that doesn't work because
// a macroname is an identifier to C
#define KNPF_SZCAST(a) static_cast<unsigned long>(a)
// Similar for time
#define KNPF_TMCAST(a) static_cast<unsigned long>(a)
#include <string>
extern EXPORT_LIBRARY_KNUTIL void toLowerCase( std::string& str );
extern EXPORT_LIBRARY_KNUTIL void toUpperCase( std::string& str );
extern EXPORT_LIBRARY_KNUTIL void truncateFromRight( std::string& str, int len );
extern EXPORT_LIBRARY_KNUTIL void std_printf( std::string& str, const char *fmt, ...);
class InternalString
{
public:
InternalString(const char *s = "", int len = 0);
~InternalString();
//Methods needed for simple set
size_t hashCode() const;
bool operator==(const InternalString &is) const;
char* m_string;
int m_stringLength;
AtomicInt m_count;
// set temporary unowned string
void setString(const char *s, int len);
private:
//prevent copying
InternalString(const InternalString &is);
InternalString &operator=(const InternalString &is);
};
/*
* Counted string, similar to std::string.
*/
class EXPORT_LIBRARY_KNUTIL KnString
{
public:
KnString();
KnString(const KnString &kns);
explicit KnString(const char *s, int len=-1);
~KnString();
KnString &operator=(const KnString &kns);
KnString &operator=(const char *s);
KnString &operator+=(const KnString &kns);
KnString &operator+=(const char *s);
KnString &printf(const char *fmt, ...)
__attribute__ ((format (printf,2,3)));
KnString ©(const char *s, int len);
KnString &reset();
KnString &trim();
/*
* Truncate len characters from the end of the string.
*/
KnString &truncateFromRight(int len=1);
/*
* Truncate len characters from the front of the string.
*/
KnString &truncateFromLeft(int len=1);
KnString &toLowerCase();
KnString &toUpperCase();
/*
* Variable length concatenation.
*/
KnString &append(const char *s, int len);
/*
* Variable length prepending.
*/
KnString &prepend(const char *s, int len);
/*
* Replace all occurrences of char s1 with char s2.
*/
void replace(const char s1, const char s2);
/*
* Replace the first occurrence of string s1 in this string with s2
* as long as s1 and s2 are the same length.
*/
void replace(const char *s1, const char *s2);
/*
* Replace all occurrences of string s1 in this string with s2
* No restrictions on lengths.
*/
unsigned int replaceAll(const char *s1, const char *s2);
/*
* Truncate the string to the length indicated. Also
* can be used to expand the storage available for the
* string (ala Java StringBuffer::setLength())
*/
KnString &setLength(size_t len);
inline char operator[](int pos) const
{
return c_str()[pos];
}
const char *c_str() const;
size_t length() const;
int indexOf(char ch) const;
int indexOf(char ch, size_t pos) const;
bool startsWith(const KnString &kns) const;
bool startsWith(const char *s) const;
bool startsWith(const char *s, size_t len) const;
bool startsWithIgnoreCase(const KnString &kns) const;
bool startsWithIgnoreCase(const char *s) const;
bool startsWithIgnoreCase(const char *s, size_t len) const;
bool equals(const KnString &kns) const;
bool equals(const char *s) const;
bool equals(const char *s, size_t len) const;
bool equalsIgnoreCase(const KnString &kns) const;
bool equalsIgnoreCase(const char *s) const;
bool equalsIgnoreCase(const char *s, size_t len) const;
bool endsWith(const KnString &kns) const;
bool endsWith(const char *s) const;
bool endsWith(const char *s, size_t len) const;
bool endsWithIgnoreCase(const KnString &kns) const;
bool endsWithIgnoreCase(const char *s) const;
bool endsWithIgnoreCase(const char *s, size_t len) const;
bool operator==(const KnString &kns) const;
bool operator==(const char *s) const;
bool operator!=(const KnString &kns) const;
bool operator!=(const char *s) const;
bool operator<=(const KnString &kns) const;
bool operator<(const KnString &kns) const;
bool operator>(const KnString &kns) const;
int compare(const KnString &kns) const;
bool has(const char *s) const;
bool has(const KnString &kns) const;
int lastIndexOf(char ch) const;
int lastIndexOf(char ch, size_t pos) const;
size_t hashCode() const;
long toLong() const;
int toInteger() const;
unsigned int toUnsignedInteger() const;
unsigned long toUnsignedLong() const;
double KnString::toDouble() const;
KnTime_t toKnTimeT() const;
/// Return boolean conversion
/// Returns bDefault if can't successfully parse.
bool toBool(KnError* pSuccess = 0, bool bDefault = true) const;
/// Put boolean conversion in bValue
/// Changes bValue only if successfully parsed
KnError toBool(bool& bValue) const;
/*
* Make relative url start with given url root
*/
void ensureLocationStartsWithUrlRoot(const KnString& urlRoot);
private:
/*
* Compare buffers, returning a value similar to memcmp().
*/
int compareFirstLenBytes(const char *s, size_t len, size_t pos=0) const;
/*
* Compare case-insensitive buffers, returning a value similar to memcmp().
*/
int compareIgnoreCase(const char *s, size_t len, size_t pos=0) const;
/*
* Compare buffers, returning value like memcmp(); take length
* into account if the buffers are equal for the length of one of them.
*/
int compareWithLength(const char *s, int len, int pos=0) const ;
char* dupInternal(int &len);
public:
InternalString* m_data;
inline bool sameInternal(InternalString* is) const
{
return m_data == is;
}
};
template <>
struct SimpleZeroTraits< KnString >
{
static inline KnString null()
{
KnString empty("");
return empty;
}
};
EXPORT_LIBRARY_KNUTIL const KnString& KnError_AsString( const KnError code );
// common strings that we can use to take advantage of reference counting
class EXPORT_LIBRARY_KNUTIL KnStringConstants {
public:
static const KnString add;
static const KnString addset;
static const KnString blank;
static const KnString colon;
static const KnString comma;
static const KnString create;
static const KnString empty;
static const KnString failed;
static const KnString forbidden;
static const KnString free;
static const KnString get;
static const KnString infinity;
static const KnString n_ew;
static const KnString notspacefound;
static const KnString now;
static const KnString remove;
static const KnString set;
static const KnString size;
static const KnString slot;
static const KnString success;
static const KnString unauthorized;
static const KnString slash;
static const KnString slash_kn;
static const KnString slash_kn_system_slash_kn_filters_slash_tcl;
static const KnString plus10dot0;
static const KnString plus5dot0;
static const KnString num0;
static const KnString num127dot0dot0dot1;
static const KnString ActivespaceConnections;
static const KnString add_journal;
static const KnString add_notify;
static const KnString add_route;
static const KnString add_topic;
static const KnString atomic_topic;
static const KnString batch;
static const KnString clear_topic;
static const KnString cluster_interface;
static const KnString cnode;
static const KnString container;
static const KnString dashmaindash;
static const KnString delete_route;
static const KnString delete_notify;
static const KnString delete_topic;
static const KnString do_max_age;
static const KnString do_max_n;
static const KnString do_method;
static const KnString done;
static const KnString dynamicGroup;
static const KnString dynamicGroupAux;
static const KnString EventsspaceDelivered;
static const KnString EventsspacePublished;
static const KnString EventsspaceRouted;
static const KnString group;
static const KnString groupOfNames;
static const KnString groupOfUniqueNames;
static const KnString groupOfUrls;
static const KnString HA_Debug;
static const KnString header1;
static const KnString header2;
static const KnString header3;
static const KnString Heartbeats;
static const KnString help;
static const KnString http;
static const KnString https;
static const KnString initial_value;
static const KnString JournalspaceTopics;
static const KnString js;
static const KnString jsobj;
static const KnString json;
static const KnString _kn_current_event;
static const KnString kn_action;
static const KnString kn_atomic;
static const KnString kn_batch;
static const KnString kn_block;
static const KnString kn_cluster_passwd;
static const KnString kn_cluster_spread_restart;
static const KnString kn_cluster_url;
static const KnString kn_cluster_user;
static const KnString kn_connection;
static const KnString kn_debug;
static const KnString kn_default_kn_expires;
static const KnString kn_default_provider;
static const KnString kn_delegate_user;
static const KnString kn_deleted;
static const KnString kn_deletions;
static const KnString kn_display_name;
static const KnString kn_displayname;
static const KnString kn_event_cluster;
static const KnString kn_event_cluster_state;
static const KnString kn_event_cluster_state_req;
static const KnString kn_event_delivered_total;
static const KnString kn_event_hash;
static const KnString kn_event_id;
static const KnString kn_event_norestorelocal;
static const KnString kn_event_procmgr_kludge;
static const KnString kn_event_published_total;
static const KnString kn_event_routed_total;
static const KnString kn_exitcode;
static const KnString kn_expires;
static const KnString kn_filtername;
static const KnString kn_filteroptions;
static const KnString kn_filterparams;
static const KnString kn_from;
static const KnString kn_heartbeat;
static const KnString kn_history_since_age;
static const KnString kn_history_since_event_id;
static const KnString kn_history_since_n;
static const KnString kn_history_since_time;
static const KnString kn_hold_new_events;
static const KnString kn_http_connections;
static const KnString kn_id;
static const KnString kn_id_is_generated;
static const KnString kn_journal_topic_count;
static const KnString kn_max;
static const KnString kn_max_queue_size;
static const KnString kn_module;
static const KnString kn_node;
static const KnString kn_notify_topic_count;
static const KnString kn_offhost_retries;
static const KnString kn_offhost_eventid_sent;
static const KnString kn_offhost_event_timestamp_retry;
static const KnString kn_offhost_pending_deletions;
static const KnString kn_owner;
static const KnString kn_password;
static const KnString kn_patternroute_id;
static const KnString kn_patternroute_destination;
static const KnString kn_patternroute_pattern;
static const KnString kn_payload;
static const KnString kn_pid;
static const KnString kn_provider_id;
static const KnString kn_purpose;
static const KnString kn_queue;
static const KnString kn_request_format;
static const KnString kn_request_manager;
static const KnString kn_response;
static const KnString kn_response_flush;
static const KnString kn_response_flush_interval;
static const KnString kn_response_format;
static const KnString kn_response_id;
static const KnString kn_response_payload;
static const KnString kn_response_uri;
static const KnString kn_response_xml;
static const KnString kn_retry;
static const KnString kn_retry_queue;
static const KnString kn_retry_queue_size;
static const KnString kn_route_;
static const KnString kn_route_id;
static const KnString kn_route_location;
static const KnString kn_route_cluster;
static const KnString kn_route_cluster_origin;
static const KnString kn_route_cluster_timestamp;
static const KnString kn_route_to;
static const KnString kn_route_topic_count;
static const KnString kn_routed_from;
static const KnString kn_server;
static const KnString kn_server_domain;
static const KnString kn_server_url;
static const KnString kn_session;
static const KnString kn_spuser;
static const KnString kn_status;
static const KnString kn_status_from;
static const KnString kn_status_to;
static const KnString kn_subtopic_topic_count;
static const KnString kn_subtopics;
static const KnString kn_system;
static const KnString kn_temporary;
static const KnString kn_temporary_expires;
static const KnString kn_time_t;
static const KnString kn_timer_heartbeat;
static const KnString kn_timer_interval;
static const KnString kn_timer_keepalive;
static const KnString kn_timer_next_update;
static const KnString kn_timer_updated;
static const KnString kn_to;
static const KnString kn_topic_event_count;
static const KnString kn_topic_etag;
static const KnString kn_topic_last_modified;
static const KnString kn_topic_name;
static const KnString kn_topic_nodelete;
static const KnString kn_topic_nopersist;
static const KnString kn_topic_nopost;
static const KnString kn_topic_rr;
static const KnString kn_topic_rr_has_blocking;
static const KnString kn_topic_rr_has_manager;
static const KnString kn_topic_status;
static const KnString kn_total_topic_count;
static const KnString kn_total_tunnel_count;
static const KnString kn_uj;
static const KnString kn_uri;
static const KnString kn_user;
static const KnString kn_userid;
static const KnString kn_valid_user;
static const KnString lib;
static const KnString list;
static const KnString list_topic;
static const KnString list_topic_metadata;
static const KnString list_event;
static const KnString list_event_metadata;
static const KnString local;
static const KnString Log_Debug;
static const KnString Log_DebugTCL;
static const KnString noop;
static const KnString notify;
static const KnString nslasha;
static const KnString NamespaceTopics;
static const KnString nsknc;
static const KnString other;
static const KnString password;
static const KnString Permissions_Audit;
static const KnString Permissions_Audit_Forbidden;
static const KnString Permissions_Debug;
static const KnString reaper;
static const KnString Recovery_Debug;
static const KnString recovery_snapshot_dir;
static const KnString replydashto;
static const KnString replydashuri;
static const KnString restart;
static const KnString root;
static const KnString route;
static const KnString RoutespaceTopics;
static const KnString scalar;
static const KnString set_topic_property;
static const KnString simple;
static const KnString SOAP;
static const KnString spaceForbiddencolonspace;
static const KnString spaceUnauthorizedcolonspace;
static const KnString start;
static const KnString started;
static const KnString station;
static const KnString status;
static const KnString Status200OK;
static const KnString Status200WT;
static const KnString stop;
static const KnString stringfalse;
static const KnString stringtrue;
static const KnString StatisticsOp_Header;
static const KnString StatisticsCat_Header;
static const KnString SubtopicspaceTopics;
static const KnString test;
static const KnString TotalspaceSubscribers;
static const KnString TotalspaceTopics;
static const KnString transform;
static const KnString unrecognizedspaceoperation;
static const KnString update_notify;
static const KnString update_route;
static const KnString user;
static const KnString waiting_on_process_to_exit;
static const KnString whitespace;
static const KnString whoami;
static const KnString wsdl;
static const KnString xdashtnscolon;
static const KnString xdashkntunnelcolon;
};
#endif /* KNSTRING_H */
--- NEW FILE: knstringtokenizer.h ---
#ifndef KNSTRINGTOKENIZER_H
#define KNSTRINGTOKENIZER_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knstring.h"
/*
* Simple string tokenizer. The string to be parsed is stored internally,
* and should not be deleted while the tokenizer is in use. If a delimiter
* is not specified, whitespace is assumed.
*/
class EXPORT_LIBRARY_KNUTIL KnStringTokenizer
{
public:
/*
* If skip is false, delimiter characters are returned as tokens.
*/
KnStringTokenizer(const KnString &str, bool skip=true);
/*
* If skip is false, delimiter characters are returned as tokens.
*/
KnStringTokenizer(const KnString &str,
const KnString &delim,
bool skip=true);
/*
* If skip is false, delimiter characters are returned as tokens.
*/
KnStringTokenizer(const KnString &str,
const char *delim,
bool skip=true);
/*
* Copy an existing tokenizer.
*/
KnStringTokenizer(const KnStringTokenizer &tk);
/*
* Destroy the tokenizer.
*/
~KnStringTokenizer();
/*
* Retrieve the next token.
*/
bool next(KnString &token);
/*
* Retrieve the next token, using the supplied delimiter, which becomes
* the default delimiter for all subsequent requests.
*/
bool next(KnString &token, const KnString &delim);
/*
* Retrieve the next token, using the supplied delimiter, which becomes
* the default delimiter for all subsequent requests.
*/
bool next(KnString &token, const char *delim);
private:
// Not implemented
KnStringTokenizer();
KnStringTokenizer &operator=(const KnStringTokenizer &);
const KnString &m_str;
KnString m_delim;
size_t m_pos;
bool m_skip;
};
#endif /* KNSTRINGTOKENIZER_H */
--- NEW FILE: knstrops.h ---
#ifndef KNSTROPS_H
#define KNSTROPS_H
/**
* Copyright (c) 2006 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
// Getting annoying writing these cliches all the time, so I'm
// experimenting with a template package. That way we can use
// same functions for both KnString & std::string as we add
// new ones in (e.g., StartsWith, etc). Not necessarily
// happy that they're function syntax rather than method
// syntax; just what I could remember how to do today ;-).
template<typename S, typename T>
static inline void TrimFromRight(S& str, const T& any)
{
size_t pos = str.find_last_not_of(any);
if (pos != S::npos)
{
str.resize(pos+1);
}
};
template<typename S, typename T>
static inline void TrimFromLeft(S& str, const T& any)
{
size_t pos = str.find_first_not_of(any);
if (pos != S::npos)
{
str = str.substr(pos);
}
};
template<typename S, typename T>
static inline bool StartsWith(const S& str, const T& any)
{
return 0 == str.compare(0,any.length(),any.c_str());
};
template<typename S>
static inline bool StartsWith(const S& str, const char *any)
{
S safe(any);
return StartsWith(str,safe);
};
#endif
--- NEW FILE: knsysutility.h ---
/**
/**
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
* Copyright 2000 - 2004 KnowNow, Inc., Sunnyvale, CA. All rights reserved.
*/
#ifndef KNSYSUTILITY_H
#define KNSYSUTILITY_H
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knstring.h"
#include "ns.h"
EXPORT_LIBRARY_KNUTIL int KnProcessStart( const KnString &exec, KnString *args,
Ns_Set *envblock,
int *pid = NULL,
bool restart = false,
bool nullio = false );
EXPORT_LIBRARY_KNUTIL bool KnProcessStop( const int pid, int *exit = NULL );
EXPORT_LIBRARY_KNUTIL bool KnProcessStop( const KnString &exec, int *exit = NULL );
EXPORT_LIBRARY_KNUTIL void* KnProcessFind( const KnString &procname );
EXPORT_LIBRARY_KNUTIL bool KnSetEnvVar( const char *envvar, const char *value);
#endif // KNSYSUTILITY_H
--- NEW FILE: kntclargs.h ---
#ifndef KNTCLARGS_H
#define KNTCLARGS_H
/**
* Copyright (c) 2008 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knerror.h"
#include "knutil/knlog.h"
#include "knutil/knstring.h"
#include "knutil/kntclerrors.h"
#include "ns.h"
# if 0
/* Started factoring out the various routines into a template
* Should be conditional on IS_PTR, probably needs to reference
* NullTraits.
*
* Currently written as if the T is always a pointer
*
* Clearly the wrong packaging for this sort of thing. Should just hand
* the array to a class and then pull args from it.
*/
template<typename T>
struct KnTclTraits {
bool exists(T& var) {
return var != 0;
}
void assign(Tcl_Interp* /* interp */, T& var,Tcl_Obj * /*const */ value) {
var = Tcl_GetString(value);
}
bool verify(const T& var,bool& setsErr) {
setsErr = false;
return true;
}
/* returns TCL_OK or TCL_ERROR */
int parseArg(
Tcl_Interp* interp, const std::string& argName, T pValue,
const int ixArg, const int objc, Tcl_Obj* /* const */ objv[],
int errc = 1)
{
std::string err = argName + " ";
if (exists(pValue)) {
err += "already present";
return KnTcl_BadArg(interp,errc,objv,err.c_str());
}
if (ixArg > objc) {
err += "requires a parameter";
return KnTcl_BadArg(interp,errc,objv,err.c_str());
}
assign(interp,pValue,objv[ixArg]);
bool bNoWrite = false;
if (!verify(pValue,bNoWrite)) {
err += "requires a valid parameter value";
return bNoWrite ? TCL_ERROR
: KnTcl_BadArg(interp,errc,objv,err.c_str());
}
return TCL_OK;
}
};
template<>
struct KnTclTraits<Ns_Set*> {
void assign(Tcl_Interp* interp, Ns_Set*& pSet, Tcl_Obj * /*const */ value) {
pSet = Ns_TclGetSet(interp, Tcl_GetString(value));
}
bool verify(const Ns_Set*& pSet,bool& setsErr) {
setsErr = true;
return 0 != pSet;
}
};
#endif
/* Trying to avoid redundancy; can certainly template to remove more*/
inline int
kntcl_parse_set_arg(
Tcl_Interp* interp, const std::string& argName, Ns_Set *& pSet,
const int ixArg, const int objc, Tcl_Obj* /* const */ objv[], int errc = 1)
{
//std::string err = argName + " ";
std::string err = argName + " ";
if (pSet) {
err += "already present";
return KnTcl_BadArg(interp,errc,objv,err.c_str());
}
if (ixArg > objc) {
err += "requires a set id as parameter";
return KnTcl_BadArg(interp,errc,objv,err.c_str());
}
pSet = Ns_TclGetSet(interp, Tcl_GetString(objv[ixArg]));
if (pSet == NULL) {
// Don't call BadArg, since Ns_TclGetSet already
// put an error into the interp
err += "requires a valid set id as parameter";
return KnTcl_BadArg(interp,errc,objv,err.c_str());
}
return TCL_OK;
}
inline int
kntcl_parse_knstring_arg(
Tcl_Interp* interp, const std::string& argName, KnString*& pString,
const int ixArg, const int objc, Tcl_Obj* /* const */ objv[], int errc = 1)
{
std::string err = argName + " ";
if (pString) {
err += "already present";
return KnTcl_BadArg(interp,1,objv,err.c_str());
}
if (ixArg > objc) {
err += "requires a string parameter";
return KnTcl_BadArg(interp,1,objv,err.c_str());
}
pString = new KnString(Tcl_GetString(objv[ixArg]));
return TCL_OK;
}
inline int
kntcl_parse_string_arg(
Tcl_Interp* interp, const std::string& argName, std::string*& pString,
const int ixArg, const int objc, Tcl_Obj* /* const */ objv[], int errc = 1)
{
std::string err = argName + " ";
if (pString) {
err += "already present";
return KnTcl_BadArg(interp,1,objv,err.c_str());
}
if (ixArg > objc) {
err += "requires a string parameter";
return KnTcl_BadArg(interp,1,objv,err.c_str());
}
pString = new std::string(Tcl_GetString(objv[ixArg]));
return TCL_OK;
}
inline int
kntcl_parse_tclobj_arg(
Tcl_Interp* interp, const std::string& argName,
Tcl_Obj *& objPtr,
const int ixArg, const int objc, Tcl_Obj* /* const */ objv[], int errc = 1)
{
std::string err = argName + " ";
if (objPtr) {
err += "already present";
return KnTcl_BadArg(interp,1,objv,err.c_str());
}
if (ixArg > objc) {
err += "requires a varname parameter";
return KnTcl_BadArg(interp,1,objv,err.c_str());
}
objPtr = objv[ixArg];
return TCL_OK;
}
inline int
kntcl_parse_nonneg_int_arg(
Tcl_Interp* interp, const std::string& argName, int& intRef,
const int ixArg, const int objc, Tcl_Obj* /* const */ objv[], int errc = 1)
{
std::string err = argName + " ";
if (intRef >= 0) {
err += "already present";
return KnTcl_BadArg(interp,1,objv,err.c_str());
}
if (ixArg > objc) {
err += "requires an integer parameter";
return KnTcl_BadArg(interp,1,objv,err.c_str());
}
int tclerr = Tcl_GetIntFromObj(interp, objv[ixArg], &intRef);
if (TCL_OK == tclerr && intRef < 0) {
err += "requires an non-negative value";
return KnTcl_BadArg(interp,1,objv,err.c_str());
}
return tclerr;
}
#endif
--- NEW FILE: kntclerrors.h ---
#ifndef KNTCL_ERRORS_H
#define KNTCL_ERRORS_H
/**
* Copyright (c) 2008 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
#include "knutil/knerror.h"
/*
* A place for wrapping Tcl_* functions to make LiveServer error handling
* code more consistent
*/
/*
* Always returns TCL_ERROR so you can just do
* return KnTcl_WrongNumArgs(interp,1,objv,"Here's my message");
* Message always includes the first objc elements of the command.
*/
EXPORT_LIBRARY_KNUTIL int KnTcl_WrongNumArgs(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], const char *message);
/* A different error message (not wrong number of arguments, but invalid.
* Same sort of message handling & error return as WrongNumArgs.
*/
EXPORT_LIBRARY_KNUTIL int KnTcl_BadArg(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], const char *message);
/*
* Use this to convert a status into a TCL error and throw it back into
* the TCL interp, ala
* return KnTcl_Error(SomethingThatReturnsKnError());
*/
EXPORT_LIBRARY_KNUTIL int KnTcl_Error(Tcl_Interp *interp, KnError status);
/*
* The following codes should be applied via string pasting or %s, not %d or %f
* They exist because it's not exactly clear wehhter tcl errors should
* be "client" or "server" side, and we want some flexibility in how to
* deliver them.
*/
#define KNTCL_ERROR_WRONG_NUM_ARGS "500"
#define KNTCL_ERROR_BAD_ARG "500"
#endif
--- NEW FILE: kntclfile.h ---
#ifndef KNTCLFILE_H
#define KNTCLFILE_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
#include "knutil/knstring.h"
#include "knutil/kntclinterp.h"
/**
* Class for instantiating and running a file as a Tcl program
* within LiveServer.
*/
// TODO:
// Add argument processing, so the argv list is populated; would
// make it easier to move scripts from tclsh into operation (and
// to parameterize scripts in the first place).
//
// Consider adding a pointer conversion operator so you can
// just use your KnTclFile pointer (object?) wherever an
// interp is required
class EXPORT_LIBRARY_KNUTIL KnTclFile {
public:
/**
* Arrange to run the file in the interpreter; allocate interpreter
* if not provided.
*/
KnTclFile( KnString& filename, KnTclInterp* interp );
~KnTclFile();
/**
* Run the file; KnErrorSuccess implies good operation; Failure
* means problems were logged.
*/
KnError run(KnString& file);
/**
* The object will be valid only if the file exists and is readable,
* and an interpreter is available to run it in.
*/
bool isValid();
private:
KnTclInterp* interp_;
KnString filename_;
bool valid_;
bool destroy;
};
#endif
--- NEW FILE: kntclinterp.h ---
#ifndef KN_TCLINTERP_H
/**
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define KN_TCLINTERP_H
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knerror.h"
#include "knutil/knlog.h"
#include "knutil/knstring.h"
#include "ns.h"
// (c) Copyright 2005 KnowNow, Inc
//
// Implements reference counting in TCL variables in order to
// make sure we don't de-allocate a TclInterp that's still in use.
// Can't use C++ variables easily, since we're passed the
// Tcl_Interp* as an input parameter in some cases.
//
// We could potentially use a dictionary in C++ for that, but
// TCL is perfectly capable of storing our information for us.
//
// Since AOLServer assures us that each Tcl_Interp is only used by one
// thread, we don't have to do any locking here.
//
// We also use this .h to provide safety-wrappers for bugs we often
// write in TCL C procs. In particular, the lexical similarity
// (and very different memory management behavior) between
// Tcl_SetResult(interp,str,0) and Tcl_AppendResult(interp,str,0)
// often causes us to create very nasty bugs or memory leaks.
class EXPORT_LIBRARY_KNUTIL KnTclInterp
{
//
// Construction and destruction
//
public:
explicit KnTclInterp(Tcl_Interp* pointer);
explicit KnTclInterp(const char* server);
~KnTclInterp();
KnError createObjCommand(CONST char* name, Tcl_ObjCmdProc* proc, void* data, Tcl_CmdDeleteProc* delProc);
KnError evalFile(KnString& filename, KnString& file);
KnError setGlobalVariable(const KnString varName, const KnString value) const;
KnError getGlobalVariable(const KnString varName, KnString& value) const;
KnError executeBooleanCommand(KnString& tclCommand, bool& value);
// Access to members
bool isValid() const;
Tcl_Interp* operator->();
const Tcl_Interp* operator->() const;
Tcl_Interp& operator*();
const Tcl_Interp& operator*() const;
protected:
// Value is current reference count. REFACTOR: change name accordingly.
int increment(int count=1);
int decrement(int count=1);
private:
static char * REFCOUNT_TCLVAR; // Can't be const 'cause TCL takes nonconst char*
static int REFCOUNT_VARFLAGS ;
bool getValue(Tcl_Obj*& valueObj, int& value) ;
bool setValue(Tcl_Obj*& valueObj, int value) ;
//
// Copy & assignment constructors. Potentially could be implemented
// if I had appropriate references handy, but I don't, so I'm keeping
// myself from writing mistakes.
//
KnTclInterp& operator=(const KnTclInterp& ref);
KnTclInterp(const KnTclInterp& ref);
bool m_amOwner;
Tcl_Interp* m_pointer;
};
inline Tcl_Obj *
KnTcl_NewStringObj(const std::string& string) {
return Tcl_NewStringObj(const_cast<CONST char*>(string.c_str()), string.length());
}
inline Tcl_Obj *
KnTcl_NewStringObj(const KnString& string) {
return Tcl_NewStringObj(const_cast<CONST char*>(string.c_str()), string.length());
}
#endif
--- NEW FILE: kntemplateuri.h ---
#ifndef KNTEMPLATEURI_H
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define KNTEMPLATEURI_H
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knpattern.h"
#include "knutil/knregex.h"
#include "knutil/knset.h"
#include <string>
#include <vector>
#include <map>
class KnTempItemDesc;
class EXPORT_LIBRARY_KNUTIL KnTemplateURI : public KnUrlPattern
{
public:
KnTemplateURI( const KnString& name, const KnString& expr);
virtual ~KnTemplateURI();
/*
* Determine whether the template uri matches the string.
*/
int getSubCount() const;
bool matchSubs(const char *str, KnSet& result);
bool isValidTemplate() const;
static bool replaceInto(KnSet& set, const char* expr, std::string& result, bool removeMatched = false);
protected:
// overload makepathregex
bool makePathRegex(KnString& putItHere, const KnString& part);
bool escape( std::string& putItHere, char aChar);
private:
KnTemplateURI();
KnTemplateURI(const KnTemplateURI& rhs);
KnTemplateURI& operator=(const KnTemplateURI& rhs);
bool m_validTemplate;
KnString m_template;
std::vector<KnTempItemDesc*> m_items;
KnMutex m_regexSubsMutex;
};
#endif /* KNTEMPLATEURI_H */
--- NEW FILE: kntime.h ---
#ifndef KNTIME_H
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define KNTIME_H
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
#include "knutil/knstring.h"
typedef enum {
KNTIME_ABSOLUTE, // + is future, - is past, @ or nothing is absolute
KNTIME_FUTURE, // + or nothing is future, - is past, @ is absolute
KNTIME_PAST // + is future, - or nothing is past, @ is absolute
} KnTimeDefault ;
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* The KnTime class handles all the time manipulation for events
* in the LiveServer system.
*
* Key parts of the contract:
* In events, time is always represented as a string.
* In internal data structures, time allows for additive arithmetic,
* especially with regard to two "relative" times:
* do_max_age with a default of negative time
* (that is, do_max_age=300 is 5 minutes ago).
* journal_reconnect_time
* with a default of positive time.
* (that is, journal_reconnect_time = 300 implies
* 5 minutes after arrival time).
*
* We encapsulate this class in order to allow for expansions in our
* time repertoire to better handle loosely synchronized systems.
*
* Syntax for time strings:
* [<sign>]<number>[.<number>]
*
* <sign> ::= "@" | "+" | "-"
* where @ is absolute, + is after a reference time,
* and - is before a reference time
*
* By my reading of this class (and while I wrote it it was a while ago),
* a time represented with this class is always absolute after
* instantiation. That is, you can't use this to parse the string
* "+infinity" or "+300" and expect to then add the returned KnTime
* to another KnTime.
* So the "operator+" should take an integer, a KnString,
* or a timeval, but not another KnTime.
*/
class EXPORT_LIBRARY_KNUTIL KnTime {
public:
explicit KnTime(); // Right now
explicit KnTime( const KnString ×tring,
KnTimeDefault bDflt = KNTIME_ABSOLUTE,
bool isDelta = false) ;
~KnTime() ;
KnTime(const KnTime& other);
KnTime& operator=( const KnTime& other ) ;
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* Get absolute time expressed as a KnString.
*
* Returns string representing absolute time
*/
const KnString& asString() const ;
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* Get absolute time expressed as a C string.
*
* String will have no modifiers and will represent time since the
* epoch (1/1/1970)
*/
const char * c_str() const ;
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* Get absolute time expressed in seconds.
*
* String will have no modifiers and will represent time since the
* epoch (1/1/1970)
*/
KnTime_t asTime_T() const ;
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* Get absolute time expressed as a floating point number.
*
* Returns seconds and milliseconds since the epoch.
*/
double asFloat() const ;
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* Get absolute time as a struct tm
*/
struct timeval asTimeVal() const ;
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* Adjust time to the present
*/
void setToNow() ;
KnTime& operator+=( const KnTime& other ) ;
bool operator<( const KnTime& other) const ;
bool operator<=( const KnTime& other) const ;
bool operator>( const KnTime& other) const ;
bool operator>=( const KnTime& other) const ;
bool operator==( const KnTime& other ) const ;
bool operator==( const KnTime_t t ) const ; // In that second: interval [t,t+1)
bool operator!=( const KnTime& other ) const ;
bool operator!=( const KnTime_t t ) const ; // In that second: interval [t,t+1)
private:
struct KnTimeImpl; // Forward declaration
KnTimeImpl *pImpl;
};
extern EXPORT_LIBRARY_KNUTIL KnTime operator+( const KnTime& lhs, const KnTime& rhs ) ;
#endif
--- NEW FILE: kntypes.h ---
#ifndef KNTYPES_H
#define KNTYPES_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#ifndef __GNUC__
#define __attribute__(x)
#endif
#ifdef KN_PRIVATE
/*
* Private types and structures.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
/* You must set the above macro in order to get the SIZE_MAX defined.
You have to set it before including stdint. ns.h includes stdint.
Probably better template-fu could avoid these ugly defines.
*/
#endif
#include "ns.h"
#else /* KN_PRIVATE */
/*
* Standard headers.
*/
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
/*
* Linux-specific types.
*/
#ifdef __linux
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
/* You must set the above macro in order to get the SIZE_MAX defined.
You have to set it before including stdint.
Probably better template-fu could avoid these ugly defines.
*/
#endif
#include <stdint.h>
#endif /* __linux */
/*
* Manually import from the std namespace.
*/
#ifndef WIN32
using std::size_t;
#endif /* !WIN32 */
#endif /* KN_PRIVATE */
/*
* Windows-specific types.
*/
#ifdef WIN32
#include <windows.h>
#define int8_t __int8
#define int16_t __int16
#define int32_t __int32
#define int64_t __int64
#define uint8_t BYTE
#define uint16_t WORD
#define uint32_t UINT32
#define uint64_t UINT64
#endif /* WIN32 */
// Explicitly use 32 bits for time even on 64-bit systems until we
// don't have to support 32-bit systems (hopefully before 2038)
// We use signed values here, where often (especially in expiration times),
// negative values mean relative time and positives mean absolute.
typedef int32_t KnTime_t;
#define KNTIME_INFINITY INT_MAX
#define KNPF_KNTIMET_FMT "%d"
#ifndef WIN32
#define UNREFERENCED_PARAMETER(P) (P)
#endif
/*
* Debugging macros. At present, we allow assertions in production builds; we'd
* rather fail quick (and allow the cluster to recover) than run badly.
* Implemented in crashhandler.cpp
*/
#ifndef NO_ASSERTS
#define KN_ASSERT(exp) (void)((exp) || (KnAssert(#exp,__FILE__,__LINE__), 0) )
#else
#define KN_ASSERT(exp) ((void)0)
#endif /* NO_ASSERTS */
#include "knexportlibraryknutil.h"
extern EXPORT_LIBRARY_KNUTIL void KnAssert(char *exp, char *file, unsigned line);
#define SAFE_DELETE(p) { if(p != NULL){ delete p; p = NULL;} }
#define SAFE_DELETE_ARRAY(p) { if(p != NULL){ delete[] p; p = NULL;} }
#endif /* KNTYPES_H */
--- NEW FILE: knurl.h ---
#ifndef KNURL_H
#define KNURL_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/knstring.h"
#include "knutil/knset.h" /* so we can url-encode sets */
/**
* Represents an Url, allowing you to retrieve its constituent parts
*/
class EXPORT_LIBRARY_KNUTIL KnUrl
{
public:
// Must copy string in since we break it into parts.
KnUrl(const KnString &url);
KnUrl(const char *url);
KnUrl(const char *scheme, const char *user, const char *passwd, const char *host, const int port, const char *path, const char *query, const char *fragment);
~KnUrl();
bool is_error(KnString& error) ;
std::string get_root() const ;
const KnString& get_host() const
{
if (!m_parsed)
parse();
return m_host ;
};
// Proper name for "protocol" part.
const KnString& get_scheme() const
{
if (!m_parsed)
this->parse();
return m_scheme ;
};
bool isHttp() const
{
return (m_scheme == KnStringConstants::http);
}
bool isHttps() const
{
return (m_scheme == KnStringConstants::https);
}
// deprecated
const KnString& get_protocol() const
{
return get_scheme() ;
};
const KnString& get_port() const
{
if (!m_parsed)
parse();
return m_port ;
};
const KnString& get_user() const
{
if (!m_parsed)
parse();
return m_user ;
};
const KnString& get_password() const
{
if (!m_parsed)
parse();
return m_password ;
};
const KnString& get_path() const
{
if (!m_parsed)
parse();
return m_path ;
};
const KnString& get_basename() const
{
if (!m_parsed)
parse();
return m_basename ;
};
// Terminology here is from section 4.2, RFC2986
bool isNonNetworkRelativeRef() const {
// A relative ref that is *not* a network-path reference
if (!m_parsed) { this->parse() ; }
return (m_host.length() == 0);
}
static bool isAbsolute(const char *p) {
KN_ASSERT(p != 0);
// If you hit a ':' before any other hier-part, you
// know it's absolute. Also: don't go more than 8 chars,
// since we really only care about http:, file:, and https:
const char *stop = p + 8;
while (*p != '\0' && p < stop) {
switch (*p) {
case '/':
case '?':
case '#':
return false;
case ':':
return true;
}
++p;
}
return false;
}
// This needs to be fast, so it works in both representations:
// Note that by 3986, there are *relative* refs that start
// with '//{authority}'.
bool isAbsolute() const {
if (m_parsed) {
return 0 != m_scheme.length();
} else {
return isAbsolute(m_string);
}
}
/* various "url-encoding" routines. */
// The encoded URL segment is added to the end of the buffer
// NOTES:
// this really is useful only for encoding *components* of URLs, and even there
// you have to be careful. It *will* encode all the reserved chars.
// so encode("http://fum?x={bar}#%baz")
// becomes http%3a%2f%2ffum%3fx%3d%7bbar%7d%23%25baz
// NOT http://fum?x=%7Dbar%7D#%25baz"
// It *should* use normalized encodings (upper case) but doesn't.
static void encode(KnString& buffer, const KnString& name);
static void encode(std::string& buffer, const KnString& name);
static void encode(std::string& buffer, const char *utf8);
// This urlencodes each key & value. Separates keys from
// values with =, and pairs with '&'. No leading special character
// (e.g., ?) is returned.
static void encode(std::string& buffer, const KnSet& knSet);
static void encode(std::string& buffer, const Ns_Set* pNsSet);
private:
// Not implemented
KnUrl();
KnUrl(const KnUrl &);
KnUrl &operator=(const KnUrl &);
// Implemented
void parse() const;
mutable KnString m_error;
mutable char* m_string;
mutable bool m_parsed;
mutable KnString m_scheme;
mutable KnString m_user;
mutable KnString m_password;
mutable KnString m_host;
mutable KnString m_port;
mutable KnString m_path;
mutable KnString m_basename;
};
#endif /* KNURL_H */
--- NEW FILE: mtrand.h ---
#ifndef MTRAND_H
#define MTRAND_H
// mtrand.h
// C++ include file for MT19937, with initialization improved 2002/1/26.
// Coded by Takuji Nishimura and Makoto Matsumoto.
// Ported to C++ by Jasper Bedaux 2003/1/1 (see http://www.bedaux.net/mtrand/).
// The generators returning floating point numbers are based on
// a version by Isaku Wada, 2002/01/09
//
// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The names of its contributors may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Any feedback is very welcome.
// http://www.math.keio.ac.jp/matumoto/emt.html
// email: matu...@math.keio.ac.jp
//
// Feedback about the C++ port should be sent to Jasper Bedaux,
// see http://www.bedaux.net/mtrand/ for e-mail address and info.
#include "knutil/knexportlibraryknutil.h"
// Mersenne Twister random number generator
class EXPORT_LIBRARY_KNUTIL MTRand_int32
{
public:
// default constructor: uses default seed only if this is the first instance
MTRand_int32() { if (!init) seed(5489UL); init = true; }
// constructor with 32 bit int as seed
MTRand_int32(unsigned long s) { seed(s); init = true; }
// constructor with array of size 32 bit ints as seed
MTRand_int32(const unsigned long* array, int size) { seed(array, size); init = true; }
// the two seed functions
void seed(unsigned long); // seed with 32 bit integer
void seed(const unsigned long*, int size); // seed with array
// overload operator() to make this a generator (functor)
unsigned long operator()() { return rand_int32(); }
virtual ~MTRand_int32() {} // destructor
protected: // used by derived classes, otherwise not accessible; use the ()-operator
unsigned long rand_int32(); // generate 32 bit random integer
private:
static const int n = 624;
static const int m = 397; // compile time constants
// the variables below are static (no duplicates can exist)
static unsigned long state[n]; // state vector array
static int p; // position in state array
static bool init; // true if init function is called
// private functions used to generate the pseudo random numbers
unsigned long twiddle(unsigned long, unsigned long); // used by gen_state()
void gen_state(); // generate new state
// make copy constructor and assignment operator unavailable, they don't make sense
MTRand_int32(const MTRand_int32&); // copy constructor not defined
void operator=(const MTRand_int32&); // assignment operator not defined
};
// inline for speed, must therefore reside in header file
inline unsigned long MTRand_int32::twiddle(unsigned long u, unsigned long v) {
return (((u & 0x80000000UL) | (v & 0x7FFFFFFFUL)) >> 1)
^ ((v & 1UL) ? 0x9908B0DFUL : 0x0UL);
}
inline unsigned long MTRand_int32::rand_int32() { // generate 32 bit random int
if (p == n) gen_state(); // new state vector needed
// gen_state() is split off to be non-inline, because it is only called once
// in every 624 calls and otherwise irand() would become too big to get inlined
unsigned long x = state[p++];
x ^= (x >> 11);
x ^= (x << 7) & 0x9D2C5680UL;
x ^= (x << 15) & 0xEFC60000UL;
return x ^ (x >> 18);
}
// generates double floating point numbers in the half-open interval [0, 1)
class EXPORT_LIBRARY_KNUTIL MTRand : public MTRand_int32 {
public:
MTRand() : MTRand_int32() {}
MTRand(unsigned long seed) : MTRand_int32(seed) {}
MTRand(const unsigned long* seed, int size) : MTRand_int32(seed, size) {}
~MTRand() {}
double operator()() {
return static_cast<double>(rand_int32()) * (1. / 4294967296.); } // divided by 2^32
private:
MTRand(const MTRand&); // copy constructor not defined
void operator=(const MTRand&); // assignment operator not defined
};
// generates double floating point numbers in the closed interval [0, 1]
class EXPORT_LIBRARY_KNUTIL MTRand_closed : public MTRand_int32 {
public:
MTRand_closed() : MTRand_int32() {}
MTRand_closed(unsigned long seed) : MTRand_int32(seed) {}
MTRand_closed(const unsigned long* seed, int size) : MTRand_int32(seed, size) {}
~MTRand_closed() {}
double operator()() {
return static_cast<double>(rand_int32()) * (1. / 4294967295.); } // divided by 2^32 - 1
private:
MTRand_closed(const MTRand_closed&); // copy constructor not defined
void operator=(const MTRand_closed&); // assignment operator not defined
};
// generates double floating point numbers in the open interval (0, 1)
class EXPORT_LIBRARY_KNUTIL MTRand_open : public MTRand_int32 {
public:
MTRand_open() : MTRand_int32() {}
MTRand_open(unsigned long seed) : MTRand_int32(seed) {}
MTRand_open(const unsigned long* seed, int size) : MTRand_int32(seed, size) {}
~MTRand_open() {}
double operator()() {
return (static_cast<double>(rand_int32()) + .5) * (1. / 4294967296.); } // divided by 2^32
private:
MTRand_open(const MTRand_open&); // copy constructor not defined
void operator=(const MTRand_open&); // assignment operator not defined
};
// generates 53 bit resolution doubles in the half-open interval [0, 1)
class EXPORT_LIBRARY_KNUTIL MTRand53 : public MTRand_int32 {
public:
MTRand53() : MTRand_int32() {}
MTRand53(unsigned long seed) : MTRand_int32(seed) {}
MTRand53(const unsigned long* seed, int size) : MTRand_int32(seed, size) {}
~MTRand53() {}
double operator()() {
return (static_cast<double>(rand_int32() >> 5) * 67108864. +
static_cast<double>(rand_int32() >> 6)) * (1. / 9007199254740992.); }
private:
MTRand53(const MTRand53&); // copy constructor not defined
void operator=(const MTRand53&); // assignment operator not defined
};
#endif // MTRAND_H
--- NEW FILE: randomnumber.h ---
#ifndef RANDOMNUMBER_H
#define RANDOMNUMBER_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
/*
* Please see http://burtleburtle.net/bob/rand/isaacafa.html for
* design and documentation.
*/
class EXPORT_LIBRARY_KNUTIL RandomNumber
{
public:
RandomNumber(const uint32_t *seed, uint32_t len);
~RandomNumber();
uint32_t rand();
private:
// Not implemented
RandomNumber();
RandomNumber(const RandomNumber &);
RandomNumber &operator=(const RandomNumber &);
enum
{
RANDSIZL = 8,
RANDSIZ = (1 << RANDSIZL)
};
void isaac();
void randinit();
uint32_t m_randa;
uint32_t m_randb;
uint32_t m_randc;
uint32_t m_randcnt;
uint32_t m_randmem[RANDSIZ];
uint32_t m_randrsl[RANDSIZ];
};
#endif /* RANDOMNUMBER_H */
--- NEW FILE: shahash.h ---
#ifndef SHAHASH_H
#define SHAHASH_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
/*
* Based upon Peter Gutmann's public domain code. Test vectors can be found at
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
class EXPORT_LIBRARY_KNUTIL ShaHash
{
public:
ShaHash();
~ShaHash();
enum
{
BlockLen = 64,
BlockWords = 16,
DigestLen = 20,
DigestWords = 5
};
/*
* Transform into the given digest (of length DigestWords) the hash
* of the given block (of length BlockWords).
*/
static void transform(uint32_t *digest, uint32_t *block);
/*
* Freeze the digest.
*/
void final(uint8_t *digest);
/*
* Add data to the hash.
*/
void update(const void *buf, uint32_t len);
private:
// Not implemented
ShaHash(const ShaHash &);
ShaHash &operator=(const ShaHash &);
uint32_t m_block[BlockWords];
uint32_t m_digest[DigestWords];
uint32_t m_count[2];
uint32_t m_index;
};
#endif /* SHAHASH_H */
--- NEW FILE: simplecache.h ---
#ifndef SIMPLECACHE_H
#define SIMPLECACHE_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "simplenull.h"
#include <list>
#include <map>
/**
* MRU Cache
* Contains up to a fixed size of "Most Recently Used" items, where items are assiciated with keys.
* When asked to fetch a value that is not in the cache, HandleNonExistingKeyFetch is called.
* When an item is removed from the cache, HandleItemRelease is called.
* In order to use the cache on implementations of those methods must be provided.
*
*/
template <typename Key, typename Value>
class SimpleCache
{
public:
SimpleCache(int size) :
maxSize(size)
{
}
virtual ~SimpleCache()
{
clear();
}
void clear()
{
for (ItrPtrMap::iterator i=m_iterators.begin(); i!=m_iterators.end(); i++)
{
void* ptrItr = i->second;
EntryList::iterator* pItr = (EntryList::iterator*) ptrItr;
delete *(*pItr);
delete ptrItr;
}
m_entries.clear();
m_iterators.clear();
}
Value get(const Key& key)
{
// look for the iterator corresponding to the key
EntryList::iterator* ptrItr = (EntryList::iterator*) m_iterators[key];
if (ptrItr)
// cache hit
{
Entry* entry = *(*ptrItr);
m_entries.erase(*ptrItr);
m_entries.push_front(entry);
*ptrItr = m_entries.begin();
return entry->m_value;
}
else
// cache miss
{
return SimpleZeroTraits<Value>::null();
}
}
void put(const Key& key, const Value& value)
{
Entry* entry;
// check if cache is full
if ( (int)m_entries.size() >= maxSize )
{
// delete LRU entry
entry = m_entries.back();
m_entries.pop_back();
delete m_iterators[entry->m_key];
m_iterators.erase(entry->m_key);
delete entry;
}
// add entry to cache
entry = new Entry(key, value);
m_entries.push_front(entry);
EntryList::iterator* ptrItr = new EntryList::iterator();
*ptrItr = m_entries.begin();
m_iterators[key] = ptrItr;
}
private:
struct Entry
{
Entry(const Key& key, const Value& value) :
m_key(key), m_value(value)
{
}
Key m_key;
Value m_value;
};
// keep entries in a list to help determinig LRU entry
typedef std::list<Entry*> EntryList;
EntryList m_entries;
// to speed up the search, use a map containing pointers to iterators in EntryList
typedef std::map<Key, void*> ItrPtrMap;
ItrPtrMap m_iterators;
const int maxSize;
};
#endif /* SIMPLESYNCMAP_H */
--- NEW FILE: simpleheap.h ---
#ifndef SIMPLEHEAP_H
#define SIMPLEHEAP_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/simplevector.h"
template<typename Elem>
class SimpleHeap
{
public:
SimpleHeap()
{
}
SimpleHeap(const SimpleHeap &heap) :
m_vec(heap.m_vec)
{
}
SimpleHeap(const SimpleVector<Elem> &vec) :
m_vec(vec)
{
/*
* Convert to a heap.
*/
convert();
}
~SimpleHeap()
{
}
SimpleHeap &operator=(const SimpleHeap &heap)
{
/*
* Let the vector worry about object identity.
*/
m_vec = heap.m_vec;
return *this;
}
SimpleHeap &operator=(const SimpleVector<Elem> &vec)
{
/*
* Let the vector worry about object identity.
*/
m_vec = vec;
/*
* Convert to a heap.
*/
convert();
return *this;
}
void clear()
{
m_vec.clear();
}
bool empty() const
{
return m_vec.empty();
}
bool pop()
{
if (empty())
{
return false;
}
else
{
/*
* There must be at least 1 element.
*/
size_t end = size() - 1;
/*
* Prepare to bubble the last child.
*/
Elem tmp = m_vec[end];
/*
* Move the largest element to the back.
*/
m_vec[end] = m_vec[0];
/*
* Reform the heap.
*/
adjust(0, end, tmp);
}
return m_vec.pop();
}
bool pop(Elem &elem)
{
if (empty())
{
return false;
}
else
{
/*
* There must be at least 1 element.
*/
size_t end = size() - 1;
/*
* Prepare to bubble the last child.
*/
Elem tmp = m_vec[end];
/*
* Move the largest element to the back.
*/
m_vec[end] = m_vec[0];
/*
* Reform the heap.
*/
adjust(0, end, tmp);
}
return m_vec.pop(elem);
}
bool push(const Elem &elem)
{
if (!m_vec.push(elem))
{
return false;
}
else
{
/*
* There must be at least 1 element.
*/
size_t end = size() - 1;
/*
* Prepare to bubble the last child.
*/
Elem tmp = m_vec[end];
size_t n = (end - 1) / 2;
/*
* Shuffle parents into place.
*/
while (end > 0 && m_vec[n] < tmp)
{
m_vec[end] = m_vec[n];
end = n;
n = (end - 1) / 2;
}
m_vec[end] = tmp;
}
return true;
}
size_t size() const
{
return m_vec.size();
}
bool top(Elem &elem) const
{
if (empty())
{
return false;
}
else
{
elem = m_vec[0];
}
return true;
}
private:
void adjust(size_t pos, size_t end, const Elem &elem)
{
size_t m = pos;
size_t n = (2 * pos) + 2;
/*
* Shuffle children into place.
*/
while (n < end)
{
if (m_vec[n] < m_vec[n - 1])
{
--n;
}
m_vec[pos] = m_vec[n];
pos = n;
n = 2 * (n + 1);
}
/*
* Check for off-by-one.
*/
if (n == end)
{
m_vec[pos] = m_vec[n - 1];
pos = n - 1;
}
n = (pos - 1) / 2;
/*
* Shuffle parents into place.
*/
while (pos > m && m_vec[n] < elem)
{
m_vec[pos] = m_vec[n];
pos = n;
n = (pos - 1) / 2;
}
m_vec[pos] = elem;
}
void convert()
{
size_t end = size();
/*
* Shuffle elements into place.
*/
if (end >= 2)
{
size_t pos = (end - 2) / 2;
do
{
adjust(pos, end, m_vec[pos]);
}
while (pos-- > 0);
}
}
SimpleVector<Elem> m_vec;
};
#endif /* SIMPLEHEAP_H */
--- NEW FILE: simpleiterator.h ---
#ifndef SIMPLEITERATOR_H
#define SIMPLEITERATOR_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#ifdef WIN32
#pragma warning ( disable : 4786 ) // Mangled name truncated to 255 chars
#endif
/*
* Interface for iterators.
*/
template<typename Elem>
class SimpleIterator
{
public:
SimpleIterator()
{
}
virtual ~SimpleIterator()
{
}
/*
* Whether any elements remain.
*/
virtual bool hasNext() = 0;
/*
* Retrieve the next element.
*/
virtual Elem &next() = 0;
/*
* Remove the current element.
*/
virtual void remove() = 0;
private:
// Not implemented
SimpleIterator(const SimpleIterator &);
SimpleIterator &operator=(const SimpleIterator &);
};
#endif /* SIMPLEITERATOR_H */
--- NEW FILE: simplelist.h ---
#ifndef SIMPLELIST_H
#define SIMPLELIST_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include <sys/types.h>
#include <cstddef>
#include "knutil/simpleiterator.h"
#ifdef WIN32
#pragma warning ( disable : 4710 ) // Not inlined
#endif
template<typename Elem>
class SimpleListIterator;
template<typename Elem>
class SimpleList
{
public:
SimpleList() :
m_head(0),
m_tail(0),
m_size(0)
{
}
SimpleList(const SimpleList &list) :
m_head(0),
m_tail(0),
m_size(0)
{
copy(list);
}
~SimpleList()
{
clear();
}
SimpleList &operator=(const SimpleList &list)
{
if (this != &list)
{
clear();
copy(list);
}
return *this;
}
bool adopt(SimpleList &list)
{
if (this != &list)
{
/*
* Treat adoption as an optimized append.
*/
if (m_head == 0)
{
m_head = list.m_head;
m_tail = list.m_tail;
}
else if (list.m_head != 0)
{
m_tail->m_next = list.m_head;
m_tail = list.m_tail;
}
m_size += list.m_size;
/*
* Reset the given list to the empty state.
*/
list.m_head = 0;
list.m_tail = 0;
list.m_size = 0;
}
return true;
}
/*
* Prepends the given list to the current list
*/
bool prependList(SimpleList &list)
{
if (this != &list)
{
if (m_head == 0)
{
m_head = list.m_head;
m_tail = list.m_tail;
}
else if (list.m_head != 0)
{
list.m_tail->m_next = m_head;
m_head = list.m_head;
}
m_size += list.m_size;
/*
* Reset the given list to the empty state.
*/
list.m_head = 0;
list.m_tail = 0;
list.m_size = 0;
}
return true;
}
bool append(const Elem &elem)
{
return insert(m_tail, new Link(0, elem));
}
void clear()
{
/*
* Run destructors, and dispose of heap allocation.
*/
for (Link *curr; (curr = m_head) != 0; delete curr)
{
m_head = m_head->m_next;
}
/*
* Reset to original state.
*/
m_head = 0;
m_tail = 0;
m_size = 0;
}
bool empty() const
{
return m_size == 0;
}
bool pop()
{
if (m_head == 0)
{
return false;
}
else
{
remove(0, m_head);
}
return true;
}
bool pop(Elem &elem)
{
return top(elem) && pop();
}
bool prepend(const Elem &elem)
{
return insert(0, new Link(m_head, elem));
}
bool push(const Elem &elem)
{
return prepend(elem);
}
size_t size() const
{
return m_size;
}
bool top(Elem &elem) const
{
if (m_head == 0)
{
return false;
}
else
{
elem = m_head->m_elem;
}
return true;
}
private:
friend class SimpleListIterator<Elem>;
/*
* Helper struct for internal storage.
*/
struct Link
{
Link(Link *next, const Elem &elem) :
m_next(next),
m_elem(elem)
{
}
Link *m_next;
Elem m_elem;
};
void copy(const SimpleList &list)
{
for (Link *curr = list.m_head; curr != 0; curr = curr->m_next)
{
append(curr->m_elem);
}
}
bool insert(Link *prev, Link *curr)
{
/*
* If prev is null, we are prepending into the list.
*/
if (prev != 0)
{
prev->m_next = curr;
}
else
{
m_head = curr;
}
/*
* Check for appending.
*/
if (m_tail == prev)
m_tail = curr;
/*
* Bump up the count after successful insertion.
*/
++m_size;
return true;
}
void remove(Link *prev, Link *curr, SimpleList *owner=0)
{
/*
* If prev is null, we are removing the first element.
*/
if (prev != 0)
{
prev->m_next = curr->m_next;
}
else
{
m_head = curr->m_next;
}
/*
* Check for removing the last element.
*/
if (m_tail == curr)
m_tail = prev;
/*
* Decrement the count after successful removal.
*/
--m_size;
/*
* Either prepend the link to a new owner, or delete it.
*/
if (owner != 0)
{
curr->m_next = owner->m_head;
owner->insert(0, curr);
}
else
{
delete curr;
curr = 0;
}
}
Link *m_head;
Link *m_tail;
size_t m_size;
};
template<typename Elem>
class SimpleListIterator : public SimpleIterator<Elem>
{
public:
/*
* Short-hand notation for SimpleList classes.
*/
typedef SimpleList<Elem> List;
typedef typename SimpleList<Elem>::Link Link;
SimpleListIterator(List &list, size_t pos=0) :
m_list(list),
m_curr(0),
m_prev(0),
m_advance(false)
{
/*
* Find the correct starting position.
*/
size_t size = m_list.size();
if (pos < size)
{
for (m_curr = m_list.m_head; pos-- > 0;)
{
m_prev = m_curr;
m_curr = m_curr->m_next;
}
}
}
virtual ~SimpleListIterator()
{
}
bool append(const Elem &elem)
{
return m_list.insert(m_curr, new Link(m_curr->m_next, elem));
}
virtual bool hasNext()
{
/*
* If we are not advancing pointers on the next call to next(),
* we only look at curr. Otherwise, check the next pointer.
*/
return m_curr != 0 && (!m_advance || m_curr->m_next != 0);
}
virtual Elem &next()
{
/*
* We should not advance when the pointers are in the proper position.
* This situation occurs after the constructor finishes, and after
* removing the current element.
*/
if (m_advance)
{
m_prev = m_curr;
m_curr = m_curr->m_next;
}
else
{
m_advance = true;
}
return m_curr->m_elem;
}
bool prepend(const Elem &elem)
{
/*
* We need to adjust the previous pointer to point to the
* just-inserted link.
*/
if (m_list.insert(m_prev, new Link(m_curr, elem)))
{
if (m_prev != 0)
{
m_prev = m_prev->m_next;
}
else
{
m_prev = m_list.m_head;
}
return true;
}
return false;
}
void relinquish(List &owner)
{
/*
* Transferring the current element causes the current pointer to
* be updated into the next position.
*/
Link *link = m_curr;
m_curr = m_curr->m_next;
m_advance = false;
m_list.remove(m_prev, link, &owner);
}
virtual void remove()
{
/*
* Removing the current element causes the current pointer to
* be updated into the next position.
*/
Link *link = m_curr;
m_curr = m_curr->m_next;
m_advance = false;
m_list.remove(m_prev, link);
}
private:
// Not implemented
SimpleListIterator();
SimpleListIterator(const SimpleListIterator &);
SimpleListIterator &operator=(const SimpleListIterator &);
List &m_list;
Link *m_curr;
Link *m_prev;
bool m_advance;
};
#endif /* SIMPLELIST_H */
--- NEW FILE: simplemap.h ---
#ifndef SIMPLEMAP_H
#define SIMPLEMAP_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include <stdlib.h>
#include "knutil/simpleiterator.h"
#include "knutil/simpletraits.h"
#include "knutil/simplenull.h"
#ifdef WIN32
#pragma warning ( disable: 4710 ) // Some things can't be inlined
#endif
/*
* Key is treated as a value. Value _should_ be a pointer.
*/
template<typename Key, typename Value>
class SimpleMapIterator;
template<typename Key, typename Value>
class SimpleMap
{
public:
/*
* Helper struct for iterators.
*/
struct Elem
{
Elem(const Key &key, const Value &value) :
m_key(key),
m_value(value)
{
}
Key m_key;
Value m_value;
};
SimpleMap(size_t max=64) :
m_table(0),
m_max(0),
m_size(0)
{
/*
* Set the high-bit only.
*/
m_max = ~(~m_max >> 1);
/*
* Round up to the next highest power of two.
*/
if (m_max > max)
{
for (m_max = 64; m_max < max; m_max <<= 1)
{
continue;
}
}
/*
* Initialize the table.
*/
m_table = static_cast<Link **>(malloc(m_max * sizeof(*m_table)));
for (size_t i = 0; i < m_max; ++i)
{
m_table[i] = 0;
}
}
SimpleMap(const SimpleMap &map) :
m_table(0),
m_max(0),
m_size(0)
{
copy(map);
}
virtual ~SimpleMap()
{
clear();
/*
* Additional clean-up.
*/
free(m_table);
}
SimpleMap &operator=(const SimpleMap &map)
{
if (this != &map)
{
clear();
/*
* Additional clean-up.
*/
free(m_table);
/*
* Reset to defaults.
*/
m_table = 0;
m_max = 0;
copy(map);
}
return *this;
}
void clear()
{
/*
* Delete the links, but not the table.
*/
for (size_t i = 0; i < m_max; ++i)
{
Link *head = m_table[i];
/*
* Reset the chain.
*/
m_table[i] = 0;
for (Link *curr; (curr = head) != 0; delete curr)
{
head = head->m_next;
}
}
/*
* Reset to defaults.
*/
m_size = 0;
}
bool contains(const Key &key) const
{
size_t code = SimpleHashTraits<Key>::get(key);
size_t pos = code & (m_max - 1);
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Key>::equals(elem.m_key, key))
{
return true;
}
}
}
return false;
}
bool empty() const
{
return m_size == 0;
}
Value get(const Key &key) const
{
size_t code = SimpleHashTraits<Key>::get(key);
size_t pos = code & (m_max - 1);
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Key>::equals(elem.m_key, key))
{
return elem.m_value;
}
}
}
return SimpleZeroTraits<Value>::null();
}
void put(const Key &key, const Value &value)
{
put(key, value, SimpleHashTraits<Key>::get(key));
}
Value remove(const Key &key)
{
/*
* Check the load factor.
*/
if (m_size <= (m_max / 2) && m_max > 64)
shrink();
size_t code = SimpleHashTraits<Key>::get(key);
size_t pos = code & (m_max - 1);
/*
* Keep track of the previous link.
*/
Link *prev = 0;
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Key>::equals(elem.m_key, key))
{
--m_size;
/*
* Remove the link.
*/
if (prev != 0)
{
prev->m_next = curr->m_next;
}
else
{
m_table[pos] = curr->m_next;
}
Value ovalue = elem.m_value;
/*
* Delete the link.
*/
delete curr;
curr = 0;
return ovalue;
}
}
prev = curr;
}
return SimpleZeroTraits<Value>::null();
}
size_t size() const
{
return m_size;
}
Value update(const Key &key, const Value &value)
{
size_t code = SimpleHashTraits<Key>::get(key);
size_t pos = code & (m_max - 1);
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Key>::equals(elem.m_key, key))
{
Value ovalue = elem.m_value;
/*
* Store the new value.
*/
elem.m_value = value;
return ovalue;
}
}
}
/*
* No match found.
*/
put(key, value, code);
return SimpleZeroTraits<Value>::null();
}
private:
friend class SimpleMapIterator<Key, Value>;
/*
* Helper struct for internal storage.
*/
struct Link
{
Link(Link *next, size_t code, const Key &key, const Value &value) :
m_next(next),
m_code(code),
m_elem(key, value)
{
}
Link(const Link &link) :
m_next(0),
m_code(link.m_code),
m_elem(link.m_elem)
{
}
Link *m_next;
size_t m_code;
Elem m_elem;
};
void copy(const SimpleMap &map)
{
/*
* Copy fields.
*/
m_table = static_cast<Link **>(malloc(map.m_max * sizeof(*m_table)));
m_max = map.m_max;
m_size = map.m_size;
/*
* Copy chains.
*/
for (size_t i = 0; i < map.m_max; ++i)
{
Link *tail = 0;
/*
* Reset the chain.
*/
m_table[i] = 0;
/*
* Maintain chain ordering.
*/
for (Link *curr = map.m_table[i]; curr != 0; curr = curr->m_next)
{
Link *link = new Link(*curr);
if (tail != 0)
{
tail->m_next = link;
}
else
{
m_table[i] = link;
}
tail = link;
}
}
}
void expand()
{
/*
* Double the table size.
*/
size_t max = (m_max * 2);
Link **table = static_cast<Link **>(
realloc(m_table, max * sizeof(*m_table)));
/*
* Partition the chains.
*/
if (table != 0)
{
for (size_t i = 0; i < m_max; ++i)
{
Link *curr = table[i];
/*
* Reset the chains.
*/
table[i] = 0;
table[i + m_max] = 0;
/*
* Maintain chain ordering.
*/
for (Link *tailOld = 0, *tailNew = 0; curr != 0;)
{
Link *next = curr->m_next;
/*
* Reset the link.
*/
curr->m_next = 0;
/*
* Test the new high-bit.
*/
if ((curr->m_code & m_max) != 0)
{
if (tailNew != 0)
{
tailNew->m_next = curr;
}
else
{
table[i + m_max] = curr;
}
tailNew = curr;
}
else
{
if (tailOld != 0)
{
tailOld->m_next = curr;
}
else
{
table[i] = curr;
}
tailOld = curr;
}
curr = next;
}
}
m_table = table;
m_max = max;
}
}
void put(const Key &key, const Value &value, size_t code)
{
/*
* Check the load factor, and detect bit overflow.
*/
if (m_size >= (m_max * 2) && (m_max * 2) > 0)
expand();
size_t pos = code & (m_max - 1);
/*
* Allocate a new link.
*/
Link *link = new Link(m_table[pos], code, key, value);
/*
* Prepend the link.
*/
m_table[pos] = link;
++m_size;
}
void shrink()
{
/*
* Halve the table size.
*/
size_t max = (m_max / 2);
/*
* Coalesce the chains.
*/
for (size_t i = 0; i < max; ++i)
{
Link *curr = m_table[i];
for (; curr != 0 && curr->m_next != 0; curr = curr->m_next)
{
continue;
}
if (curr != 0)
{
curr->m_next = m_table[i + max];
}
else
{
m_table[i] = m_table[i + max];
}
}
/*
* Shrink the table.
*/
Link **table = static_cast<Link **>(
realloc(m_table, max * sizeof(*m_table)));
if (table != 0)
m_table = table;
/*
* Must always update m_max.
*/
m_max = max;
}
void unlink(Link *link)
{
size_t code = link->m_code;
size_t pos = code & (m_max - 1);
/*
* Keep track of the previous link.
*/
Link *prev = 0;
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
if (curr == link)
{
--m_size;
/*
* Remove the link.
*/
if (prev != 0)
{
prev->m_next = curr->m_next;
}
else
{
m_table[pos] = curr->m_next;
}
/*
* Delete the link.
*/
delete curr;
curr = 0;
break;
}
prev = curr;
}
}
Link **m_table;
size_t m_max;
size_t m_size;
};
template<typename Key, typename Value>
class SimpleMapIterator : public SimpleIterator<typename SimpleMap<Key, Value>::Elem>
{
public:
/*
* Short-hand notation for SimpleMap classes.
*/
typedef SimpleMap<Key, Value> Map;
typedef typename SimpleMap<Key, Value>::Elem Elem;
typedef typename SimpleMap<Key, Value>::Link Link;
SimpleMapIterator(Map &map) :
m_map(map),
m_curr(0),
m_prev(0),
m_pos(0)
{
/*
* Find the first valid chain.
*/
for (; m_pos < m_map.m_max; ++m_pos)
{
if ((m_curr = m_map.m_table[m_pos]) != 0)
break;
}
}
virtual ~SimpleMapIterator()
{
}
virtual bool hasNext()
{
return m_curr != 0;
}
virtual Elem &next()
{
m_prev = m_curr;
m_curr = m_curr->m_next;
/*
* Find the next valid chain.
*/
if (m_curr == 0)
{
for (++m_pos; m_pos < m_map.m_max; ++m_pos)
{
if ((m_curr = m_map.m_table[m_pos]) != 0)
break;
}
}
return m_prev->m_elem;
}
virtual void remove()
{
m_map.unlink(m_prev);
m_prev = 0;
}
private:
// Not implemented
SimpleMapIterator();
SimpleMapIterator(const SimpleMapIterator &);
SimpleMapIterator &operator=(const SimpleMapIterator &);
Map &m_map;
Link *m_curr;
Link *m_prev;
size_t m_pos;
};
#endif /* SIMPLEMAP_H */
--- NEW FILE: simplenull.h ---
#ifndef SIMPLENULL_H
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define SIMPLENULL_H
/*
* Define the "null" (not-found) value for a type
*/
template<typename T>
struct SimpleZeroTraits
{
static inline T null()
{
return 0;
}
};
#endif
--- NEW FILE: simplequeue.h ---
#ifndef SIMPLEQUEUE_H
#define SIMPLEQUEUE_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include <cstddef>
#include "knutil/simpleiterator.h"
template<typename Elem>
class SimpleQueueIterator;
template<typename Elem>
class SimpleQueue
{
public:
SimpleQueue() :
m_head(0),
m_tail(0),
m_size(0)
{
}
SimpleQueue(const SimpleQueue &queue) :
m_head(0),
m_tail(0),
m_size(0)
{
copy(queue);
}
~SimpleQueue()
{
clear();
}
SimpleQueue &operator=(const SimpleQueue &queue)
{
if (this != &queue)
{
clear();
copy(queue);
}
return *this;
}
bool adopt(SimpleQueue &queue)
{
if (this != &queue)
{
/*
* Treat adoption as an optimized append.
*/
if (m_head == 0)
{
m_head = queue.m_head;
m_tail = queue.m_tail;
}
else if (queue.m_head != 0)
{
queue.m_head->m_prev = m_tail;
m_tail->m_next = queue.m_head;
m_tail = queue.m_tail;
}
m_size += queue.m_size;
/*
* Reset the given queue to the empty state.
*/
queue.m_head = 0;
queue.m_tail = 0;
queue.m_size = 0;
}
return true;
}
bool append(const Elem &elem)
{
return insert(new Link(0, m_tail, elem));
}
void clear()
{
/*
* Run destructors, and dispose of heap allocation.
*/
for (Link *curr; (curr = m_head) != 0; delete curr)
{
m_head = m_head->m_next;
}
/*
* Reset to original state.
*/
m_head = 0;
m_tail = 0;
m_size = 0;
}
bool empty() const
{
return m_size == 0;
}
bool pop()
{
if (m_head == 0)
{
return false;
}
else
{
remove(m_head);
}
return true;
}
bool pop(Elem &elem)
{
return top(elem) && pop();
}
bool prepend(const Elem &elem)
{
return insert(new Link(m_head, 0, elem));
}
bool push(const Elem &elem)
{
return prepend(elem);
}
size_t size() const
{
return m_size;
}
bool top(Elem &elem) const
{
if (m_head == 0)
{
return false;
}
else
{
elem = m_head->m_elem;
}
return true;
}
private:
friend class SimpleQueueIterator<Elem>;
/*
* Helper struct for internal storage.
*/
struct Link
{
Link(Link *next, Link *prev, const Elem &elem) :
m_next(next),
m_prev(prev),
m_elem(elem)
{
}
Link *m_next;
Link *m_prev;
Elem m_elem;
};
void copy(const SimpleQueue &queue)
{
for (Link *curr = queue.m_head; curr != 0; curr = curr->m_next)
{
append(curr->m_elem);
}
}
bool insert(Link *curr)
{
/*
* If m_prev is null, we are prepending into the queue.
*/
if (curr->m_prev != 0)
{
curr->m_prev->m_next = curr;
}
else
{
m_head = curr;
}
/*
* Check for appending.
*/
if (curr->m_next != 0)
{
curr->m_next->m_prev = curr;
}
else
{
m_tail = curr;
}
/*
* Bump up the count after successful insertion.
*/
++m_size;
return true;
}
void remove(Link *curr, SimpleQueue *owner=0)
{
/*
* If m_prev is null, we are removing the first element.
*/
if (curr->m_prev != 0)
{
curr->m_prev->m_next = curr->m_next;
}
else
{
m_head = curr->m_next;
}
/*
* Check for removing the last element.
*/
if (curr->m_next != 0)
{
curr->m_next->m_prev = curr->m_prev;
}
else
{
m_tail = curr->m_prev;
}
/*
* Decrement the count after successful removal.
*/
--m_size;
/*
* Either prepend the link to a new owner, or delete it.
*/
if (owner != 0)
{
curr->m_prev = 0;
curr->m_next = owner->m_head;
owner->insert(curr);
}
else
{
delete curr;
curr = 0;
}
}
Link *m_head;
Link *m_tail;
size_t m_size;
};
template<typename Elem>
class SimpleQueueIterator : public SimpleIterator<Elem>
{
public:
/*
* Short-hand notation for SimpleQueue classes.
*/
typedef SimpleQueue<Elem> Queue;
typedef typename SimpleQueue<Elem>::Link Link;
SimpleQueueIterator(Queue &queue, size_t pos=0) :
m_queue(queue),
m_curr(0),
m_last(0)
{
/*
* Find the correct starting position.
*/
size_t size = m_queue.size();
if (pos < (size / 2))
{
for (m_curr = m_queue.m_head; pos-- > 0;)
{
m_curr = m_curr->m_next;
}
}
else if (pos < size)
{
for (m_curr = m_queue.m_tail; ++pos < size;)
{
m_curr = m_curr->m_prev;
}
}
}
virtual ~SimpleQueueIterator()
{
}
bool append(const Elem &elem)
{
if (m_queue.insert(new Link(m_last->m_next, m_last, elem)))
{
if (m_curr != m_last)
m_curr = m_last->m_next;
return true;
}
return false;
}
virtual bool hasNext()
{
return m_curr != 0;
}
bool hasPrevious()
{
return m_curr != m_queue.m_head;
}
virtual Elem &next()
{
m_last = m_curr;
m_curr = m_curr->m_next;
return m_last->m_elem;
}
bool prepend(const Elem &elem)
{
return m_queue.insert(new Link(m_last, m_last->m_prev, elem));
}
Elem &previous()
{
Link *link = (m_curr != 0 ? m_curr->m_prev : m_queue.m_tail);
m_last = link;
m_curr = link;
return m_last->m_elem;
}
void relinquish(Queue &owner)
{
m_curr = m_last->m_next;
m_queue.remove(m_last, &owner);
m_last = 0;
}
virtual void remove()
{
m_curr = m_last->m_next;
m_queue.remove(m_last);
m_last = 0;
}
private:
// Not implemented
SimpleQueueIterator();
SimpleQueueIterator(const SimpleQueueIterator &);
SimpleQueueIterator &operator=(const SimpleQueueIterator &);
Queue &m_queue;
Link *m_curr;
Link *m_last;
};
#endif /* SIMPLEQUEUE_H */
--- NEW FILE: simpleset.h ---
#ifndef SIMPLESET_H
#define SIMPLESET_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/simpleiterator.h"
#include "knutil/simpletraits.h"
#include "knutil/simplenull.h"
#ifdef WIN32
#pragma warning ( disable : 4710 ) // Not inlined
#endif
/*
* Elem _should_ be a pointer.
*/
template<typename Elem>
class SimpleSetIterator;
template<typename Elem>
class SimpleSet
{
public:
SimpleSet( size_t max = 64 ) :
m_table(0),
m_max(0),
m_size(0)
{
/*
* Set the high-bit only.
*/
m_max = ~(~m_max >> 1);
/*
* Round up to the next highest power of two.
*/
if (m_max > max)
{
for (m_max = 64; m_max < max; m_max <<= 1)
{
continue;
}
}
/*
* Initialize the table.
*/
m_table = static_cast<Link **>(malloc(m_max * sizeof(*m_table)));
for (size_t i = 0; i < m_max; ++i)
{
m_table[i] = 0;
}
}
SimpleSet(const SimpleSet &set) :
m_table(0),
m_max(0),
m_size(0)
{
copy(set);
}
~SimpleSet()
{
clear();
/*
* Additional clean-up.
*/
free(m_table);
}
SimpleSet &operator=(const SimpleSet &set)
{
if (this != &set)
{
clear();
/*
* Additional clean-up.
*/
free(m_table);
/*
* Reset to defaults.
*/
m_table = 0;
m_max = 0;
copy(set);
}
return *this;
}
void clear()
{
/*
* Delete the links, but not the table.
*/
for (size_t i = 0; i < m_max; ++i)
{
Link *head = m_table[i];
/*
* Reset the chain.
*/
m_table[i] = 0;
for (Link *curr; (curr = head) != 0; delete curr)
{
head = head->m_next;
}
}
/*
* Reset to defaults.
*/
m_size = 0;
}
template<typename Key>
bool contains(const Key &key) const
{
return find(key) != NULL;
}
template<typename Key>
Elem get(const Key &key) const
{
Link* link = find(key);
if(link)
return link->m_elem;
return SimpleZeroTraits<Elem>::null();
}
bool empty() const
{
return m_size == 0;
}
void put(const Elem &elem)
{
put(elem, SimpleHashTraits<Elem>::get(elem));
}
template<typename Key>
Elem remove(const Key &key)
{
/*
* Check the load factor.
*/
if (m_size <= (m_max / 2) && m_max > 64)
shrink();
size_t code = SimpleHashTraits<Key>::get(key);
size_t pos = code & (m_max - 1);
/*
* Keep track of the previous link.
*/
Link *prev = 0;
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Elem, Key>::equals(elem, key))
{
--m_size;
/*
* Remove the link.
*/
if (prev != 0)
{
prev->m_next = curr->m_next;
}
else
{
m_table[pos] = curr->m_next;
}
Elem oelem = elem;
/*
* Delete the link.
*/
delete curr;
curr = 0;
return oelem;
}
}
prev = curr;
}
return SimpleZeroTraits<Elem>::null();
}
size_t size() const
{
return m_size;
}
Elem update(const Elem &nelem)
{
size_t code = SimpleHashTraits<Elem>::get(nelem);
size_t pos = code & (m_max - 1);
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Elem>::equals(elem, nelem))
{
Elem oelem = elem;
/*
* Store the new value.
*/
elem = nelem;
return oelem;
}
}
}
/*
* No match found.
*/
put(nelem, code);
return 0;
}
private:
friend class SimpleSetIterator<Elem>;
/*
* Helper struct for internal storage.
*/
struct Link
{
Link(Link *next, size_t code, const Elem &elem) :
m_next(next),
m_code(code),
m_elem(elem)
{
}
Link(const Link &link) :
m_next(0),
m_code(link.m_code),
m_elem(link.m_elem)
{
}
Link *m_next;
size_t m_code;
Elem m_elem;
};
template<typename Key>
Link* find(const Key &key) const
{
size_t code = SimpleHashTraits<Key>::get(key);
size_t pos = code & (m_max - 1);
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Elem, Key>::equals(elem, key))
{
return curr;
}
}
}
return NULL;
}
void copy(const SimpleSet &set)
{
/*
* Copy fields.
*/
m_table = static_cast<Link **>(malloc(set.m_max * sizeof(*m_table)));
m_max = set.m_max;
m_size = set.m_size;
/*
* Copy chains.
*/
for (size_t i = 0; i < set.m_max; ++i)
{
Link *tail = 0;
/*
* Reset the chain.
*/
m_table[i] = 0;
/*
* Maintain chain ordering.
*/
for (Link *curr = set.m_table[i]; curr != 0; curr = curr->m_next)
{
Link *link = new Link(*curr);
if (tail != 0)
{
tail->m_next = link;
}
else
{
m_table[i] = link;
}
tail = link;
}
}
}
void expand()
{
/*
* Double the table size.
*/
size_t max = (m_max * 2);
Link **table = static_cast<Link **>(
realloc(m_table, max * sizeof(*m_table)));
/*
* Partition the chains.
*/
if (table != 0)
{
for (size_t i = 0; i < m_max; ++i)
{
Link *curr = table[i];
/*
* Reset the chains.
*/
table[i] = 0;
table[i + m_max] = 0;
/*
* Maintain chain ordering.
*/
for (Link *tailOld = 0, *tailNew = 0; curr != 0;)
{
Link *next = curr->m_next;
/*
* Reset the link.
*/
curr->m_next = 0;
/*
* Test the new high-bit.
*/
if ((curr->m_code & m_max) != 0)
{
if (tailNew != 0)
{
tailNew->m_next = curr;
}
else
{
table[i + m_max] = curr;
}
tailNew = curr;
}
else
{
if (tailOld != 0)
{
tailOld->m_next = curr;
}
else
{
table[i] = curr;
}
tailOld = curr;
}
curr = next;
}
}
m_table = table;
m_max = max;
}
}
void put(const Elem &elem, size_t code)
{
/*
* Check the load factor, and detect bit overflow.
*/
if (m_size >= (m_max * 2) && (m_max * 2) > 0)
expand();
size_t pos = code & (m_max - 1);
/*
* Allocate a new link.
*/
Link *link = new Link(m_table[pos], code, elem);
/*
* Prepend the link.
*/
m_table[pos] = link;
++m_size;
}
void shrink()
{
/*
* Halve the table size.
*/
size_t max = (m_max / 2);
/*
* Coalesce the chains.
*/
for (size_t i = 0; i < max; ++i)
{
Link *curr = m_table[i];
for (; curr != 0 && curr->m_next != 0; curr = curr->m_next)
{
continue;
}
if (curr != 0)
{
curr->m_next = m_table[i + max];
}
else
{
m_table[i] = m_table[i + max];
}
}
/*
* Shrink the table.
*/
Link **table = static_cast<Link **>(
realloc(m_table, max * sizeof(*m_table)));
if (table != 0)
m_table = table;
/*
* Must always update m_max.
*/
m_max = max;
}
void unlink(Link *link)
{
size_t code = link->m_code;
size_t pos = code & (m_max - 1);
/*
* Keep track of the previous link.
*/
Link *prev = 0;
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
if (curr == link)
{
--m_size;
/*
* Remove the link.
*/
if (prev != 0)
{
prev->m_next = curr->m_next;
}
else
{
m_table[pos] = curr->m_next;
}
/*
* Delete the link.
*/
delete curr;
curr = 0;
break;
}
prev = curr;
}
}
Link **m_table;
size_t m_max;
size_t m_size;
};
template<typename Elem>
class SimpleSetIterator : public SimpleIterator<Elem>
{
public:
/*
* Short-hand notation for SimpleSet classes.
*/
typedef SimpleSet<Elem> Set;
typedef typename SimpleSet<Elem>::Link Link;
SimpleSetIterator(Set &set) :
m_set(set),
m_curr(0),
m_prev(0),
m_pos(0)
{
/*
* Find the first valid chain.
*/
for (; m_pos < m_set.m_max; ++m_pos)
{
if ((m_curr = m_set.m_table[m_pos]) != 0)
break;
}
}
virtual ~SimpleSetIterator()
{
}
virtual bool hasNext()
{
return m_curr != 0;
}
virtual Elem &next()
{
m_prev = m_curr;
m_curr = m_curr->m_next;
/*
* Find the next valid chain.
*/
if (m_curr == 0)
{
for (++m_pos; m_pos < m_set.m_max; ++m_pos)
{
if ((m_curr = m_set.m_table[m_pos]) != 0)
break;
}
}
return m_prev->m_elem;
}
virtual void remove()
{
m_set.unlink(m_prev);
m_prev = 0;
}
private:
// Not implemented
SimpleSetIterator();
SimpleSetIterator(const SimpleSetIterator &);
SimpleSetIterator &operator=(const SimpleSetIterator &);
Set &m_set;
Link *m_curr;
Link *m_prev;
size_t m_pos;
};
#endif /* SIMPLESET_H */
--- NEW FILE: simplesynccache.h ---
#ifndef SIMPLESYNCCACHE_H
#define SIMPLESYNCCACHE_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "simplenull.h"
#include "knrwlock.h"
#include <list>
#include <map>
/**
* MRU Cache
* Contains up to a fixed size of "Most Recently Used" items, where items are assiciated with keys.
* When asked to fetch a value that is not in the cache, HandleNonExistingKeyFetch is called.
* When an item is removed from the cache, HandleItemRelease is called.
* In order to use the cache on implementations of those methods must be provided.
*
*/
template <typename Key, typename Value>
class SimpleSyncCache
{
private:
public:
SimpleSyncCache(int size) :
maxSize(size)
{
}
virtual ~SimpleSyncCache()
{
clear();
}
void clear()
{
// Acquire lock on whole map structure
KnMutex::KnLock local_writelock(m_global_rwlock);
for (ItrPtrMapItr i=m_iterators.begin(); i!=m_iterators.end(); i++)
{
EntryListItr* ptrItr = i->second;
delete *(*ptrItr);
delete ptrItr;
}
m_entries.clear();
m_iterators.clear();
}
Value get(const Key& key)
{
// Acquire lock on whole map structure
KnMutex::KnLock local_writelock(m_global_rwlock);
// look for the iterator corresponding to the key
EntryListItr* ptrItr = (EntryListItr*) m_iterators[key];
if (ptrItr)
// cache hit
{
Entry* entry = *(*ptrItr);
m_entries.erase(*ptrItr);
m_entries.push_front(entry);
*ptrItr = m_entries.begin();
return entry->m_value;
}
else
// cache miss
{
return SimpleZeroTraits<Value>::null();
}
}
void put(const Key& key, const Value& value)
{
Entry* entry;
// Acquire lock on whole map structure
KnMutex::KnLock local_writelock(m_global_rwlock);
// check if cache is full
if ( (int)m_entries.size() >= maxSize )
{
// delete LRU entry
entry = m_entries.back();
m_entries.pop_back();
delete m_iterators[entry->m_key];
m_iterators.erase(entry->m_key);
delete entry;
}
// add entry to cache
entry = new Entry(key, value);
m_entries.push_front(entry);
EntryListItr* ptrItr = new EntryListItr();
*ptrItr = m_entries.begin();
m_iterators[key] = ptrItr;
}
private:
struct Entry
{
Entry(const Key& key, const Value& value) :
m_key(key), m_value(value)
{
}
Key m_key;
Value m_value;
};
typedef std::list<Entry*> EntryList;
typedef typename EntryList::iterator EntryListItr;
// to speed up the search, use a map containing pointers to iterators in EntryList
EntryList m_entries;
//typedef std::map<Key, void*> ItrPtrMap;
typedef std::map<Key, EntryListItr*> ItrPtrMap;
// keep entries in a list to help determinig LRU entry
ItrPtrMap m_iterators;
typedef typename ItrPtrMap::iterator ItrPtrMapItr;
const int maxSize;
mutable KnMutex m_global_rwlock;
};
#endif /* SIMPLESYNCMAP_H */
--- NEW FILE: simplesyncmap.h ---
#ifndef SIMPLESYNCMAP_H
#define SIMPLESYNCMAP_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/simpleiterator.h"
#include "knutil/simpletraits.h"
#include "knutil/simplenull.h"
#include "knutil/knmutex.h"
#ifdef WIN32
#pragma warning ( disable: 4710 ) // Some things can't be inlined
#endif
/*
* Key is treated as a value. Value _should_ be a pointer.
*/
template<typename Key, typename Value>
class SimpleSyncMapIterator;
template<typename Key, typename Value>
class SimpleSyncMap
{
public:
/*
* Helper struct for iterators.
*/
struct Elem
{
Elem(const Key &key, const Value &value) :
m_key(key),
m_value(value)
{
}
Key m_key;
Value m_value;
};
SimpleSyncMap(size_t max=64) :
m_table(0),
m_max(0),
m_size(0)
{
/* Acquire the global lock */
KnMutex::KnLock local_writelock(m_global_rwlock);
/*
* Set the high-bit only.
*/
m_max = ~(~m_max >> 1);
/*
* Round up to the next highest power of two.
*/
if (m_max > max)
{
for (m_max = 64; m_max < max; m_max <<= 1)
{
continue;
}
}
/*
* Initialize the table.
*/
m_table = static_cast<Link **>(malloc(m_max * sizeof(*m_table)));
/*
* Initilize the mutex vector ( one mutex per hash entry )
*/
for (size_t i = 0; i < m_max; ++i)
{
m_table[i] = 0;
}
}
SimpleSyncMap(const SimpleSyncMap &map) :
m_table(0),
m_max(0),
m_size(0)
{
/* Acquire lock on whole map structure */
KnMutex::KnLock local_writelock(m_global_rwlock);
copy(map);
}
virtual ~SimpleSyncMap()
{
/* Acquire lock on whole map structure */
KnMutex::KnLock local_writelock(m_global_rwlock);
clear();
/*
* Additional clean-up.
*/
free(m_table);
}
SimpleSyncMap &operator=(const SimpleSyncMap &map)
{
/* Acquire lock on whole map structure */
KnMutex::KnLock local_writelock(m_global_rwlock);
if (this != &map)
{
/* clear aquires it's own lock */
clear();
/*
* Additional clean-up.
*/
free(m_table);
/*
* Reset to defaults.
*/
m_table = 0;
m_max = 0;
copy(map);
}
return *this;
}
private:
/* made clear() private, since it's only used from destructor and the global rwlock
* is acquired there. If you need to make it public, then re-architect to make sure
* you don't have a path through function where the same lock is acquired multiple times
* from the same thread - which would deadlock.
*/
void clear()
{
/*
* Delete the links, but not the table.
*/
for (size_t i = 0; i < m_max; ++i)
{
Link *head = m_table[i];
/*
* Reset the chain.
*/
m_table[i] = 0;
for (Link *curr; (curr = head) != 0; delete curr)
{
head = head->m_next;
}
}
/*
* Reset to defaults.
*/
m_size = 0;
}
public:
bool contains(const Key &key) const
{
/* Acquire the global lock */
KnMutex::KnLock local_writelock(m_global_rwlock);
size_t code = SimpleHashTraits<Key>::get(key);
size_t pos = code & (m_max - 1);
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Key>::equals(elem.m_key, key))
{
return true;
}
}
}
return false;
}
bool empty() const
{
/* Acquire the global lock */
KnMutex::KnLock local_writelock(m_global_rwlock);
return m_size == 0;
}
Value get(const Key &key) const
{
/* Acquire the global lock */
KnMutex::KnLock local_writelock(m_global_rwlock);
size_t code = SimpleHashTraits<Key>::get(key);
size_t pos = code & (m_max - 1);
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Key>::equals(elem.m_key, key))
{
return elem.m_value;
}
}
}
return SimpleZeroTraits<Value>::null();
}
bool getKey(const Key &key, const Key *&entry) const
{
/* Acquire the global lock */
KnMutex::KnLock local_writelock(m_global_rwlock);
size_t code = SimpleHashTraits<Key>::get(key);
size_t pos = code & (m_max - 1);
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Key>::equals(elem.m_key, key))
{
entry = &elem.m_key;
return true;
}
}
}
return false;
}
void put(const Key &key, const Value &value)
{
KnMutex::KnLock local_writelock(m_global_rwlock);
put(key, value, SimpleHashTraits<Key>::get(key));
}
Value remove(const Key &key)
{
/* Acquire global readlock */
KnMutex::KnLock local_writelock(m_global_rwlock);
/*
* Check the load factor.
*/
if (m_size <= (m_max / 2) && m_max > 64)
{
/* change the lock on global to write lock, but to avoid deadlock because
of multiple lock request on same lock in same thread, first release the readlock,
then aquire the write lock */
shrink();
}
size_t code = SimpleHashTraits<Key>::get(key);
size_t pos = code & (m_max - 1);
/*
* Keep track of the previous link.
*/
Link *prev = 0;
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Key>::equals(elem.m_key, key))
{
--m_size;
/*
* Remove the link.
*/
if (prev != 0)
{
prev->m_next = curr->m_next;
}
else
{
m_table[pos] = curr->m_next;
}
Value ovalue = elem.m_value;
/*
* Delete the link.
*/
delete curr;
curr = 0;
return ovalue;
}
}
prev = curr;
}
return SimpleZeroTraits<Value>::null();
}
// NOTE: don't use it from inside class, when we already have a lock, use m_size directly
// Re-enabled it as a public method for help in debugging
// KnPerm::KnNetworkFilter
size_t size() const
{
KnMutex::KnLock local_readlock(m_global_rwlock);
return m_size;
}
Value update(const Key &key, const Value &value)
{
/* Acquire global writelock */
KnMutex::KnLock local_writelock(m_global_rwlock);
size_t code = SimpleHashTraits<Key>::get(key);
size_t pos = code & (m_max - 1);
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
Elem &elem = curr->m_elem;
/*
* Compare hash codes before keys.
*/
if (curr->m_code == code)
{
if (SimpleCompareTraits<Key>::equals(elem.m_key, key))
{
Value ovalue = elem.m_value;
/*
* Store the new value.
*/
elem.m_value = value;
return ovalue;
}
}
}
/*
* No match found.
*/
put(key, value, code /*, local_readlock*/);
return SimpleZeroTraits<Value>::null();
}
private:
friend class SimpleSyncMapIterator<Key, Value>;
/*
* Helper struct for internal storage.
*/
struct Link
{
Link(Link *next, size_t code, const Key &key, const Value &value) :
m_next(next),
m_code(code),
m_elem(key, value)
{
}
Link(const Link &link) :
m_next(0),
m_code(link.m_code),
m_elem(link.m_elem)
{
}
Link *m_next;
size_t m_code;
Elem m_elem;
};
void copy(const SimpleSyncMap &map)
{
/*
* Copy fields.
*/
m_table = static_cast<Link **>(malloc(map.m_max * sizeof(*m_table)));
m_max = map.m_max;
m_size = map.m_size;
/*
* Copy chains.
*/
for (size_t i = 0; i < map.m_max; ++i)
{
Link *tail = 0;
/*
* Reset the chain.
*/
m_table[i] = 0;
/*
* Maintain chain ordering.
*/
for (Link *curr = map.m_table[i]; curr != 0; curr = curr->m_next)
{
Link *link = new Link(*curr);
if (tail != 0)
{
tail->m_next = link;
}
else
{
m_table[i] = link;
}
tail = link;
}
}
}
void expand()
{
/*
* Double the table size.
*/
size_t max = (m_max * 2);
Link **table = static_cast<Link **>(
realloc(m_table, max * sizeof(*m_table)));
/*
* Partition the chains.
*/
if (table != 0)
{
for (size_t i = 0; i < m_max; ++i)
{
Link *curr = table[i];
/*
* Reset the chains.
*/
table[i] = 0;
table[i + m_max] = 0;
/*
* Maintain chain ordering.
*/
for (Link *tailOld = 0, *tailNew = 0; curr != 0;)
{
Link *next = curr->m_next;
/*
* Reset the link.
*/
curr->m_next = 0;
/*
* Test the new high-bit.
*/
if ((curr->m_code & m_max) != 0)
{
if (tailNew != 0)
{
tailNew->m_next = curr;
}
else
{
table[i + m_max] = curr;
}
tailNew = curr;
}
else
{
if (tailOld != 0)
{
tailOld->m_next = curr;
}
else
{
table[i] = curr;
}
tailOld = curr;
}
curr = next;
}
}
m_table = table;
m_max = max;
}
}
void put(const Key &key, const Value &value, size_t code)
{
/*
* Check the load factor, and detect bit overflow.
*/
if (m_size >= (m_max * 2) && (m_max * 2) > 0){
expand();
}
size_t pos = code & (m_max - 1);
/*
* Allocate a new link.
*/
Link *link = new Link(m_table[pos], code, key, value);
/*
* Prepend the link.
*/
m_table[pos] = link;
/*Note:!! This should normally require a writelock on global_rwlock, but I think given
the current member function, a readlock should do fine */
++m_size;
}
void shrink()
{
/*
* Halve the table size.
*/
size_t max = (m_max / 2);
/*
* Coalesce the chains.
*/
for (size_t i = 0; i < max; ++i)
{
Link *curr = m_table[i];
for (; curr != 0 && curr->m_next != 0; curr = curr->m_next)
{
continue;
}
if (curr != 0)
{
curr->m_next = m_table[i + max];
}
else
{
m_table[i] = m_table[i + max];
}
}
/*
* Shrink the table.
*/
Link **table = static_cast<Link **>(
realloc(m_table, max * sizeof(*m_table)));
if (table != 0)
m_table = table;
/*
* Must always update m_max.
*/
m_max = max;
}
void unlink(Link *link)
{
/* Acquire readlock on global structure */
KnMutex::KnLock local_writelock(m_global_rwlock);
size_t code = link->m_code;
size_t pos = code & (m_max - 1);
/*
* Keep track of the previous link.
*/
Link *prev = 0;
for (Link *curr = m_table[pos]; curr != 0; curr = curr->m_next)
{
if (curr == link)
{
--m_size;
/*
* Remove the link.
*/
if (prev != 0)
{
prev->m_next = curr->m_next;
}
else
{
m_table[pos] = curr->m_next;
}
/*
* Delete the link.
*/
delete curr;
curr = 0;
break;
}
prev = curr;
}
}
Link **m_table;
mutable KnMutex m_global_rwlock;
size_t m_max;
size_t m_size;
};
template<typename Key, typename Value>
class SimpleSyncMapIterator : public SimpleIterator<
typename SimpleSyncMap<Key, Value>::Elem>
{
public:
/*
* Short-hand notation for SimpleSyncMap classes.
*/
typedef SimpleSyncMap<Key, Value> Map;
typedef typename SimpleSyncMap<Key, Value>::Elem Elem;
typedef typename SimpleSyncMap<Key, Value>::Link Link;
SimpleSyncMapIterator(Map &map) :
m_map(map),
m_curr(0),
m_prev(0),
m_pos(0)
{
/*
* Find the first valid chain.
*/
for (; m_pos < m_map.m_max; ++m_pos)
{
if ((m_curr = m_map.m_table[m_pos]) != 0)
break;
}
}
virtual ~SimpleSyncMapIterator()
{
}
virtual bool hasNext()
{
return m_curr != 0;
}
virtual Elem &next()
{
m_prev = m_curr;
m_curr = m_curr->m_next;
/*
* Find the next valid chain.
*/
if (m_curr == 0)
{
for (++m_pos; m_pos < m_map.m_max; ++m_pos)
{
if ((m_curr = m_map.m_table[m_pos]) != 0)
break;
}
}
return m_prev->m_elem;
}
virtual void remove()
{
m_map.unlink(m_prev);
m_prev = 0;
}
private:
// Not implemented
SimpleSyncMapIterator();
SimpleSyncMapIterator(const SimpleSyncMapIterator &);
SimpleSyncMapIterator &operator=(const SimpleSyncMapIterator &);
Map &m_map;
Link *m_curr;
Link *m_prev;
size_t m_pos;
};
#endif /* SimpleSyncMap_H */
--- NEW FILE: simplesyncvector.h ---
#ifndef SIMPLESYNCVECTOR_H
#define SIMPLESYNCVECTOR_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/kntypes.h"
#include "knutil/knlog.h"
#include "knutil/knmutex.h"
#include "knutil/simpleiterator.h"
#include "knutil/simpletraits.h"
#ifdef WIN32
#pragma warning ( disable : 4710 ) // Not inlined
#endif
template<typename Elem>
class SimpleSyncVector
{
public:
SimpleSyncVector() :
m_pelem(m_elem),
m_max(m_elem.size()),
m_size(0)
{
}
SimpleSyncVector(const SimpleSyncVector &vec) :
m_pelem(m_elem),
m_max(m_elem.size()),
m_size(0)
{
// synchronize the parameter SimpleSyncVector
KnMutex::KnLock lock(vec.m_lock);
copy(vec);
}
~SimpleSyncVector()
{
// clear is already synchronized throght remove(), therefore no need for mutex
clear();
}
SimpleSyncVector &operator=(const SimpleSyncVector &vec)
{
KnMutex::KnLock lock(vec.m_lock);
if (this != &vec)
{
clear();
copy(vec);
}
return *this;
}
const Elem &operator[](size_t pos) const
{
KnMutex::KnLock lock(m_lock);
KN_ASSERT(pos < m_size);
return m_pelem[pos];
}
Elem &operator[](size_t pos)
{
KnMutex::KnLock lock(m_lock);
KN_ASSERT(pos < m_size);
return m_pelem[pos];
}
bool append(const Elem &elem)
{
KnMutex::KnLock lock(m_lock);
return store(m_size, &elem, 1);
}
bool append(const Elem *pelem, size_t nelems)
{
KnMutex::KnLock lock(m_lock);
return store(m_size, pelem, nelems);
}
void clear()
{
/*
* Run destructors, and dispose of heap allocation.
*/
// remove is already synchronized, no need for mutex
remove(0, m_size, true);
}
bool contains(const Elem &elem) const
{
KnMutex::KnLock lock(m_lock);
for (Elem *p = m_pelem, *q = m_pelem + m_size; p != q; ++p)
{
if (SimpleCompareTraits<Elem>::equals(*p, elem))
return true;
}
return false;
}
bool empty() const
{
KnMutex::KnLock lock(m_lock);
return m_size == 0;
}
bool insert(size_t pos, const Elem &elem)
{
KnMutex::KnLock lock(m_lock);
KN_ASSERT(pos <= m_size);
return store(pos, &elem, 1);
}
bool insert(size_t pos, const Elem *pelem, size_t nelems)
{
KnMutex::KnLock lock(m_lock);
KN_ASSERT(pos <= m_size);
return store(pos, pelem, nelems);
}
bool pop()
{
KnMutex::KnLock lock(m_lock);
if (m_size == 0)
{
return false;
}
else
{
// replaced the remove(m_size - 1) call with the actual code to avoid locking twice
size_t pos = m_size - 1;
size_t nelems = 1;
KN_ASSERT(pos + nelems <= m_size);
/*
* Utilize traits-based implementation.
*/
Memory::remove(m_pelem, m_size, pos, nelems);
m_size -= nelems;
}
return true;
}
bool pop(Elem &elem)
{
KnMutex::KnLock lock(m_lock);
// this does in fact top(elem) && pop(), but it had been expanded to avoid locking twice
// this replaces the top(elem) call
if (m_size == 0)
{
return false;
}
else
{
elem = m_pelem[m_size - 1];
}
// replaced the pop() call, in fact remove(m_size - 1) call since m_size != 0
size_t pos = m_size - 1;
size_t nelems = 1;
KN_ASSERT(pos + nelems <= m_size);
/*
* Utilize traits-based implementation.
*/
Memory::remove(m_pelem, m_size, pos, nelems);
m_size -= nelems;
return true;
}
bool prepend(const Elem &elem)
{
KnMutex::KnLock lock(m_lock);
return store(0, &elem, 1);
}
bool prepend(const Elem *pelem, size_t nelems)
{
KnMutex::KnLock lock(m_lock);
return store(0, pelem, nelems);
}
bool push(const Elem &elem)
{
// append() is already synchronized so no need for mutex
return append(elem);
}
void remove(size_t pos, size_t nelems=1, bool clear=false)
{
KnMutex::KnLock lock(m_lock);
KN_ASSERT(pos + nelems <= m_size);
/*
* Utilize traits-based implementation.
*/
Memory::remove(m_pelem, m_size, pos, nelems);
m_size -= nelems;
if(clear)
{
if (m_pelem != m_elem)
free(m_pelem);
/*
* Reset to original state.
*/
m_pelem = m_elem;
m_max = m_elem.size();
m_size = 0;
}
}
bool reserve(size_t max)
{
KnMutex::KnLock lock(m_lock);
if (m_max < max)
{
/*
* Utilize traits-based implementation.
*/
Elem *pelem = Memory::reserve(m_pelem, m_size, max, m_pelem != m_elem);
if (pelem != 0)
{
m_pelem = pelem;
m_max = max;
}
else
{
return false;
}
}
return true;
}
size_t size() const
{
KnMutex::KnLock lock(m_lock);
return m_size;
}
void swap(size_t m, size_t n)
{
KnMutex::KnLock lock(m_lock);
KN_ASSERT(m < m_size && n < m_size);
Elem elem = m_pelem[m];
m_pelem[m] = m_pelem[n];
m_pelem[n] = elem;
}
bool top(Elem &elem) const
{
KnMutex::KnLock lock(m_lock);
if (m_size == 0)
{
return false;
}
else
{
elem = m_pelem[m_size - 1];
}
return true;
}
bool update(const Elem &elem)
{
KnMutex::KnLock lock(m_lock);
//simulates contains(elem) || append(elem);
// contain(elem) call
for (Elem *p = m_pelem, *q = m_pelem + m_size; p != q; ++p)
{
if (SimpleCompareTraits<Elem>::equals(*p, elem))
return true;
}
// end of contain(elem)
// append(elem) means store(m_size, &elem, 1); which is expanded to store as bellow
{
// initialize the parameters for store()
size_t pos = m_size;
size_t nelems = 1;
const Elem *pelem = &elem;
/*
* Reserve extra space if the vector isn't empty.
*/
size_t max = m_size + nelems;
if (m_max < max)
{
if (m_size > 0)
max = static_cast<size_t>(max * 1.5);
/*
if (!reserve(max))
return false;
*/
if (m_max < max)
{
/*
* Utilize traits-based implementation.
*/
Elem *pelem = Memory::reserve(m_pelem, m_size, max, m_pelem != m_elem);
if (pelem != 0)
{
m_pelem = pelem;
m_max = max;
}
else
{
return false;
}
}
}
/*
* Utilize traits-based implementation.
*/
Memory::store(m_pelem, m_size, pos, pelem, nelems);
m_size += nelems;
return true;
}
}
private:
void copy(const SimpleSyncVector &vec)
{
append(vec.m_pelem, vec.m_size);
}
bool store(size_t pos, const Elem *pelem, size_t nelems)
{
/*
* Reserve extra space if the vector isn't empty.
*/
size_t max = m_size + nelems;
if (m_max < max)
{
if (m_size > 0)
max = static_cast<size_t>(max * 1.5);
/*
if (!reserve(max))
return false;
*/
if (m_max < max)
{
/*
* Utilize traits-based implementation.
*/
Elem *pelem = Memory::reserve(m_pelem, m_size, max, m_pelem != m_elem);
if (pelem != 0)
{
m_pelem = pelem;
m_max = max;
}
else
{
return false;
}
}
}
/*
* Utilize traits-based implementation.
*/
Memory::store(m_pelem, m_size, pos, pelem, nelems);
m_size += nelems;
return true;
}
typedef typename SimpleBufferTraits<Elem>::Impl Buffer;
typedef typename SimpleMemoryTraits<Elem>::Impl Memory;
enum
{
ElemSize = sizeof(Elem)
};
Buffer m_elem;
Elem *m_pelem;
size_t m_max;
size_t m_size;
mutable KnMutex m_lock;
};
template<typename Elem>
class SimpleSyncVectorIterator : public SimpleIterator<Elem>
{
public:
SimpleSyncVectorIterator(SimpleSyncVector<Elem> &vec, size_t pos=0) :
m_vec(vec),
m_pos(pos)
{
}
virtual ~SimpleSyncVectorIterator()
{
}
virtual bool hasNext()
{
return m_pos < m_vec.size();
}
virtual Elem &next()
{
return m_vec[m_pos++];
}
virtual void remove()
{
m_vec.remove(--m_pos);
}
private:
// Not implemented
SimpleSyncVectorIterator();
SimpleSyncVectorIterator(const SimpleSyncVectorIterator &);
SimpleSyncVectorIterator &operator=(const SimpleSyncVectorIterator &);
SimpleSyncVector<Elem> &m_vec;
size_t m_pos;
};
#endif /* SIMPLESYNCVECTOR_H */
--- NEW FILE: simpletraits.h ---
#ifndef SIMPLETRAITS_H
#define SIMPLETRAITS_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knhash.h"
#ifdef HAVE_STDINT_H
/* You must set the above macro in order to get the SIZE_MAX defined.
You have to set it before including stdint.
Probably better template-fu could avoid these ugly defines.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif
#include <stdint.h>
#endif
#if defined(HAVE_LIMITS_H) || defined(_WINDOWS)
/* Also need UINT_MAX for same #if below */
#include <limits.h>
#endif
#ifdef _WINDOWS
# ifndef WIN32
Error: We need to find the way to determine size_t != uint_t in this case.
# else
# ifndef SIZE_MAX
# define SIZE_MAX UINT_MAX
# endif
# endif
#endif
/*
* (C) Copyright Krzysztof Czarnecki & Ulrich Eisenecker 1998-2000.
* Permission to copy, use, modify, sell and distribute this software is
* granted provided this copyright notice appears in all copies. In case of
* modification, the modified files should carry a notice stating that
* you changed the files.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
/*
* Authors: Mat Marcus and Jesse Jones
* Copyright 2000 Adobe Systems Incorporated and others. All rights reserved.
* The original version of this source code may be found at
* http://opensource.adobe.com.
* The contents of this file are subject to the Adobe Open Source
* License Version 1.0.
*/
/*
* NOTICE:
*
* Small modifications made to reflect changes in template syntax.
*
* Some compilers (such as gcc) will complain about the call to IsPtr(...)
* for non-POD data types. This is due to section 5.2.2/7 of the standard:
*
* "When there is no parameter for a given argument, the argument is
* passed in such a way that the receiving function can obtain the
* value of the argument by invoking va_arg. The lvalue-to-rvalue,
* array-to-pointer, and function-to-pointer standard conversions are
* performed on the argument expression. After these conversions, if
* the argument does not have arithmetic, enumeration, pointer, pointer
* to member, or class type, the program is ill-formed. If the
* argument has a non-POD class type, the behavior is undefined."
*
* Since we are using IsPtr(...) solely for its signature (the function
* is never defined), our behavior is valid.
*/
#ifdef WIN32
#pragma warning ( disable : 4786 ) // Mangled name truncated to 255
#endif
namespace metactrl
{
namespace intimate
{
struct SelectThen
{
template<typename Then, typename Else>
struct Result
{
typedef Then RET;
};
};
struct SelectElse
{
template<typename Then, typename Else>
struct Result
{
typedef Else RET;
};
};
template<bool Condition>
struct Selector
{
typedef SelectThen RET;
};
template<>
struct Selector<false>
{
typedef SelectElse RET;
};
struct PointerShim
{
/*
* Since the compiler only allows at most one non-trivial
* implicit conversion, we can make use of a shim class to
* be sure that IsPtr below doesn't accept classes with
* implicit pointer conversion operators.
*/
PointerShim(const volatile void *); /* no implementation */
/*
* Ensure sizeof(PointerShim) > 1.
*/
char dummy[2];
};
/*
* These are the discriminating functions.
*/
char IsPtr(PointerShim); /* no implementation is required */
PointerShim IsPtr(...); /* no implementation is required */
} // namespace intimate
template<typename T>
struct ISPTR
{
/*
* This template meta-function takes a type T
* and returns true exactly when T is a pointer.
* One can imagine meta-functions discriminating on
* other criteria.
*/
enum
{
RET = sizeof(intimate::IsPtr(*(static_cast<T *>(0)))) == 1
};
};
template<bool Condition, typename Then, typename Else>
struct IF
{
typedef typename intimate::Selector<Condition>::RET select;
typedef typename select::template Result<Then,Else>::RET RET;
};
} // namespace metactrl
/*
* Return a pointer from a pointer (no-op).
*/
template<typename T>
struct SimplePointerFast
{
static inline const T get(const T t)
{
return t;
}
};
/*
* Return a pointer from an object.
*/
template<typename T>
struct SimplePointerSlow
{
static inline const T *get(const T &t)
{
return &t;
}
};
/*
* Extract a pointer from a type.
*/
template<typename T>
struct SimplePointerTraits
{
typedef typename metactrl::IF<
metactrl::ISPTR<T>::RET,
SimplePointerFast<T>,
SimplePointerSlow<T>
>::RET Impl;
};
/*
* Compare two objects of possibly differing types for equality.
*/
template<typename T, typename U=T>
struct SimpleCompareTraits
{
typedef typename SimplePointerTraits<T>::Impl TPtr;
typedef typename SimplePointerTraits<U>::Impl UPtr;
static inline bool equals(const T &t, const U &u)
{
return *(TPtr::get(t)) == *(UPtr::get(u));
}
};
/*
* Specialize comparison of C strings.
*/
template<>
struct SimpleCompareTraits<const char *, const char *>
{
static inline bool equals(const char *const &t, const char *const &u)
{
return strcmp(t, u) == 0;
}
};
template<>
struct SimpleCompareTraits<const char *, char *>
{
static inline bool equals(const char *const &t, char *const &u)
{
return strcmp(t, u) == 0;
}
};
template<>
struct SimpleCompareTraits<char *, const char *>
{
static inline bool equals(char *const &t, const char *const &u)
{
return strcmp(t, u) == 0;
}
};
template<>
struct SimpleCompareTraits<char *, char *>
{
static inline bool equals(char *const &t, char *const &u)
{
return strcmp(t, u) == 0;
}
};
/*
* Specialize comparison of raw pointers.
*/
template<>
struct SimpleCompareTraits<const void *, const void *>
{
static inline bool equals(const void *const &t, const void *const &u)
{
return t == u;
}
};
template<>
struct SimpleCompareTraits<const void *, void *>
{
static inline bool equals(const void *const &t, void *const &u)
{
return t == u;
}
};
template<>
struct SimpleCompareTraits<void *, const void *>
{
static inline bool equals(void *const &t, const void *const &u)
{
return t == u;
}
};
template<>
struct SimpleCompareTraits<void *, void *>
{
static inline bool equals(void *const &t, void *const &u)
{
return t == u;
}
};
/*
* Extract a hash value from a type.
*/
template<typename T>
struct SimpleHashTraits
{
typedef typename SimplePointerTraits<T>::Impl Ptr;
static inline size_t get(const T &t)
{
return (Ptr::get(t))->hashCode();
}
};
/*
* Specialize hashing of integer types. Unfortunately,
* this really needs something like the Boost <is_same.hpp> component.
*/
template <>
struct SimpleHashTraits<unsigned int>
{
static inline size_t get(const unsigned int &t)
{
return static_cast<size_t>(t);
}
};
template <>
struct SimpleHashTraits<int>
{
static inline size_t get(const int &t)
{
return static_cast<size_t>(t);
}
};
// Probably should do this with MPL-ish template metaprogramming,
// (or just bite the bullet and bring Boost's traits classes in),
// but this is at least reasonably correct:
#if SIZE_MAX > UINT_MAX
template <>
struct SimpleHashTraits<size_t>
{
static inline size_t get(const size_t &t)
{
return t;
}
};
#endif
/*
* Specialize hashing of C strings.
*/
template<>
struct SimpleHashTraits<const char *>
{
static inline size_t get(const char *const &t)
{
return hash32(t, strlen(t), 0);
}
};
template<>
struct SimpleHashTraits<char *>
{
static inline size_t get(char *const &t)
{
return hash32(t, strlen(t), 0);
}
};
/*
* Specialize hashing of raw pointers.
*/
template<>
struct SimpleHashTraits<const void *>
{
static inline size_t get(const void *const &t)
{
return reinterpret_cast<size_t>(t) >> 7;
}
};
template<>
struct SimpleHashTraits<void *>
{
static inline size_t get(void *const &t)
{
return reinterpret_cast<size_t>(t) >> 7;
}
};
#endif /* SIMPLETRAITS_H */
--- NEW FILE: simplevector.h ---
#ifndef SIMPLEVECTOR_H
#define SIMPLEVECTOR_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include <new>
#include "knutil/kntypes.h"
#include "knutil/knlog.h"
#include "knutil/simpleiterator.h"
#include "knutil/simpletraits.h"
#ifdef WIN32
#pragma warning ( disable : 4710 ) // Not inlined
#endif
/*
* Buffer for unrestricted alignment.
*/
template<typename Elem>
union SimpleBufferFast
{
public:
operator const Elem *() const
{
return reinterpret_cast<const Elem *>(m_buffer);
}
operator Elem *()
{
return reinterpret_cast<Elem *>(m_buffer);
}
size_t size() const
{
return BufferSize;
}
private:
enum
{
BufferSize = 32
};
char m_buffer[BufferSize * sizeof(Elem)];
};
/*
* Buffer for conservative alignment.
*/
template<typename Elem>
union SimpleBufferSlow
{
public:
operator const Elem *() const
{
return reinterpret_cast<const Elem *>(m_buffer);
}
operator Elem *()
{
return reinterpret_cast<Elem *>(m_buffer);
}
size_t size() const
{
return BufferSize;
}
private:
enum
{
BufferSize = 10
};
long double m_align;
char m_buffer[BufferSize * sizeof(Elem)];
};
/*
* Specialize for characters.
*/
template<typename Elem>
struct SimpleBufferTraits
{
typedef typename metactrl::IF<
sizeof(Elem) == 1,
SimpleBufferFast<Elem>,
SimpleBufferSlow<Elem>
>::RET Impl;
};
/*
* Raw memory implementation.
*/
template<typename Elem>
struct SimpleMemoryFast
{
static void remove(Elem *oldPtr, size_t oldSize,
size_t pos, size_t nelems)
{
/*
* Left-shift elements to cover hole created by removal. Don't bother
* moving elements around if the resultant vector is empty, or if the
* removed elements came from the back.
*/
size_t range = pos + nelems;
if (nelems > 0 && range < oldSize)
{
memmove(&oldPtr[pos], &oldPtr[range], (oldSize - range) * ElemSize);
}
}
static Elem *reserve(Elem *oldPtr, size_t oldSize,
size_t newSize, bool freePtr)
{
/*
* Allocate a bigger vector. Use realloc() if the existing memory
* came from the heap; otherwise, manually copy elements.
*/
Elem *newPtr = 0;
if (oldPtr != 0 && freePtr)
{
newPtr = static_cast<Elem *>(realloc(oldPtr, newSize * ElemSize));
}
else
{
newPtr = static_cast<Elem *>(malloc(newSize * ElemSize));
if (newPtr != 0)
{
memcpy(newPtr, oldPtr, oldSize * ElemSize);
}
}
return newPtr;
}
static void store(Elem *oldPtr, size_t oldSize,
size_t pos, const Elem *newPtr, size_t nelems)
{
/*
* Right-shift all elements [pos, oldSize).
*/
size_t range = pos + nelems;
if (nelems > 0)
{
if (pos < oldSize)
{
memmove(&oldPtr[range], &oldPtr[pos], (oldSize - pos) * ElemSize);
}
memcpy(&oldPtr[pos], newPtr, nelems * ElemSize);
}
}
enum
{
ElemSize = sizeof(Elem)
};
};
/*
* Object implementation.
*/
template<typename Elem>
struct SimpleMemorySlow
{
static void remove(Elem *oldPtr, size_t oldSize,
size_t pos, size_t nelems)
{
/*
* Left-shift elements to cover hole created by removal. Don't bother
* moving elements around if the resultant vector is empty, or if the
* removed elements came from the back.
*/
if (nelems > 0)
{
size_t i = pos;
for (; i < oldSize - nelems; ++i)
{
oldPtr[i] = oldPtr[i + nelems];
}
for (; i < oldSize; ++i)
{
oldPtr[i].~Elem();
}
}
}
static Elem *reserve(Elem *oldPtr, size_t oldSize,
size_t newSize, bool freePtr)
{
/*
* Allocate a bigger vector. It is not safe to use realloc().
*/
Elem *newPtr = static_cast<Elem *>(malloc(newSize * ElemSize));
if (newPtr != 0)
{
for (size_t i = 0; i < oldSize; ++i)
{
new (&newPtr[i]) Elem(oldPtr[i]);
oldPtr[i].~Elem();
}
if (freePtr)
free(oldPtr);
}
return newPtr;
}
static void store(Elem *oldPtr, size_t oldSize,
size_t pos, const Elem *newPtr, size_t nelems)
{
/*
* Right-shift all elements [pos, oldSize).
*/
size_t range = pos + nelems;
if (nelems > 0)
{
size_t i;
for (i = (oldSize + nelems) - 1; i >= range; --i)
{
if (i < oldSize)
{
oldPtr[i] = oldPtr[i - nelems];
}
else
{
new (&oldPtr[i]) Elem(oldPtr[i - nelems]);
}
}
for (i = pos; i < range; ++i)
{
if (i < oldSize)
{
oldPtr[i] = newPtr[i - pos];
}
else
{
new (&oldPtr[i]) Elem(newPtr[i - pos]);
}
}
}
}
enum
{
ElemSize = sizeof(Elem)
};
};
/*
* Specialize for pointers.
*/
template<typename Elem>
struct SimpleMemoryTraits
{
typedef typename metactrl::IF<
metactrl::ISPTR<Elem>::RET,
SimpleMemoryFast<Elem>,
SimpleMemorySlow<Elem>
>::RET Impl;
};
/*
* Specialize built-in types.
*/
template<>
struct SimpleMemoryTraits<signed char>
{
typedef SimpleMemoryFast<signed char> Impl;
};
template<>
struct SimpleMemoryTraits<signed short>
{
typedef SimpleMemoryFast<signed short> Impl;
};
template<>
struct SimpleMemoryTraits<signed int>
{
typedef SimpleMemoryFast<signed int> Impl;
};
template<>
struct SimpleMemoryTraits<signed long>
{
typedef SimpleMemoryFast<signed long> Impl;
};
#ifdef WIN32
template<>
struct SimpleMemoryTraits<signed __int64>
{
typedef SimpleMemoryFast<signed __int64> Impl;
};
#else
template<>
struct SimpleMemoryTraits<signed long long>
{
typedef SimpleMemoryFast<signed long long> Impl;
};
#endif
template<>
struct SimpleMemoryTraits<unsigned char>
{
typedef SimpleMemoryFast<unsigned char> Impl;
};
template<>
struct SimpleMemoryTraits<unsigned short>
{
typedef SimpleMemoryFast<unsigned short> Impl;
};
template<>
struct SimpleMemoryTraits<unsigned int>
{
typedef SimpleMemoryFast<unsigned int> Impl;
};
template<>
struct SimpleMemoryTraits<unsigned long>
{
typedef SimpleMemoryFast<unsigned long> Impl;
};
#ifdef WIN32
template<>
struct SimpleMemoryTraits<unsigned __int64>
{
typedef SimpleMemoryFast<unsigned __int64> Impl;
};
#else
template<>
struct SimpleMemoryTraits<unsigned long long>
{
typedef SimpleMemoryFast<unsigned long long> Impl;
};
#endif
template<>
struct SimpleMemoryTraits<bool>
{
typedef SimpleMemoryFast<bool> Impl;
};
template<>
struct SimpleMemoryTraits<char>
{
typedef SimpleMemoryFast<char> Impl;
};
template<>
struct SimpleMemoryTraits<float>
{
typedef SimpleMemoryFast<float> Impl;
};
template<>
struct SimpleMemoryTraits<double>
{
typedef SimpleMemoryFast<double> Impl;
};
template<>
struct SimpleMemoryTraits<long double>
{
typedef SimpleMemoryFast<long double> Impl;
};
template<typename Elem>
class SimpleVector
{
public:
SimpleVector() :
m_pelem(m_elem),
m_max(m_elem.size()),
m_size(0)
{
}
SimpleVector(const SimpleVector &vec) :
m_pelem(m_elem),
m_max(m_elem.size()),
m_size(0)
{
copy(vec);
}
~SimpleVector()
{
clear();
}
SimpleVector &operator=(const SimpleVector &vec)
{
if (this != &vec)
{
clear();
copy(vec);
}
return *this;
}
const Elem &operator[](size_t pos) const
{
KN_ASSERT(pos < m_size);
return m_pelem[pos];
}
Elem &operator[](size_t pos)
{
KN_ASSERT(pos < m_size);
return m_pelem[pos];
}
bool append(const Elem elem)
{
return store(m_size, &elem, 1);
}
bool append(const Elem *pelem, size_t nelems)
{
return store(m_size, pelem, nelems);
}
void clear()
{
/*
* Run destructors, and dispose of heap allocation.
*/
remove(0, m_size);
if (m_pelem != m_elem)
free(m_pelem);
/*
* Reset to original state.
*/
m_pelem = m_elem;
m_max = m_elem.size();
m_size = 0;
}
bool contains(const Elem &elem) const
{
for (Elem *p = m_pelem, *q = m_pelem + m_size; p != q; ++p)
{
if (SimpleCompareTraits<Elem>::equals(*p, elem))
return true;
}
return false;
}
bool empty() const
{
return m_size == 0;
}
bool insert(size_t pos, const Elem elem)
{
KN_ASSERT(pos <= m_size);
return store(pos, &elem, 1);
}
bool insert(size_t pos, const Elem *pelem, size_t nelems)
{
KN_ASSERT(pos <= m_size);
return store(pos, pelem, nelems);
}
bool pop()
{
if (m_size == 0)
{
return false;
}
else
{
remove(m_size - 1);
}
return true;
}
bool pop(Elem &elem)
{
return top(elem) && pop();
}
bool prepend(const Elem elem)
{
return store(0, &elem, 1);
}
bool prepend(const Elem *pelem, size_t nelems)
{
return store(0, pelem, nelems);
}
bool push(const Elem elem)
{
return append(elem);
}
void remove(size_t pos, size_t nelems=1)
{
KN_ASSERT(pos + nelems <= m_size);
/*
* Utilize traits-based implementation.
*/
Memory::remove(m_pelem, m_size, pos, nelems);
m_size -= nelems;
}
bool reserve(size_t max)
{
if (m_max < max)
{
/*
* Utilize traits-based implementation.
*/
Elem *pelem = Memory::reserve(m_pelem, m_size, max, m_pelem != m_elem);
if (pelem != 0)
{
m_pelem = pelem;
m_max = max;
}
else
{
return false;
}
}
return true;
}
size_t size() const
{
return m_size;
}
void swap(size_t m, size_t n)
{
KN_ASSERT(m < m_size && n < m_size);
Elem elem = m_pelem[m];
m_pelem[m] = m_pelem[n];
m_pelem[n] = elem;
}
bool top(Elem &elem) const
{
if (m_size == 0)
{
return false;
}
else
{
elem = m_pelem[m_size - 1];
}
return true;
}
bool update(const Elem &elem)
{
return contains(elem) || append(elem);
}
private:
void copy(const SimpleVector &vec)
{
append(vec.m_pelem, vec.m_size);
}
bool store(size_t pos, const Elem *pelem, size_t nelems)
{
/*
* Reserve extra space if the vector isn't empty.
*/
size_t max = m_size + nelems;
if (m_max < max)
{
if (m_size > 0)
max = static_cast<size_t>(max * 1.5);
if (!reserve(max))
return false;
}
/*
* Utilize traits-based implementation.
*/
Memory::store(m_pelem, m_size, pos, pelem, nelems);
m_size += nelems;
return true;
}
typedef typename SimpleBufferTraits<Elem>::Impl Buffer;
typedef typename SimpleMemoryTraits<Elem>::Impl Memory;
enum
{
ElemSize = sizeof(Elem)
};
Buffer m_elem;
Elem *m_pelem;
size_t m_max;
size_t m_size;
};
template<typename Elem>
class SimpleVectorIterator : public SimpleIterator<Elem>
{
public:
SimpleVectorIterator(SimpleVector<Elem> &vec, size_t pos=0) :
m_vec(vec),
m_pos(pos)
{
}
virtual ~SimpleVectorIterator()
{
}
virtual bool hasNext()
{
return m_pos < m_vec.size();
}
virtual Elem &next()
{
return m_vec[m_pos++];
}
virtual void remove()
{
m_vec.remove(--m_pos);
}
private:
// Not implemented
SimpleVectorIterator();
SimpleVectorIterator(const SimpleVectorIterator &);
SimpleVectorIterator &operator=(const SimpleVectorIterator &);
SimpleVector<Elem> &m_vec;
size_t m_pos;
};
#endif /* SIMPLEVECTOR_H */
--- NEW FILE: uuidgenerator.h ---
#ifndef UUIDGENERATOR_H
#define UUIDGENERATOR_H
/**
* Copyright (c) 2001 KnowNow, Inc. All rights reserved.
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knexportlibraryknutil.h"
#include "knutil/kntypes.h"
#include "knutil/knstring.h"
class EXPORT_LIBRARY_KNUTIL UuidGenerator
{
public:
/*
* Generate the next uuid and append it the given string.
*/
static bool next(KnString &kns);
private:
// Not implemented
UuidGenerator();
~UuidGenerator();
UuidGenerator(const UuidGenerator &);
UuidGenerator &operator=(const UuidGenerator &);
};
#endif /* UUIDGENERATOR_H */
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
aolserver-commits mailing list
aolserve...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/aolserver-commits