This commit is contained in:
Ivan
2022-04-05 11:42:28 +03:00
commit 6dc0eb0fcf
5565 changed files with 1200500 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Hauke Strasdat, Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/utils/format_string.h>
#include <iostream>
#ifdef __GNUC__
# define PANGO_FUNCTION __PRETTY_FUNCTION__
#elif (_MSC_VER >= 1310)
# define PANGO_FUNCTION __FUNCTION__
#else
# define PANGO_FUNCTION "unknown"
#endif
namespace pangolin {
template <typename... Args> PANGO_HOST_DEVICE
void abort(const char* function, const char* file, int line, Args&&... args)
{
std::printf("pangolin::abort() in function '%s', file '%s', line %d.\n", function, file, line);
#ifndef __CUDACC__
std::cout << FormatString(std::forward<Args>(args)...) << std::endl;
std::abort();
#endif
}
}
// Always check, even in debug
#define PANGO_ENSURE(expr, ...) ((expr) ? ((void)0) : pangolin::abort(PANGO_FUNCTION, __FILE__, __LINE__, ##__VA_ARGS__))
// May be disabled for optimisation
#define PANGO_ASSERT(expr, ...) ((expr) ? ((void)0) : pangolin::abort(PANGO_FUNCTION, __FILE__, __LINE__, ##__VA_ARGS__))

View File

@@ -0,0 +1,42 @@
#pragma once
#include <pangolin/platform.h>
#ifdef HAVE_EIGEN
# include <Eigen/Core>
#endif
namespace pangolin
{
// Scalar / Vector agnostic static_cast-like thing
//
// e.g. Promote float to double:
// ComponentCast<double,float>::cast(0.14f);
//
// e.g. Promote Eigen::Vector2f to Eigen::Vector2d:
// ComponentCast<Eigen::Vector2d,Eigen::Vector2f>::cast(Eigen::Vector2f(0.1,0.2);
template <typename To, typename From>
struct ComponentCast
{
PANGO_HOST_DEVICE
static To cast(const From& val)
{
return static_cast<To>(val);
}
};
#ifdef HAVE_EIGEN
template <typename To, typename FromDerived>
struct ComponentCast<To, Eigen::MatrixBase<FromDerived> >
{
PANGO_HOST_DEVICE
static To cast(const Eigen::MatrixBase<FromDerived>& val)
{
return val.template cast<typename To::Scalar>();
}
};
#endif
}

View File

@@ -0,0 +1,74 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <string>
namespace pangolin
{
enum ImageFileType
{
ImageFileTypePpm,
ImageFileTypeTga,
ImageFileTypePng,
ImageFileTypeJpg,
ImageFileTypeTiff,
ImageFileTypeGif,
ImageFileTypeExr,
ImageFileTypePango,
ImageFileTypePvn,
ImageFileTypeZstd,
ImageFileTypeLz4,
ImageFileTypeP12b,
ImageFileTypePly,
ImageFileTypeObj,
ImageFileTypeUnknown
};
PANGOLIN_EXPORT
std::string ImageFileTypeToName(ImageFileType);
PANGOLIN_EXPORT
ImageFileType NameToImageFileType(const std::string&);
PANGOLIN_EXPORT
std::string FileLowercaseExtention(const std::string& filename);
PANGOLIN_EXPORT
ImageFileType FileTypeMagic(const unsigned char data[], size_t bytes);
PANGOLIN_EXPORT
ImageFileType FileTypeExtension(const std::string& ext);
PANGOLIN_EXPORT
ImageFileType FileType(const std::string& filename);
}

View File

@@ -0,0 +1,151 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <string>
#include <vector>
#include <algorithm>
namespace pangolin
{
PANGOLIN_EXPORT
std::vector<std::string>& Split(const std::string& s, char delim, std::vector<std::string>& elements);
PANGOLIN_EXPORT
std::vector<std::string> Split(const std::string &s, char delim);
PANGOLIN_EXPORT
std::vector<std::string> Expand(const std::string &s, char open='[', char close=']', char delim=',');
PANGOLIN_EXPORT
std::string SanitizePath(const std::string& path);
PANGOLIN_EXPORT
std::string PathParent(const std::string& path, int levels = 1);
PANGOLIN_EXPORT
bool FileExists(const std::string& filename);
PANGOLIN_EXPORT
std::string FindPath(const std::string& child_path, const std::string& signature_path);
PANGOLIN_EXPORT
std::string PathExpand(const std::string& sPath);
PANGOLIN_EXPORT
bool MatchesWildcard(const std::string& str, const std::string& wildcard);
// Fill 'file_vec' with the files that match the glob-like 'wildcard_file_path'
// ? can be used to match any single charector
// * can be used to match any sequence of charectors in a directory
// ** can be used to match any directories across any number of levels
// e.g. FilesMatchingWildcard("~/*/code/*.h", vec);
// e.g. FilesMatchingWildcard("~/**/*.png", vec);
PANGOLIN_EXPORT
bool FilesMatchingWildcard(const std::string& wildcard_file_path, std::vector<std::string>& file_vec);
PANGOLIN_EXPORT
std::string MakeUniqueFilename(const std::string& filename);
PANGOLIN_EXPORT
bool IsPipe(const std::string& file);
PANGOLIN_EXPORT
bool IsPipe(int fd);
PANGOLIN_EXPORT
int WritablePipeFileDescriptor(const std::string& file);
/**
* Open the file for reading. Note that it is opened with O_NONBLOCK. The pipe
* open is done in two stages so that the producer knows a reader is waiting
* (but not blocked). The reader then checks PipeHasDataToRead() until it
* returns true. The file can then be opened. Note that the file descriptor
* should be closed after the read stream has been created so that the write
* side of the pipe does not get signaled.
*/
PANGOLIN_EXPORT
int ReadablePipeFileDescriptor(const std::string& file);
PANGOLIN_EXPORT
bool PipeHasDataToRead(int fd);
PANGOLIN_EXPORT
void FlushPipe(const std::string& file);
// TODO: Tidy these inlines up / move them
inline bool StartsWith(const std::string& str, const std::string& prefix)
{
return !str.compare(0, prefix.size(), prefix);
}
inline bool EndsWith(const std::string& str, const std::string& prefix)
{
return !str.compare(str.size() - prefix.size(), prefix.size(), prefix);
}
inline std::string Trim(const std::string& str, const std::string& delimiters = " \f\n\r\t\v" )
{
const size_t f = str.find_first_not_of( delimiters );
return f == std::string::npos ?
"" :
str.substr( f, str.find_last_not_of( delimiters ) + 1 );
}
inline void ToUpper( std::string& str )
{
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
}
inline void ToLower( std::string& str )
{
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
}
inline std::string ToUpperCopy( const std::string& str )
{
std::string out;
out.resize(str.size());
std::transform(str.begin(), str.end(), out.begin(), ::toupper);
return out;
}
inline std::string ToLowerCopy( const std::string& str )
{
std::string out;
out.resize(str.size());
std::transform(str.begin(), str.end(), out.begin(), ::tolower);
return out;
}
}

View File

