summaryrefslogtreecommitdiffstats
path: root/xbmc/commons
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--xbmc/commons/Buffer.h254
-rw-r--r--xbmc/commons/CMakeLists.txt7
-rw-r--r--xbmc/commons/Exception.cpp22
-rw-r--r--xbmc/commons/Exception.h113
-rw-r--r--xbmc/commons/ilog.h46
5 files changed, 442 insertions, 0 deletions
diff --git a/xbmc/commons/Buffer.h b/xbmc/commons/Buffer.h
new file mode 100644
index 0000000..98085ea
--- /dev/null
+++ b/xbmc/commons/Buffer.h
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include <memory>
+#include <string.h>
+#include <string>
+
+namespace XbmcCommons
+{
+ class BufferException final
+ {
+ std::string message;
+
+ public:
+ explicit BufferException(const char* message_) : message(message_) {}
+ };
+
+ /**
+ * This class is based on the java java.nio.Buffer class however, it
+ * does not implement the 'mark' functionality.
+ *
+ * [ the following is borrowed from the javadocs for java.nio.Buffer
+ * where it applies to this class]:
+ *
+ * A buffer is a linear, finite sequence of elements of a unspecified types.
+ * Aside from its content, the essential properties of a buffer are its capacity,
+ * limit, and position:
+ * A buffer's capacity is the number of elements it contains. The capacity
+ * of a buffer is never negative and never changes.
+ *
+ * A buffer's limit is the index of the first element that should not be
+ * read or written. A buffer's limit is never negative and is never greater
+ * than its capacity.
+ *
+ * A buffer's position is the index of the next element to be read or written.
+ * A buffer's position is never negative and is never greater than its limit.
+ *
+ * Invariants:
+ *
+ * The following invariant holds for the mark, position, limit, and capacity values:
+ *
+ * 0 <= mark <= position <= limit <= capacity
+ *
+ * A newly-created buffer always has a position of zero and a limit set to the
+ * capacity. The initial content of a buffer is, in general, undefined.
+ *
+ * Example:
+ * Buffer buffer(1024);
+ * buffer.putInt(1).putString("hello there").putLongLong( ((long long)2)^40 );
+ * buffer.flip();
+ * std::cout << "buffer contents:" << buffer.getInt() << ", ";
+ * std::cout << buffer.getCharPointerDirect() << ", ";
+ * std::cout << buffer.getLongLong() << std::endl;
+ *
+ * Note: the 'gets' are sensitive to the order-of-operations. Therefore, while
+ * the above is correct, it would be wrong to chain the output as follows:
+ *
+ * std::cout << "buffer contents:" << buffer.getInt() << ", " << std::cout
+ * << buffer.getCharPointerDirect() << ", " << buffer.getLongLong()
+ * << std::endl;
+ *
+ * This would result in the get's executing from right to left and therefore would
+ * produce totally erroneous results. This is also a problem when the values are
+ * passed to a method as in:
+ *
+ * printf("buffer contents: %d, \"%s\", %ll\n", buffer.getInt(),
+ * buffer.getCharPointerDirect(), buffer.getLongLong());
+ *
+ * This would also produce erroneous results as they get's will be evaluated
+ * from right to left in the parameter list of printf.
+ */
+ class Buffer
+ {
+ std::shared_ptr<unsigned char> bufferRef;
+ unsigned char* buffer = nullptr;
+ size_t mposition = 0;
+ size_t mcapacity = 0;
+ size_t mlimit = 0;
+
+ inline void check(size_t count) const
+ {
+ if ((mposition + count) > mlimit)
+ throw BufferException("Buffer buffer overflow: Cannot add more data to the Buffer's buffer.");
+ }
+
+ public:
+ /**
+ * Construct an uninitialized buffer instance, perhaps as an lvalue.
+ */
+ inline Buffer() { clear(); }
+
+ /**
+ * Construct a buffer given an externally managed memory buffer.
+ * The ownership of the buffer is assumed to be the code that called
+ * this constructor, therefore the Buffer destructor will not free it.
+ *
+ * The newly constructed buffer is considered empty and is ready to
+ * have data written into it.
+ *
+ * If you want to read from the buffer you just created, you can use:
+ *
+ * Buffer b = Buffer(buf,bufSize).forward(bufSize).flip();
+ */
+ inline Buffer(void* buffer_, size_t bufferSize) : buffer((unsigned char*)buffer_), mcapacity(bufferSize)
+ {
+ clear();
+ }
+
+ /**
+ * Construct a buffer buffer using the size buffer provided. The
+ * buffer will be internally managed and potentially shared with
+ * other Buffer instances. It will be freed upon destruction of
+ * the last Buffer that references it.
+ */
+ inline explicit Buffer(size_t bufferSize) : buffer(bufferSize ? new unsigned char[bufferSize] : NULL), mcapacity(bufferSize)
+ {
+ clear();
+ bufferRef.reset(buffer, std::default_delete<unsigned char[]>());
+ }
+
+ /**
+ * Copy another buffer. This is a "shallow copy" and therefore
+ * shares the underlying data buffer with the Buffer it is a copy
+ * of. Changes made to the data through this buffer will be seen
+ * in the source buffer and vice/vrs. However, each buffer maintains
+ * its own indexing.
+ */
+ inline Buffer(const Buffer& buf) = default;
+
+ /**
+ * Copy another buffer. This is a "shallow copy" and therefore
+ * shares the underlying data buffer with the Buffer it is a copy
+ * of. Changes made to the data through this buffer will be seen
+ * in the source buffer and vice/vrs. However, each buffer maintains
+ * its own indexing.
+ */
+ inline Buffer& operator=(const Buffer& buf)
+ {
+ buffer = buf.buffer;
+ bufferRef = buf.bufferRef;
+ mcapacity = buf.mcapacity;
+ mlimit = buf.mlimit;
+ return *this;
+ }
+
+ inline Buffer& allocate(size_t bufferSize)
+ {
+ buffer = bufferSize ? new unsigned char[bufferSize] : NULL;
+ bufferRef.reset(buffer, std::default_delete<unsigned char[]>());
+ mcapacity = bufferSize;
+ clear();
+ return *this;
+ }
+
+ /**
+ * Flips this buffer. The limit is set to the current position
+ * and then the position is set to zero.
+ *
+ * After a sequence of channel-read or put operations, invoke this
+ * method to prepare for a sequence of channel-write or relative
+ * get operations. For example:
+ *
+ * buf.put(magic); // Prepend header
+ * in.read(buf); // Read data into rest of buffer
+ * buf.flip(); // Flip buffer
+ * out.write(buf); // Write header + data to channel
+ *
+ * This is used to prepare the Buffer for reading from after
+ * it has been written to.
+ */
+ inline Buffer& flip() { mlimit = mposition; mposition = 0; return *this; }
+
+ /**
+ *Clears this buffer. The position is set to zero, the limit
+ * is set to the capacity.
+ *
+ * Invoke this method before using a sequence of channel-read
+ * or put operations to fill this buffer. For example:
+ *
+ * buf.clear(); // Prepare buffer for reading
+ * in.read(buf); // Read data
+ *
+ * This method does not actually erase the data in the buffer,
+ * but it is named as if it did because it will most often be used
+ * in situations in which that might as well be the case.
+ */
+ inline Buffer& clear() { mlimit = mcapacity; mposition = 0; return *this; }
+
+ /**
+ * This method resets the position to the beginning of the buffer
+ * so that it can be either reread or written to all over again.
+ */
+ inline Buffer& rewind() { mposition = 0; return *this; }
+
+ /**
+ * This method provides for the remaining number of bytes
+ * that can be read out of the buffer or written into the
+ * buffer before it's finished.
+ */
+ inline size_t remaining() const { return mlimit - mposition; }
+
+ inline Buffer& put(const void* src, size_t bytes)
+ { check(bytes); memcpy( buffer + mposition, src, bytes); mposition += bytes; return *this; }
+ inline Buffer& get(void* dest, size_t bytes)
+ { check(bytes); memcpy( dest, buffer + mposition, bytes); mposition += bytes; return *this; }
+
+ inline unsigned char* data() const { return buffer; }
+ inline unsigned char* curPosition() const { return buffer + mposition; }
+ inline Buffer& setPosition(size_t position) { mposition = position; return *this; }
+ inline Buffer& forward(size_t positionIncrement)
+ { check(positionIncrement); mposition += positionIncrement; return *this; }
+
+ inline size_t limit() const { return mlimit; }
+ inline size_t capacity() const { return mcapacity; }
+ inline size_t position() const { return mposition; }
+
+#define DEFAULTBUFFERRELATIVERW(name,type) \
+ inline Buffer& put##name(const type & val) { return put(&val, sizeof(type)); } \
+ inline type get##name() { type ret; get(&ret, sizeof(type)); return ret; }
+
+ DEFAULTBUFFERRELATIVERW(Bool,bool);
+ DEFAULTBUFFERRELATIVERW(Int,int);
+ DEFAULTBUFFERRELATIVERW(Char,char);
+ DEFAULTBUFFERRELATIVERW(Long,long);
+ DEFAULTBUFFERRELATIVERW(Float,float);
+ DEFAULTBUFFERRELATIVERW(Double,double);
+ DEFAULTBUFFERRELATIVERW(Pointer,void*);
+ DEFAULTBUFFERRELATIVERW(LongLong,long long);
+#undef DEFAULTBUFFERRELATIVERW
+
+ inline Buffer& putString(const char* str) { size_t len = strlen(str) + 1; check(len); put(str, len); return (*this); }
+ inline Buffer& putString(const std::string& str) { size_t len = str.length() + 1; check(len); put(str.c_str(), len); return (*this); }
+
+ inline std::string getString() { std::string ret((const char*)(buffer + mposition)); size_t len = ret.length() + 1; check(len); mposition += len; return ret; }
+ inline std::string getString(size_t length)
+ {
+ check(length);
+ std::string ret((const char*)(buffer + mposition),length);
+ mposition += length;
+ return ret;
+ }
+ inline char* getCharPointerDirect() { char* ret = (char*)(buffer + mposition); size_t len = strlen(ret) + 1; check(len); mposition += len; return ret; }
+
+ };
+
+}
+
diff --git a/xbmc/commons/CMakeLists.txt b/xbmc/commons/CMakeLists.txt
new file mode 100644
index 0000000..ff6245d
--- /dev/null
+++ b/xbmc/commons/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(SOURCES Exception.cpp)
+
+set(HEADERS Buffer.h
+ Exception.h
+ ilog.h)
+
+core_add_library(commons)
diff --git a/xbmc/commons/Exception.cpp b/xbmc/commons/Exception.cpp
new file mode 100644
index 0000000..b9bd2e5
--- /dev/null
+++ b/xbmc/commons/Exception.cpp
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Exception.h"
+
+#include "utils/log.h"
+
+namespace XbmcCommons
+{
+ Exception::~Exception() = default;
+
+ void Exception::LogThrowMessage(const char* prefix) const
+ {
+ CLog::Log(LOGERROR, "EXCEPTION Thrown ({}) : {}", classname, message);
+ }
+}
+
diff --git a/xbmc/commons/Exception.h b/xbmc/commons/Exception.h
new file mode 100644
index 0000000..ea2c9bc
--- /dev/null
+++ b/xbmc/commons/Exception.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+//---------------------------------------------------------
+// This include should be moved to commons but even as it is,
+// it wont cause a linker circular dependency since it's just
+// a header.
+#include "utils/StringUtils.h"
+//---------------------------------------------------------
+#include <stdarg.h>
+
+
+#ifdef __GNUC__
+// The 'this' pointer counts as a parameter on member methods.
+#define XBMCCOMMONS_ATTRIB_EXCEPTION_FORMAT __attribute__((format(printf,2,3)))
+#else
+#define XBMCCOMMONS_ATTRIB_EXCEPTION_FORMAT
+#endif
+
+#define XBMCCOMMONS_COPYVARARGS(fmt) va_list argList; va_start(argList, fmt); Set(fmt, argList); va_end(argList)
+#define XBMCCOMMONS_STANDARD_EXCEPTION(E) \
+ class E : public XbmcCommons::Exception \
+ { \
+ public: \
+ inline E(const char* message,...) XBMCCOMMONS_ATTRIB_EXCEPTION_FORMAT : Exception(#E) { XBMCCOMMONS_COPYVARARGS(message); } \
+ \
+ inline E(const E& other) : Exception(other) {} \
+ }
+
+namespace XbmcCommons
+{
+ /**
+ * This class a superclass for exceptions that want to utilize some
+ * utility functionality including autologging with the specific
+ * exception name.
+ */
+ class Exception
+ {
+ private:
+
+ std::string classname;
+ std::string message;
+
+ protected:
+
+ inline explicit Exception(const char* classname_) : classname(classname_) { }
+ inline Exception(const char* classname_, const char* message_) : classname(classname_), message(message_) { }
+ inline Exception(const Exception& other) = default;
+
+ /**
+ * This method is called from the constructor of subclasses. It
+ * will set the message from varargs as well as call log message
+ */
+ inline void Set(const char* fmt, va_list& argList)
+ {
+ message = StringUtils::FormatV(fmt, argList);
+ }
+
+ /**
+ * This message can be called from the constructor of subclasses.
+ * It will set the message and log the throwing.
+ */
+ inline void SetMessage(const char* fmt, ...) XBMCCOMMONS_ATTRIB_EXCEPTION_FORMAT
+ {
+ // calls 'set'
+ XBMCCOMMONS_COPYVARARGS(fmt);
+ }
+
+ inline void setClassname(const char* cn) { classname = cn; }
+
+ public:
+ virtual ~Exception();
+
+ virtual void LogThrowMessage(const char* prefix = NULL) const;
+
+ inline virtual const char* GetExMessage() const { return message.c_str(); }
+ };
+
+ /**
+ * This class forms the base class for unchecked exceptions. Unchecked exceptions
+ * are those that really shouldn't be handled explicitly. For example, on windows
+ * when a access violation is converted to a win32_exception, there's nothing
+ * that can be done in most code. The outer most stack frame might try to
+ * do some error logging prior to shutting down, but that's really it.
+ */
+ XBMCCOMMONS_STANDARD_EXCEPTION(UncheckedException);
+
+/**
+ * In cases where you catch(...){} you will (may) inadvertently be
+ * catching UncheckedException's. Therefore this macro will allow
+ * you to do something equivalent to:
+ * catch (anything except UncheckedException) {}
+ *
+ * In order to avoid catching UncheckedException, use the macro as follows:
+ *
+ * try { ... }
+ * XBMCCOMMONS_HANDLE_UNCHECKED
+ * catch(...){ ... }
+ */
+// Yes. I recognize that the name of this macro is an oxymoron.
+#define XBMCCOMMONS_HANDLE_UNCHECKED \
+ catch (const XbmcCommons::UncheckedException& ) { throw; } \
+ catch (const XbmcCommons::UncheckedException* ) { throw; }
+
+}
+
diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h
new file mode 100644
index 0000000..10b3880
--- /dev/null
+++ b/xbmc/commons/ilog.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#define LOG_LEVEL_NONE -1 // nothing at all is logged
+#define LOG_LEVEL_NORMAL 0 // shows notice, error, severe and fatal
+#define LOG_LEVEL_DEBUG 1 // shows all
+#define LOG_LEVEL_DEBUG_FREEMEM 2 // shows all + shows freemem on screen
+#define LOG_LEVEL_MAX LOG_LEVEL_DEBUG_FREEMEM
+
+// ones we use in the code
+#define LOGDEBUG 0
+#define LOGINFO 1
+#define LOGWARNING 2
+#define LOGERROR 3
+#define LOGFATAL 4
+#define LOGNONE 5
+
+// extra masks - from bit 5
+#define LOGMASKBIT 5
+#define LOGMASK ((1 << LOGMASKBIT) - 1)
+
+#define LOGSAMBA (1 << (LOGMASKBIT + 0))
+#define LOGCURL (1 << (LOGMASKBIT + 1))
+#define LOGFFMPEG (1 << (LOGMASKBIT + 2))
+#define LOGDBUS (1 << (LOGMASKBIT + 4))
+#define LOGJSONRPC (1 << (LOGMASKBIT + 5))
+#define LOGAUDIO (1 << (LOGMASKBIT + 6))
+#define LOGAIRTUNES (1 << (LOGMASKBIT + 7))
+#define LOGUPNP (1 << (LOGMASKBIT + 8))
+#define LOGCEC (1 << (LOGMASKBIT + 9))
+#define LOGVIDEO (1 << (LOGMASKBIT + 10))
+#define LOGWEBSERVER (1 << (LOGMASKBIT + 11))
+#define LOGDATABASE (1 << (LOGMASKBIT + 12))
+#define LOGAVTIMING (1 << (LOGMASKBIT + 13))
+#define LOGWINDOWING (1 << (LOGMASKBIT + 14))
+#define LOGPVR (1 << (LOGMASKBIT + 15))
+#define LOGEPG (1 << (LOGMASKBIT + 16))
+#define LOGANNOUNCE (1 << (LOGMASKBIT + 17))
+#define LOGWSDISCOVERY (1 << (LOGMASKBIT + 18))