@@ -0,0 +1,153 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <condition_variable>
#include <list>
#include <mutex>
#include <mutex>
#include <thread>
namespace pangolin
{
template<typename BufPType>
class FixSizeBuffersQueue
{
public:
FixSizeBuffersQueue() {}
~FixSizeBuffersQueue() {
}
BufPType getNewest() {
std::lock_guard<std::mutex> vlock(vMtx);
std::lock_guard<std::mutex> elock(eMtx);
if(validBuffers.size() == 0) {
// Empty queue.
return 0;
} else {
// Requeue all but newest buffers.
while(validBuffers.size() > 1) {
emptyBuffers.push_back(std::move(validBuffers.front()));
validBuffers.pop_front();
}
// Return newest buffer.
BufPType bp = std::move(validBuffers.front());
validBuffers.pop_front();
return bp;
}
}
BufPType getNext() {
std::lock_guard<std::mutex> vlock(vMtx);
if(validBuffers.size() == 0) {
// Empty queue.
return 0;
} else {
// Return oldest buffer.
BufPType bp = std::move(validBuffers.front());
validBuffers.pop_front();
return bp;
}
}
BufPType getFreeBuffer() {
std::lock_guard<std::mutex> vlock(vMtx);
std::lock_guard<std::mutex> elock(eMtx);
if(emptyBuffers.size() > 0) {
// Simply get a free buffer from the free buffers list.
BufPType bp = std::move(emptyBuffers.front());
emptyBuffers.pop_front();
return bp;
} else {
if(validBuffers.size() == 0) {
// Queue not yet initialized.
throw std::runtime_error("Queue not yet initialised.");
} else {
std::cerr << "Out of free buffers." << std::endl;
// No free buffers return oldest among the valid buffers.
BufPType bp = std::move(validBuffers.front());
validBuffers.pop_front();
return bp;
}
}
}
void addValidBuffer(BufPType bp) {
// Add buffer to valid buffers queue.
std::lock_guard<std::mutex> vlock(vMtx);
validBuffers.push_back(std::move(bp));
}
void returnOrAddUsedBuffer(BufPType bp) {
// Add buffer back to empty buffers queue.
std::lock_guard<std::mutex> elock(eMtx);
emptyBuffers.push_back(std::move(bp));
}
size_t AvailableFrames() const {
std::lock_guard<std::mutex> vlock(vMtx);
return validBuffers.size();
}
size_t EmptyBuffers() const {
std::lock_guard<std::mutex> elock(eMtx);
return emptyBuffers.size();
}
bool DropNFrames(size_t n) {
std::lock_guard<std::mutex> vlock(vMtx);
if(validBuffers.size() < n) {
return false;
} else {
std::lock_guard<std::mutex> elock(eMtx);
// Requeue all but newest buffers.
for(unsigned int i=0; i<n; ++i) {
emptyBuffers.push_back(std::move(validBuffers.front()));
validBuffers.pop_front();
}
return true;
}
}
// unsigned int BufferSizeBytes(){
// return bufferSizeBytes;
// }
private:
std::list<BufPType> validBuffers;
std::list<BufPType> emptyBuffers;
mutable std::mutex vMtx;
mutable std::mutex eMtx;
// unsigned int maxNumBuffers;
// unsigned int bufferSizeBytes;
};
}

View File

@@ -0,0 +1,87 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Hauke Strasdat, Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <sstream>
namespace pangolin {
namespace details {
// Following: http://stackoverflow.com/a/22759544
template <typename T>
class IsStreamable {
private:
template <typename TT>
static auto test(int) -> decltype( (std::declval<std::stringstream&>() << std::declval<TT>(), std::true_type()) );
template <typename>
static auto test(...) -> std::false_type;
public:
static const bool value = decltype(test<T>(0))::value;
};
inline void FormatStream(std::stringstream& stream, const char* text)
{
stream << text;
}
// Following: http://en.cppreference.com/w/cpp/language/parameter_pack
template <typename T, typename... Args>
void FormatStream(std::stringstream& stream, const char* text, T arg, Args... args)
{
static_assert(IsStreamable<T>::value,
"One of the args has not an ostream overload!");
for (; *text != '\0'; ++text) {
if (*text == '%') {
stream << arg;
FormatStream(stream, text + 1, args...);
return;
}
stream << *text;
}
stream << "\nFormat-Warning: There are " << sizeof...(Args) + 1
<< " args unused.";
}
} // namespace details
template <typename... Args>
std::string FormatString(const char* text, Args... args)
{
std::stringstream stream;
details::FormatStream(stream, text, args...);
return stream.str();
}
inline std::string FormatString()
{
return std::string();
}
}

View File

@@ -0,0 +1,44 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
// TODO: Something a bit more useful here, probably using format_string.h
#pragma once
#ifndef _ANDROID_
# include <cstdio>
# define pango_print_debug(...) printf(__VA_ARGS__)
# define pango_print_info(...) printf(__VA_ARGS__)
# define pango_print_error(...) fprintf(stderr, __VA_ARGS__)
# define pango_print_warn(...) fprintf(stderr, __VA_ARGS__)
#else
# include <android/log.h>
# define pango_print_debug(...) __android_log_print(ANDROID_LOG_DEBUG, "pango", __VA_ARGS__ );
# define pango_print_info(...) __android_log_print(ANDROID_LOG_INFO, "pango", __VA_ARGS__ );
# define pango_print_error(...) __android_log_print(ANDROID_LOG_ERROR, "pango", __VA_ARGS__ );
# define pango_print_warn(...) __android_log_print(ANDROID_LOG_ERROR, "pango", __VA_ARGS__ );
#endif

View File

@@ -0,0 +1,55 @@
#pragma once
#include <streambuf>
#include <vector>
namespace pangolin {
// A simple streambuf wrapper around std::vector for memory buffer use
struct memstreambuf : public std::streambuf
{
public:
memstreambuf(size_t initial_buffer_size)
{
buffer.reserve(initial_buffer_size);
}
// Avoiding use of std::streambuf's move constructor, since it is missing for old GCC
memstreambuf(memstreambuf&& o)
: buffer(std::move(o.buffer))
{
pubseekpos(o.pubseekoff(0, std::ios_base::cur));
}
size_t size() const
{
return buffer.size();
}
const unsigned char* data() const
{
return buffer.data();
}
void clear()
{
buffer.clear();
}
std::vector<unsigned char> buffer;
protected:
std::streamsize xsputn(const char_type* __s, std::streamsize __n) override
{
buffer.insert(buffer.end(), __s, __s + __n);
return __n;
}
int_type overflow(int_type __c) override
{
buffer.push_back( static_cast<unsigned char>(__c) );
return __c;
}
};
}

View File

@@ -0,0 +1,80 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/utils/type_convert.h>
#include <string>
#include <vector>
namespace pangolin
{
class PANGOLIN_EXPORT Params
{
public:
typedef std::vector<std::pair<std::string,std::string>> ParamMap;
Params()
{
}
Params(std::initializer_list<std::pair<std::string,std::string>> l)
: params(l)
{
}
bool Contains(const std::string& key) const
{
for(ParamMap::const_iterator it = params.begin(); it!=params.end(); ++it) {
if(it->first == key) return true;
}
return false;
}
template<typename T>
T Get(const std::string& key, T default_val) const
{
// Return last value passed to the key.
for(ParamMap::const_reverse_iterator it = params.rbegin(); it!=params.rend(); ++it) {
if(it->first == key) return Convert<T, std::string>::Do(it->second);
}
return default_val;
}
template<typename T>
void Set(const std::string& key, const T& val)
{
params.push_back(std::pair<std::string,std::string>(key,Convert<std::string,T>::Do(val)));
}
ParamMap params;
};
}

View File

@@ -0,0 +1,108 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PANGOLIN_PARSE_H
#define PANGOLIN_PARSE_H
#include <string>
#include <cctype>
namespace pangolin
{
const unsigned int parse_max_token_size = 1024;
inline void ConsumeWhitespace(std::istream& is)
{
while(is.good() && std::isspace(is.peek()) ) {
is.get();
}
}
inline bool ConsumeToNewline(std::istream& is)
{
while(is.good()) {
if(is.get() == '\n') {
return true;
}
}
return false;
}
template<size_t buffer_size> inline
size_t ReadToken(std::istream& is, char buffer[buffer_size])
{
size_t r = 0;
while(is.good() && r < buffer_size-1) {
int c = is.peek();
if( std::isgraph(c) ) {
buffer[r++] = (char)is.get();
}else{
break;
}
}
buffer[r] = '\0';
return r;
}
inline std::string ReadToken(std::istream &is)
{
char str_token[parse_max_token_size];
ReadToken<parse_max_token_size>(is, str_token);
return std::string(str_token);
}
template<size_t buffer_size> inline
size_t ConsumeWhitespaceReadToken(std::istream& is, char buffer[buffer_size])
{
ConsumeWhitespace(is);
return ReadToken<buffer_size>(is, buffer);
}
inline int ParseToken(const char* token, const char* token_list[], size_t token_list_size)
{
for(size_t i=0; i < token_list_size; ++i) {
if( strcmp(token, token_list[i]) == 0 ) {
return i;
}
}
return -1;
}
#define PANGOLIN_DEFINE_PARSE_TOKEN(x) \
inline x ParseToken##x(const char* token) { \
return (x)ParseToken(token, x##String, x##Size); \
} \
inline x ParseToken##x(std::istream& is) { \
char str_token[parse_max_token_size]; \
ReadToken<parse_max_token_size>(is, str_token); \
return ParseToken##x( str_token ); \
}
}
#endif // PANGOLIN_PARSE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
#pragma once
#include <pangolin/utils/timer.h>
#include <memory>
namespace pangolin
{
class ConditionVariableInterface
{
public:
virtual ~ConditionVariableInterface()
{
}
virtual void wait() = 0;
virtual bool wait(timespec t) = 0;
virtual void signal() = 0;
virtual void broadcast() = 0;
};
std::shared_ptr<ConditionVariableInterface> create_named_condition_variable(const
std::string& name);
std::shared_ptr<ConditionVariableInterface> open_named_condition_variable(const
std::string& name);
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include <memory>
#include <string>
namespace pangolin
{
class SemaphoreInterface
{
public:
virtual ~SemaphoreInterface() {
}
virtual bool tryAcquire() = 0;
virtual void acquire() = 0;
virtual void release() = 0;
};
std::shared_ptr<SemaphoreInterface> create_named_semaphore(const std::string& name,
unsigned int value);
std::shared_ptr<SemaphoreInterface> open_named_semaphore(const std::string& name);
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include <memory>
#include <string>
namespace pangolin
{
class SharedMemoryBufferInterface
{
public:
virtual ~SharedMemoryBufferInterface() {
}
virtual bool tryLock() = 0;
virtual void lock() = 0;
virtual void unlock() = 0;
virtual unsigned char *ptr() = 0;
virtual std::string name() = 0;
};
std::shared_ptr<SharedMemoryBufferInterface> create_named_shared_memory_buffer(const
std::string& name, size_t size);
std::shared_ptr<SharedMemoryBufferInterface> open_named_shared_memory_buffer(const
std::string& name, bool readwrite);
}

View File

@@ -0,0 +1,64 @@
#pragma once
#include <functional>
namespace pangolin {
template<typename TokenType=void>
class Registration
{
public:
using UnregisterFunc = std::function<void(const TokenType&)>;
Registration()
: token()
{
}
Registration(TokenType token, UnregisterFunc unregister)
: token(token), unregister(unregister)
{
}
// No copy constructor
Registration(const Registration&) = delete;
// Default move constructor
Registration(Registration&& o)
{
*this = std::move(o);
}
Registration<TokenType>& operator =(Registration<TokenType>&& o)
{
token = o.token;
unregister = std::move(o.unregister);
o.unregister = nullptr;
return *this;
}
~Registration()
{
Release();
}
void Release()
{
if(unregister) {
unregister(token);
token = TokenType();
}
}
const TokenType& Token()
{
return token;
}
private:
TokenType token;
UnregisterFunc unregister;
};
}

View File

@@ -0,0 +1,56 @@
#pragma once
#include <functional>
#include <map>
#include <pangolin/utils/registration.h>
namespace pangolin {
// Based on http://simmesimme.github.io/tutorials/2015/09/20/signal-slot
template <typename... Args>
class Signal
{
public:
using Id = size_t;
using Reg = Registration<Id>;
Signal()
: current_id_(0)
{
}
Signal(const Signal&) = delete;
Signal(Signal&&) = default;
// connects a std::function to the signal. The returned
// value can be used to disconnect the function again
Reg Connect(const std::function<void(Args...)>& slot) const {
slots_.insert(std::make_pair(++current_id_, slot));
return Reg(current_id_, [this](Id id){ Disconnect(id);});
}
// disconnects a previously connected function
void Disconnect(Id id) const {
slots_.erase(id);
}
// disconnects all previously connected functions
void DisconnectAll() const {
slots_.clear();
}
// calls all connected functions
void operator()(Args... p) {
for(auto it : slots_) {
it.second(p...);
}
}
private:
mutable std::map<Id, std::function<void(Args...)>> slots_;
mutable Id current_id_;
};
}

View File

@@ -0,0 +1,75 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <map>
#include <vector>
#include <pangolin/platform.h>
#include <pangolin/utils/file_utils.h>
#include <csignal>
#ifndef SIGPIPE
# define SIGPIPE 13
#endif // !SIGPIPE
namespace pangolin
{
typedef void (*SigCallbackFn)(int);
struct PANGOLIN_EXPORT SigCallback
{
SigCallback(const int & sig, SigCallbackFn fn, void* data)
: sig(sig), fn(fn), data(data), value(false)
{
std::signal(sig, fn);
}
int sig;
SigCallbackFn fn;
void * data;
volatile sig_atomic_t value;
};
class PANGOLIN_EXPORT SigState
{
public:
static SigState& I();
SigState();
~SigState();
void Clear();
std::map<int, SigCallback> sig_callbacks;
};
PANGOLIN_EXPORT
void RegisterNewSigCallback(SigCallbackFn callback, void* data, const int signal);
}

View File

@@ -0,0 +1,446 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdarg.h>
#include <cmath>
namespace pangolin
{
static const double Identity3d[] = {1,0,0, 0,1,0, 0,0,1};
static const double Zero3d[] = {0,0,0, 0,0,0, 0,0,0};
static const double Identity4d[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
static const double Zero4d[] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
static const float Identity3f[] = {1,0,0, 0,1,0, 0,0,1};
static const float Zero3f[] = {0,0,0, 0,0,0, 0,0,0};
static const float Identity4f[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
static const float Zero4f[] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
template<int R, int C, typename P>
void MatPrint(const P m[R*C])
{
for( int r=0; r < R; ++r)
{
for( int c=0; c < C; ++c )
std::cout << m[R*c+r] << " ";
std::cout << std::endl;
}
std::cout << std::endl;
}
template<int R, int C, typename P>
void MatPrint(const P m[R*C], std::string name)
{
std::cout << name << " = [" << std::endl;
for( int r=0; r < R; ++r)
{
for( int c=0; c < C; ++c )
std::cout << m[R*c+r] << " ";
std::cout << std::endl;
}
std::cout << std::endl << "]" << std::endl;
}
// Set array using varadic arguments
template<int R, int C, typename P>
void MatSet(P m[R*C], ...)
{
va_list ap;
va_start(ap,m);
for( int i=0; i< R*C; ++i )
{
*m = (P)va_arg(ap,double);
++m;
}
}
// m = zeroes(N)
template<int R, int C, typename P>
void SetZero(P m[R*C] )
{
std::fill_n(m,R*C,0);
}
// m = identity(N)
template<int N, typename P>
void SetIdentity(P m[N*N] )
{
std::fill_n(m,N*N,0);
for( int i=0; i< N; ++i )
m[N*i+i] = 1;
}
// mo = m1 * m2
template<int R, int M, int C, typename P>
void MatMul(P mo[R*C], const P m1[R*M], const P m2[M*C] )
{
for( int r=0; r < R; ++r)
for( int c=0; c < C; ++c )
{
mo[R*c+r] = 0;
for( int m=0; m < M; ++ m) mo[R*c+r] += m1[R*m+r] * m2[M*c+m];
}
}
// mo = m1 * m2 * s
template<int R, int M, int C, typename P>
void MatMul(P mo[R*C], const P m1[R*M], const P m2[M*C], P s )
{
for( int r=0; r < R; ++r)
for( int c=0; c < C; ++c )
{
mo[R*c+r] = 0;
for( int m=0; m < M; ++ m) mo[R*c+r] += m1[R*m+r] * m2[M*c+m] * s;
}
}
// mo = m1 * transpose(m2)
template<int R, int M, int C, typename P>
void MatMulTranspose(P mo[R*C], const P m1[R*M], const P m2[C*M] )
{
for( int r=0; r < R; ++r)
for( int c=0; c < C; ++c )
{
mo[R*c+r] = 0;
for( int m=0; m < M; ++ m) mo[R*c+r] += m1[R*m+r] * m2[C*m+c];
}
}
// m = m1 + m2
template<int R, int C, typename P>
void MatAdd(P m[R*C], const P m1[R*C], const P m2[R*C])
{
for( int i=0; i< R*C; ++i )
m[i] = m1[i] + m2[i];
}
// m = m1 - m2
template<int R, int C, typename P>
void MatSub(P m[R*C], const P m1[R*C], const P m2[R*C])
{
for( int i=0; i< R*C; ++i )
m[i] = m1[i] - m2[i];
}
// m = m1 * scalar
template<int R, int C, typename P>
void MatMul(P m[R*C], const P m1[R*C], P scalar)
{
for( int i=0; i< R*C; ++i )
m[i] = m1[i] * scalar;
}
// m = m1 + m2
template<int R, int C, typename P>
void MatMul(P m[R*C], P scalar)
{
for( int i=0; i< R*C; ++i )
m[i] *= scalar;
}
template<int N, typename P>
void MatTranspose(P out[N*N], const P in[N*N] )
{
for( int c=0; c<N; ++c )
for( int r=0; r<N; ++r )
out[N*c+r] = in[N*r+c];
}
template<int N, typename P>
void MatTranspose(P m[N*N] )
{
for( int c=0; c<N; ++c )
for( int r=0; r<c; ++r )
std::swap<P>(m[N*c+r],m[N*r+c]);
}
// m = a x b
template<typename P>
void VecCross3(P m[3], const P a[3], const P b[3])
{
m[0] = a[1]*b[2] - a[2]*b[1];
m[1] = a[2]*b[0] - a[0]*b[2];
m[2] = a[0]*b[1] - a[1]*b[0];
}
// s = skewSymetrixMatrix(v)
template<typename P>
void MatSkew(P s[3*3], const P v[3] )
{
s[0] = 0;
s[1] = v[2];
s[2] = -v[1];
s[3] = -v[2];
s[4] = 0;
s[5] = v[0];
s[6] = v[1];
s[7] = -v[0];
s[8] = 0;
}
template<int N, typename P>
void MatOrtho( P m[N*N] )
{
// http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/index.htm
P Itimes3[N*N];
SetIdentity<N>(Itimes3);
MatMul<N,N>(Itimes3,(P)3.0);
P mmT[N*N];
MatMulTranspose<N,N,N>(mmT,m,m);
P _c[N*N];
MatSub<N,N>(_c,Itimes3,mmT);
P _m[N*N];
MatMul<N,N,N>(_m,m,_c,(P)0.5);
std::copy(_m,_m+(N*N),m);
}
template<typename P>
void Rotation(P R[3*3], P x, P y, P z)
{
P sx = sin(x);
P sy = sin(y);
P sz = sin(z);
P cx = cos(x);
P cy = cos(y);
P cz = cos(z);
// P cx = sqrt( (P)1.0 - sx * sx);
// P cy = sqrt( (P)1.0 - sy * sy);
// P cz = sqrt( (P)1.0 - sz * sz);
R[0] = cy * cz;
R[1] = sx * sy * cz + cx * sz;
R[2] = -cx * sy * cz + sx * sz;
R[3] = -cy * sz;
R[4] = -sx * sy * sz + cx * cz;
R[5] = cx * sy * sz + sx * cz;
R[6] = sy;
R[7] = -sx * cy;
R[8] = cx * cy;
}
template<typename P>
void LieSetIdentity(P T_ba[3*4] )
{
SetIdentity<3>(T_ba);
std::fill_n(T_ba+(3*3),3,0);
}
template<typename P>
void LieSetRotation(P T_ba[3*4], const P R_ba[3*3] )
{
std::copy(R_ba,R_ba+(3*3),T_ba);
}
template<typename P>
void LieSetTranslation(P T_ba[3*4], const P a_b[3] )
{
std::copy(a_b, a_b+3, T_ba+(3*3));
}
template<typename P>
void LieSetSE3(P T_ba[3*4], const P R_ba[3*3], const P a_b[3] )
{
LieSetRotation<P>(T_ba,R_ba);
LieSetTranslation<P>(T_ba,a_b);
}
template<typename P>
void LieGetRotation(P R_ba[3*3], const P T_ba[3*4] )
{
std::copy(T_ba,T_ba+(3*3),R_ba);
}
template<typename P>
void LieApplySO3( P out[3], const P R_ba[3*3], const P in[3] )
{
MatMul<3,3,1,P>(out,R_ba,in);
}
template<typename P>
void LieApplySE3vec( P x_b[3], const P T_ba[3*4], const P x_a[3] )
{
P rot[3];
MatMul<3,3,1,P>(rot,T_ba,x_a);
MatAdd<3,1,P>(x_b,rot,T_ba+(3*3));
}
template<typename P>
void LieApplySE34x4vec3( P x_b[3], const P T_ba[4*4], const P x_a[3] )
{
x_b[0] = T_ba[0]*x_a[0] + T_ba[4]*x_a[1] + T_ba[8]*x_a[2] + T_ba[12];
x_b[1] = T_ba[1]*x_a[0] + T_ba[5]*x_a[1] + T_ba[9]*x_a[2] + T_ba[13];
x_b[2] = T_ba[2]*x_a[0] + T_ba[6]*x_a[1] + T_ba[10]*x_a[2] + T_ba[14];
}
template<typename P>
void LieMulSO3( P R_ca[3*3], const P R_cb[3*3], const P R_ba[3*3] )
{
MatMul<3,3,3>(R_ca,R_cb,R_ba);
}
template<typename P>
void LieMulSE3( P T_ca[3*4], const P T_cb[3*4], const P T_ba[3*4] )
{
LieMulSO3<>(T_ca,T_cb,T_ba);
P R_cb_times_a_b[3];
LieApplySO3<>(R_cb_times_a_b,T_cb,T_ba+(3*3));
MatAdd<3,1>(T_ca+(3*3),R_cb_times_a_b,T_cb+(3*3));
}
template<typename P>
void LiePutSE3in4x4(P out[4*4], const P in[3*4] )
{
SetIdentity<4>(out);
std::copy(in,in+3, out);
std::copy(in+3,in+6, out+4);
std::copy(in+6,in+9, out+8);
std::copy(in+9,in+12, out+12);
}
template<typename P>
void LieSE3from4x4(P out[3*4], const P in[4*4] )
{
std::copy(in,in+3, out);
std::copy(in+4,in+7, out+3);
std::copy(in+8,in+11, out+6);
std::copy(in+12,in+15, out+9);
}
template<typename P>
void LieMul4x4bySE3( P T_ca[4*4], const P T_cb[3*4], const P T_ba[4*4] )
{
// TODO: fast
P T_cb4[4*4];
LiePutSE3in4x4<>(T_cb4,T_cb);
P res[4*4];
MatMul<4,4,4>(res,T_cb4,T_ba);
std::copy(res,res+(4*4),T_ca);
}
template<typename P>
void LieTransposeSO3( P R_ab[3*3], const P R_ba[3*3] )
{
MatTranspose<3,P>(R_ab,R_ba);
}
template<typename P>
void LieInverseSE3( P T_ab[3*4], const P T_ba[3*4] )
{
LieTransposeSO3<P>(T_ab,T_ba);
P minus_b_a[3];
LieApplySO3(minus_b_a, T_ab, T_ba+(3*3));
MatMul<3,1,P>(T_ab+(3*3),minus_b_a, -1);
}
// c = a x b
template<typename P>
void CrossProduct( P c[3], const P a[3], const P b[3] )
{
c[0] = a[1] * b[2] - a[2] * b[1];
c[1] = a[2] * b[0] - a[0] * b[2];
c[2] = a[0] * b[1] - a[1] * b[0];
}
template<int R, typename P>
P Length( P v[R] )
{
P sum_sq = 0;
for(size_t r = 0; r < R; ++r ) {
sum_sq += v[r] * v[r];
}
return sqrt(sum_sq);
}
template<int R, typename P>
void Normalise( P v[R] )
{
const P length = Length<R,P>(v);
for(size_t r = 0; r < R; ++r ) {
v[r] /= length;
}
}
template<typename P>
void EnforceUpT_wc(P T_wc[3*4], const P up_w[3])
{
// Copy R_wc
P R_wc[3*3];
std::copy(T_wc,T_wc+3*3,R_wc);
// New R_wc should go into T_wc
P* NR_wc = T_wc;
// // cx_w,cy_w,cz_w are camera axis in world coordinates
// // Calculate new camera coordinates (ncx_w,ncy_w,ncz_w)
// ncx_w = up_w x cz_w
CrossProduct(NR_wc + 0*3, up_w, R_wc + 2*3);
// ncy_w = cz_w x ncx_w
CrossProduct(NR_wc + 1*3, R_wc + 2*3, NR_wc + 0*3);
// ncz_w = cz_w
std::copy(R_wc + 2*3, R_wc + 3*3, NR_wc + 2*3);
Normalise<3,P>(NR_wc + 0*3);
Normalise<3,P>(NR_wc + 1*3);
Normalise<3,P>(NR_wc + 2*3);
}
template<typename P>
void EnforceUpT_cw(P T_cw_4x4[4*4], const P up_w[3])
{
// 3x4 from 4x4
P T_cw[3*4];
LieSE3from4x4<P>(T_cw,T_cw_4x4);
// Invert T_cw
P T_wc[3*4];
LieInverseSE3<P>(T_wc, T_cw);
// Enforce up for T_wc
EnforceUpT_wc<P>(T_wc, up_w);
// Invert
LieInverseSE3<P>(T_cw, T_wc);
// 4x4 from 3x4
LiePutSE3in4x4<P>(T_cw_4x4,T_cw);
}
}

View File

@@ -0,0 +1,97 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <iostream>
#include <streambuf>
#include <fstream>
#include <pangolin/platform.h>
#include <thread>
#include <mutex>
#include <condition_variable>
#ifdef _LINUX_
// On linux, using posix file i/o to allow sync writes.
#define USE_POSIX_FILE_IO
#endif
namespace pangolin
{
class PANGOLIN_EXPORT threadedfilebuf : public std::streambuf
{
public:
~threadedfilebuf();
threadedfilebuf();
threadedfilebuf(const std::string& filename, size_t buffer_size_bytes);
void open(const std::string& filename, size_t buffer_size_bytes);
void close();
void force_close();
void operator()();
protected:
void soft_close();
//! Override streambuf::xsputn for asynchronous write
std::streamsize xsputn(const char * s, std::streamsize n) override;
//! Override streambuf::overflow for asynchronous write
int overflow(int c) override;
std::streampos seekoff(
std::streamoff off, std::ios_base::seekdir way,
std::ios_base::openmode which = std::ios_base::in | std::ios_base::out
) override;
#ifdef USE_POSIX_FILE_IO
int filenum = -1;
#else
std::filebuf file;
#endif
char* mem_buffer;
std::streamsize mem_size;
std::streamsize mem_max_size;
std::streamsize mem_start;
std::streamsize mem_end;
std::streampos input_pos;
std::mutex update_mutex;
std::condition_variable cond_queued;
std::condition_variable cond_dequeued;
std::thread write_thread;
bool should_run;
bool is_pipe;
};
}

View File

@@ -0,0 +1,116 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <chrono>
#include <thread>
#include <pangolin/platform.h>
namespace pangolin
{
// These methods exist for backwards compatibility.
// They are deprecated in favour of direct use of std::chrono in C++11
using baseclock = std::chrono::steady_clock;
using basetime = baseclock::time_point;
static_assert(baseclock::is_steady, "baseclock must be steady to be robust against system time settings");
inline basetime TimeNow()
{
return baseclock::now();
}
inline double Time_s(basetime t)
{
using namespace std::chrono;
return duration_cast<seconds>( t.time_since_epoch() ).count();
}
inline int64_t Time_us(basetime t)
{
using namespace std::chrono;
return duration_cast<microseconds>( t.time_since_epoch() ).count();
}
inline double TimeDiff_s(basetime start, basetime end)
{
const baseclock::duration d = end - start;
return Time_s( basetime() + d);
}
inline int64_t TimeDiff_us(basetime start, basetime end)
{
const baseclock::duration d = end - start;
return Time_us( basetime() + d);
}
inline basetime TimeAdd(basetime t1, basetime t2)
{
return t1 + t2.time_since_epoch();
}
inline double TimeNow_s()
{
return Time_s(TimeNow());
}
inline int64_t TimeNow_us()
{
return Time_us(TimeNow());
}
inline basetime WaitUntil(basetime t)
{
std::this_thread::sleep_until(t);
return TimeNow();
}
struct Timer
{
Timer() {
Reset();
}
void Reset()
{
start = TimeNow();
}
double Elapsed_s()
{
basetime currtime = TimeNow();
return TimeDiff_s(start,currtime);
}
basetime start;
};
}

View File

@@ -0,0 +1,102 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <ostream>
#include <functional>
namespace pangolin
{
// Find the open brace preceeded by '$'
inline const char* FirstOpenBrace(const char* str, char token = '$', char open = '{')
{
bool symbol = false;
for(; *str != '\0'; ++str ) {
if( *str == token) {
symbol = true;
}else{
if( symbol ) {
if( *str == open ) {
return str;
} else {
symbol = false;
}
}
}
}
return 0;
}
// Find the first matching end brace. str includes open brace
inline const char* MatchingEndBrace(const char* str, char open = '{', char close = '}')
{
int b = 0;
for(; *str != '\0'; ++str ) {
if( *str == open ) {
++b;
}else if( *str == close ) {
--b;
if( b == 0 ) {
return str;
}
}
}
return 0;
}
inline std::string Transform(const std::string& val, std::function<std::string(const std::string&)> dictionary, char token = '$', char open = '{', char close = '}')
{
std::string expanded = val;
while(true)
{
const char* brace = FirstOpenBrace(expanded.c_str(), token, open);
if(brace)
{
const char* endbrace = MatchingEndBrace(brace);
if( endbrace )
{
std::ostringstream oss;
oss << std::string(expanded.c_str(), brace-1);
const std::string inexpand = Transform( std::string(brace+1,endbrace), dictionary, token, open, close );
oss << dictionary(inexpand);
oss << std::string(endbrace+1, expanded.c_str() + expanded.length() );
expanded = oss.str();
continue;
}
}
break;
}
return expanded;
}
}

View File

@@ -0,0 +1,210 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <iostream>
#include <sstream>
#include <functional>
#include <pangolin/compat/type_traits.h>
namespace pangolin
{
struct BadInputException : std::exception {
char const* what() const throw() { return "Failed to serialise type"; }
};
}
namespace std
{
// Dummy methods to serialise functions / functors / lambdas etc
#ifdef CALLEE_HAS_VARIADIC_TEMPLATES
template<typename Ret, typename... Args>
inline std::istream& operator>>(std::istream& /*is*/, std::function<Ret(Args...)>& /*f*/) {
throw pangolin::BadInputException();
}
template<typename Ret, typename... Args>
inline std::ostream& operator<<(std::ostream& /*os*/, const std::function<Ret(Args...)>& /*f*/) {
throw pangolin::BadInputException();
}
#else
template<typename Ret, typename Arg>
inline std::istream& operator>>(std::istream& /*is*/, std::function<Ret(Arg)>& /*f*/) {
throw pangolin::BadInputException();
}
template<typename Ret, typename Arg>
inline std::ostream& operator<<(std::ostream& /*os*/, const std::function<Ret(Arg)>& /*f*/) {
throw pangolin::BadInputException();
}
inline std::istream& operator>>(std::istream& /*is*/, std::function<void(void)>& /*f*/) {
throw pangolin::BadInputException();
}
inline std::ostream& operator<<(std::ostream& /*os*/, const std::function<void(void)>& /*f*/) {
throw pangolin::BadInputException();
}
#endif
}
namespace pangolin
{
template<typename T, typename S, typename Enable=void>
struct Convert;
// Generic conversion through serialisation from / to string
template<typename T, typename S, typename Enable>
struct Convert {
static T Do(const S& src)
{
std::ostringstream oss;
oss << src;
std::istringstream iss(oss.str());
T target;
iss >> target;
if(iss.fail())
throw BadInputException();
return target;
}
};
// Between the same types is just a copy
template<typename T>
struct Convert<T, T > {
static T Do(const T& src)
{
return src;
}
};
// Apply bool alpha IO manipulator for bool types
template<>
struct Convert<bool,std::string> {
static bool Do(const std::string& src)
{
bool target;
std::istringstream iss(src);
iss >> target;
if(iss.fail())
{
std::istringstream iss2(src);
iss2 >> std::boolalpha >> target;
if( iss2.fail())
throw BadInputException();
}
return target;
}
};
// From strings
template<typename T>
struct Convert<T,std::string, typename pangolin::enable_if_c<
!std::is_same<T,std::string>::value
>::type > {
static T Do(const std::string& src)
{
T target;
std::istringstream iss(src);
iss >> target;
if(iss.fail())
throw BadInputException();
return target;
}
};
// To strings
template<typename S>
struct Convert<std::string, S, typename pangolin::enable_if_c<
!std::is_same<S,std::string>::value
>::type > {
static std::string Do(const S& src)
{
std::ostringstream oss;
oss << src;
return oss.str();
}
};
// Between scalars
template<typename T, typename S>
struct Convert<T, S, typename pangolin::enable_if_c<
std::is_scalar<T>::value && !std::is_same<T, bool>::value &&
std::is_scalar<S>::value && !std::is_same<S, bool>::value &&
!std::is_same<S,T>::value
>::type > {
static T Do(const S& src)
{
return static_cast<T>(src);
}
};
// From Scalars to bool (different than scalar definition to avoid MSVC Warnings)
template<typename T, typename S>
struct Convert<T, S, typename pangolin::enable_if_c<
std::is_same<T, bool>::value &&
std::is_scalar<S>::value &&
!std::is_same<S, T>::value
>::type > {
static T Do(const S& src)
{
return src != static_cast<S>(0);
}
};
// From bool to Scalars (different than scalar definition to avoid MSVC Warnings)
template<typename T, typename S>
struct Convert<T, S, typename pangolin::enable_if_c<
std::is_scalar<T>::value &&
std::is_same<S, bool>::value &&
!std::is_same<S, T>::value
>::type > {
static T Do(const S& src)
{
return src ? static_cast<T>(0) : static_cast<T>(1);
}
};
template<typename S>
std::string ToString(const S& src)
{
return Convert<std::string,S>::Do(src);
}
template<typename T>
T FromString(const std::string& src)
{
return Convert<T,std::string>::Do(src);
}
}

View File

@@ -0,0 +1,49 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/utils/params.h>
#include <string>
namespace pangolin
{
class PANGOLIN_EXPORT Uri : public Params
{
public:
std::string scheme;
std::string url;
std::string full_uri;
};
//! Parse string as Video URI
PANGOLIN_EXPORT
Uri ParseUri(const std::string& str_uri);
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include <tuple>
namespace pangolin {
template<typename TPred, typename T>
bool all_of(TPred pred, const T& i)
{
return pred(i);
}
template<typename TPred, typename T, typename... Targs>
bool all_of(const TPred& pred, const T& i, const Targs& ... ins)
{
return pred(i) && all_of(pred, ins...);
}
template<typename TPred, typename T>
bool any_of(TPred pred, const T& i)
{
return pred(i);
}
template<typename TPred, typename T, typename... Targs>
bool any_of(const TPred& pred, const T& i, Targs& ... ins)
{
return pred(i) || any_of(pred, ins...);
}
template<typename TContainer, typename... Targs>
bool all_found(const TContainer& c, const Targs& ... its)
{
using T1 = typename std::tuple_element<0, std::tuple<Targs...>>::type;
return all_of([&c](const T1& it){return it != c.end();}, its...);
}
template<typename T, typename... Targs>
bool all_equal(const T& v1, const Targs& ... its)
{
return all_of([v1](const T& o){return v1 == o;}, its...);
}
}

View File

@@ -0,0 +1,52 @@
Use of this software is granted under one of the following two licenses,
to be chosen freely by the user.
1. Boost Software License - Version 1.0 - August 17th, 2003
===============================================================================
Copyright (c) 2006, 2007 Marcin Kalicinski
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
2. The MIT License
===============================================================================
Copyright (c) 2006, 2007 Marcin Kalicinski
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,174 @@
#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED
#define RAPIDXML_ITERATORS_HPP_INCLUDED
// Copyright (C) 2006, 2009 Marcin Kalicinski
// Version 1.13
// Revision $DateTime: 2009/05/13 01:46:17 $
//! \file rapidxml_iterators.hpp This file contains rapidxml iterators
#include "rapidxml.hpp"
namespace rapidxml
{
//! Iterator of child nodes of xml_node
template<class Ch>
class node_iterator
{
public:
typedef typename xml_node<Ch> value_type;
typedef typename xml_node<Ch> &reference;
typedef typename xml_node<Ch> *pointer;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
node_iterator()
: m_node(0)
{
}
node_iterator(xml_node<Ch> *node)
: m_node(node->first_node())
{
}
reference operator *() const
{
assert(m_node);
return *m_node;
}
pointer operator->() const
{
assert(m_node);
return m_node;
}
node_iterator& operator++()
{
assert(m_node);
m_node = m_node->next_sibling();
return *this;
}
node_iterator operator++(int)
{
node_iterator tmp = *this;
++this;
return tmp;
}
node_iterator& operator--()
{
assert(m_node && m_node->previous_sibling());
m_node = m_node->previous_sibling();
return *this;
}
node_iterator operator--(int)
{
node_iterator tmp = *this;
++this;
return tmp;
}
bool operator ==(const node_iterator<Ch> &rhs)
{
return m_node == rhs.m_node;
}
bool operator !=(const node_iterator<Ch> &rhs)
{
return m_node != rhs.m_node;
}
private:
xml_node<Ch> *m_node;
};
//! Iterator of child attributes of xml_node
template<class Ch>
class attribute_iterator
{
public:
typedef typename xml_attribute<Ch> value_type;
typedef typename xml_attribute<Ch> &reference;
typedef typename xml_attribute<Ch> *pointer;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
attribute_iterator()
: m_attribute(0)
{
}
attribute_iterator(xml_node<Ch> *node)
: m_attribute(node->first_attribute())
{
}
reference operator *() const
{
assert(m_attribute);
return *m_attribute;
}
pointer operator->() const
{
assert(m_attribute);
return m_attribute;
}
attribute_iterator& operator++()
{
assert(m_attribute);
m_attribute = m_attribute->next_attribute();
return *this;
}
attribute_iterator operator++(int)
{
attribute_iterator tmp = *this;
++this;
return tmp;
}
attribute_iterator& operator--()
{
assert(m_attribute && m_attribute->previous_attribute());
m_attribute = m_attribute->previous_attribute();
return *this;
}
attribute_iterator operator--(int)
{
attribute_iterator tmp = *this;
++this;
return tmp;
}
bool operator ==(const attribute_iterator<Ch> &rhs)
{
return m_attribute == rhs.m_attribute;
}
bool operator !=(const attribute_iterator<Ch> &rhs)
{
return m_attribute != rhs.m_attribute;
}
private:
xml_attribute<Ch> *m_attribute;
};
}
#endif

View File

@@ -0,0 +1,421 @@
#ifndef RAPIDXML_PRINT_HPP_INCLUDED
#define RAPIDXML_PRINT_HPP_INCLUDED
// Copyright (C) 2006, 2009 Marcin Kalicinski
// Version 1.13
// Revision $DateTime: 2009/05/13 01:46:17 $
//! \file rapidxml_print.hpp This file contains rapidxml printer implementation
#include "rapidxml.hpp"
// Only include streams if not disabled
#ifndef RAPIDXML_NO_STREAMS
#include <ostream>
#include <iterator>
#endif
namespace rapidxml
{
///////////////////////////////////////////////////////////////////////
// Printing flags
const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
///////////////////////////////////////////////////////////////////////
// Internal
//! \cond internal
namespace internal
{
///////////////////////////////////////////////////////////////////////////
// Internal character operations
// Copy characters from given range to given output iterator
template<class OutIt, class Ch>
inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
{
while (begin != end)
*out++ = *begin++;
return out;
}
// Copy characters from given range to given output iterator and expand
// characters into references (&lt; &gt; &apos; &quot; &amp;)
template<class OutIt, class Ch>
inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
{
while (begin != end)
{
if (*begin == noexpand)
{
*out++ = *begin; // No expansion, copy character
}
else
{
switch (*begin)
{
case Ch('<'):
*out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
break;
case Ch('>'):
*out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
break;
case Ch('\''):
*out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
break;
case Ch('"'):
*out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
break;
case Ch('&'):
*out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';');
break;
default:
*out++ = *begin; // No expansion, copy character
}
}
++begin; // Step to next character
}
return out;
}
// Fill given output iterator with repetitions of the same character
template<class OutIt, class Ch>
inline OutIt fill_chars(OutIt out, int n, Ch ch)
{
for (int i = 0; i < n; ++i)
*out++ = ch;
return out;
}
// Find character
template<class Ch, Ch ch>
inline bool find_char(const Ch *begin, const Ch *end)
{
while (begin != end)
if (*begin++ == ch)
return true;
return false;
}
///////////////////////////////////////////////////////////////////////////
// Internal printing operations
// Print node
template<class OutIt, class Ch>
inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
// Print proper node type
switch (node->type())
{
// Document
case node_document:
out = print_children(out, node, flags, indent);
break;
// Element
case node_element:
out = print_element_node(out, node, flags, indent);
break;
// Data
case node_data:
out = print_data_node(out, node, flags, indent);
break;
// CDATA
case node_cdata:
out = print_cdata_node(out, node, flags, indent);
break;
// Declaration
case node_declaration:
out = print_declaration_node(out, node, flags, indent);
break;
// Comment
case node_comment:
out = print_comment_node(out, node, flags, indent);
break;
// Doctype
case node_doctype:
out = print_doctype_node(out, node, flags, indent);
break;
// Pi
case node_pi:
out = print_pi_node(out, node, flags, indent);
break;
// Unknown
default:
assert(0);
break;
}
// If indenting not disabled, add line break after node
if (!(flags & print_no_indenting))
*out = Ch('\n'), ++out;
// Return modified iterator
return out;
}
// Print children of the node
template<class OutIt, class Ch>
inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
out = print_node(out, child, flags, indent);
return out;
}
// Print attributes of the node
template<class OutIt, class Ch>
inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
{
for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
{
if (attribute->name() && attribute->value())
{
// Print attribute name
*out = Ch(' '), ++out;
out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
*out = Ch('='), ++out;
// Print attribute value using appropriate quote type
if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
{
*out = Ch('\''), ++out;
out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
*out = Ch('\''), ++out;
}
else
{
*out = Ch('"'), ++out;
out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
*out = Ch('"'), ++out;
}
}
}
return out;
}
// Print data node
template<class OutIt, class Ch>
inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_data);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
return out;
}
// Print data node
template<class OutIt, class Ch>
inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_cdata);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'); ++out;
*out = Ch('!'); ++out;
*out = Ch('['); ++out;
*out = Ch('C'); ++out;
*out = Ch('D'); ++out;
*out = Ch('A'); ++out;
*out = Ch('T'); ++out;
*out = Ch('A'); ++out;
*out = Ch('['); ++out;
out = copy_chars(node->value(), node->value() + node->value_size(), out);
*out = Ch(']'); ++out;
*out = Ch(']'); ++out;
*out = Ch('>'); ++out;
return out;
}
// Print element node
template<class OutIt, class Ch>
inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_element);
// Print element name and attributes, if any
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'), ++out;
out = copy_chars(node->name(), node->name() + node->name_size(), out);
out = print_attributes(out, node, flags);
// If node is childless
if (node->value_size() == 0 && !node->first_node())
{
// Print childless node tag ending
*out = Ch('/'), ++out;
*out = Ch('>'), ++out;
}
else
{
// Print normal node tag ending
*out = Ch('>'), ++out;
// Test if node contains a single data node only (and no other nodes)
xml_node<Ch> *child = node->first_node();
if (!child)
{
// If node has no children, only print its value without indenting
out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
}
else if (child->next_sibling() == 0 && child->type() == node_data)
{
// If node has a sole data child, only print its value without indenting
out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
}
else
{
// Print all children with full indenting
if (!(flags & print_no_indenting))
*out = Ch('\n'), ++out;
out = print_children(out, node, flags, indent + 1);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
}
// Print node end
*out = Ch('<'), ++out;
*out = Ch('/'), ++out;
out = copy_chars(node->name(), node->name() + node->name_size(), out);
*out = Ch('>'), ++out;
}
return out;
}
// Print declaration node
template<class OutIt, class Ch>
inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
// Print declaration start
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'), ++out;
*out = Ch('?'), ++out;
*out = Ch('x'), ++out;
*out = Ch('m'), ++out;
*out = Ch('l'), ++out;
// Print attributes
out = print_attributes(out, node, flags);
// Print declaration end
*out = Ch('?'), ++out;
*out = Ch('>'), ++out;
return out;
}
// Print comment node
template<class OutIt, class Ch>
inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_comment);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'), ++out;
*out = Ch('!'), ++out;
*out = Ch('-'), ++out;
*out = Ch('-'), ++out;
out = copy_chars(node->value(), node->value() + node->value_size(), out);
*out = Ch('-'), ++out;
*out = Ch('-'), ++out;
*out = Ch('>'), ++out;
return out;
}
// Print doctype node
template<class OutIt, class Ch>
inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_doctype);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'), ++out;
*out = Ch('!'), ++out;
*out = Ch('D'), ++out;
*out = Ch('O'), ++out;
*out = Ch('C'), ++out;
*out = Ch('T'), ++out;
*out = Ch('Y'), ++out;
*out = Ch('P'), ++out;
*out = Ch('E'), ++out;
*out = Ch(' '), ++out;
out = copy_chars(node->value(), node->value() + node->value_size(), out);
*out = Ch('>'), ++out;
return out;
}
// Print pi node
template<class OutIt, class Ch>
inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_pi);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'), ++out;
*out = Ch('?'), ++out;
out = copy_chars(node->name(), node->name() + node->name_size(), out);
*out = Ch(' '), ++out;
out = copy_chars(node->value(), node->value() + node->value_size(), out);
*out = Ch('?'), ++out;
*out = Ch('>'), ++out;
return out;
}
}
//! \endcond
///////////////////////////////////////////////////////////////////////////
// Printing
//! Prints XML to given output iterator.
//! \param out Output iterator to print to.
//! \param node Node to be printed. Pass xml_document to print entire document.
//! \param flags Flags controlling how XML is printed.
//! \return Output iterator pointing to position immediately after last character of printed text.
template<class OutIt, class Ch>
inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
{
return internal::print_node(out, &node, flags, 0);
}
#ifndef RAPIDXML_NO_STREAMS
//! Prints XML to given output stream.
//! \param out Output stream to print to.
//! \param node Node to be printed. Pass xml_document to print entire document.
//! \param flags Flags controlling how XML is printed.
//! \return Output stream.
template<class Ch>
inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
{
print(std::ostream_iterator<Ch>(out), node, flags);
return out;
}
//! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
//! \param out Output stream to print to.
//! \param node Node to be printed.
//! \return Output stream.
template<class Ch>
inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
{
return print(out, node);
}
#endif
}
#endif

View File

@@ -0,0 +1,122 @@
#ifndef RAPIDXML_UTILS_HPP_INCLUDED
#define RAPIDXML_UTILS_HPP_INCLUDED
// Copyright (C) 2006, 2009 Marcin Kalicinski
// Version 1.13
// Revision $DateTime: 2009/05/13 01:46:17 $
//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
#include "rapidxml.hpp"
#include <vector>
#include <string>
#include <fstream>
#include <stdexcept>
namespace rapidxml
{
//! Represents data loaded from a file
template<class Ch = char>
class file
{
public:
//! Loads file into the memory. Data will be automatically destroyed by the destructor.
//! \param filename Filename to load.
file(const char *filename)
{
using namespace std;
// Open stream
basic_ifstream<Ch> stream(filename, ios::binary);
if (!stream)
throw runtime_error(string("cannot open file ") + filename);
stream.unsetf(ios::skipws);
// Determine stream size
stream.seekg(0, ios::end);
size_t size = (size_t)stream.tellg();
stream.seekg(0);
// Load data and add terminating 0
m_data.resize(size + 1);
stream.read(&m_data.front(), static_cast<streamsize>(size));
m_data[size] = 0;
}
//! Loads file into the memory. Data will be automatically destroyed by the destructor
//! \param stream Stream to load from
file(std::basic_istream<Ch> &stream)
{
using namespace std;
// Load data and add terminating 0
stream.unsetf(ios::skipws);
m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
if (stream.fail() || stream.bad())
throw runtime_error("error reading stream");
m_data.push_back(0);
}
//! Gets file data.
//! \return Pointer to data of file.
Ch *data()
{
return &m_data.front();
}
//! Gets file data.
//! \return Pointer to data of file.
const Ch *data() const
{
return &m_data.front();
}
//! Gets file data size.
//! \return Size of file data, in characters.
std::size_t size() const
{
return m_data.size();
}
private:
std::vector<Ch> m_data; // File data
};
//! Counts children of node. Time complexity is O(n).
//! \return Number of children of node
template<class Ch>
inline std::size_t count_children(xml_node<Ch> *node)
{
xml_node<Ch> *child = node->first_node();
std::size_t count = 0;
while (child)
{
++count;
child = child->next_sibling();
}
return count;
}
//! Counts attributes of node. Time complexity is O(n).
//! \return Number of attributes of node
template<class Ch>
inline std::size_t count_attributes(xml_node<Ch> *node)
{
xml_attribute<Ch> *attr = node->first_attribute();
std::size_t count = 0;
while (attr)
{
++count;
attr = attr->next_attribute();
}
return count;
}
}
#endif