diff --git a/addons/pvr.mythtv/addon/addon.xml.in b/addons/pvr.mythtv/addon/addon.xml.in index e77e2f578..24d91788e 100644 --- a/addons/pvr.mythtv/addon/addon.xml.in +++ b/addons/pvr.mythtv/addon/addon.xml.in @@ -1,7 +1,7 @@ diff --git a/addons/pvr.mythtv/addon/changelog.txt b/addons/pvr.mythtv/addon/changelog.txt index 40a3d0d99..7d07fc673 100644 --- a/addons/pvr.mythtv/addon/changelog.txt +++ b/addons/pvr.mythtv/addon/changelog.txt @@ -1,4 +1,14 @@ -v1.9.29 +v1.10.1 +- Options to disable channel icons and recordings or fanart images + +v1.10.0 +- jansson 2.7: fix compilation on ios8/arm64 +- Cleaned cache by max age +- Improves loading of channels and recordings +- Adding WS API Security Pin parameter +- Adding episode info (subtitle) to EPG title + +v1.29.0 - fixed resource leak on file cache failure v1.9.28 diff --git a/addons/pvr.mythtv/addon/resources/channel.png b/addons/pvr.mythtv/addon/resources/channel.png new file mode 100644 index 000000000..f3968f91f Binary files /dev/null and b/addons/pvr.mythtv/addon/resources/channel.png differ diff --git a/addons/pvr.mythtv/addon/resources/language/English/strings.po b/addons/pvr.mythtv/addon/resources/language/English/strings.po index b2946fff0..0e1413abe 100644 --- a/addons/pvr.mythtv/addon/resources/language/English/strings.po +++ b/addons/pvr.mythtv/addon/resources/language/English/strings.po @@ -73,7 +73,11 @@ msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "" -#empty strings from id 30014 to 30018 +msgctxt "#30014" +msgid "MythTV Security Pin for API services" +msgstr "" + +#empty strings from id 30015 to 30018 msgctxt "#30019" msgid "General" @@ -189,7 +193,15 @@ msgctxt "#30062" msgid "Block backend shutdown" msgstr "" -#empty strings from id 30063 to 30099 +msgctxt "#30063" +msgid "Enable channel icons" +msgstr "" + +msgctxt "#30064" +msgid "Enable recording fanart/thumbnails" +msgstr "" + +#empty strings from id 30065 to 30099 # Systeminformation labels msgctxt "#30100" diff --git a/addons/pvr.mythtv/addon/resources/language/French (Canada)/strings.po b/addons/pvr.mythtv/addon/resources/language/French (Canada)/strings.po index fb8d66c60..f65215518 100644 --- a/addons/pvr.mythtv/addon/resources/language/French (Canada)/strings.po +++ b/addons/pvr.mythtv/addon/resources/language/French (Canada)/strings.po @@ -72,6 +72,10 @@ msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port du dorsal MythTV pour les services API" +msgctxt "#30014" +msgid "MythTV Security Pin for API services" +msgstr "Code PIN de sécurité pour les services API" + msgctxt "#30019" msgid "General" msgstr "Général" diff --git a/addons/pvr.mythtv/addon/resources/language/French/strings.po b/addons/pvr.mythtv/addon/resources/language/French/strings.po index 4c6993d70..484763f0b 100644 --- a/addons/pvr.mythtv/addon/resources/language/French/strings.po +++ b/addons/pvr.mythtv/addon/resources/language/French/strings.po @@ -72,6 +72,10 @@ msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port du serveur MythTV pour les services API" +msgctxt "#30014" +msgid "MythTV Security Pin for API services" +msgstr "Code PIN de sécurité pour les services API" + msgctxt "#30019" msgid "General" msgstr "Général" @@ -180,6 +184,14 @@ msgctxt "#30062" msgid "Block backend shutdown" msgstr "Bloquer l'arrêt du serveur" +msgctxt "#30063" +msgid "Enable channel icons" +msgstr "Afficher l'icône des chaînes" + +msgctxt "#30064" +msgid "Enable recording fanart/thumbnails" +msgstr "Afficher la vignette des enregistrements" + msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Version du protocole: %i - Version de la base de données: %i" diff --git a/addons/pvr.mythtv/addon/resources/recording.png b/addons/pvr.mythtv/addon/resources/recording.png new file mode 100644 index 000000000..49233317e Binary files /dev/null and b/addons/pvr.mythtv/addon/resources/recording.png differ diff --git a/addons/pvr.mythtv/addon/resources/settings.xml b/addons/pvr.mythtv/addon/resources/settings.xml index 6da293b14..425fdc381 100644 --- a/addons/pvr.mythtv/addon/resources/settings.xml +++ b/addons/pvr.mythtv/addon/resources/settings.xml @@ -4,6 +4,7 @@ + @@ -29,5 +30,7 @@ + + diff --git a/addons/pvr.mythtv/src/avinfo.cpp b/addons/pvr.mythtv/src/avinfo.cpp index cb8611f8a..b387d22e3 100644 --- a/addons/pvr.mythtv/src/avinfo.cpp +++ b/addons/pvr.mythtv/src/avinfo.cpp @@ -20,7 +20,7 @@ * */ -#include "xbmc_codec_types.h" +#include #include "avinfo.h" #include "client.h" diff --git a/addons/pvr.mythtv/src/client.cpp b/addons/pvr.mythtv/src/client.cpp index 8e4032e50..cbef59a5b 100644 --- a/addons/pvr.mythtv/src/client.cpp +++ b/addons/pvr.mythtv/src/client.cpp @@ -35,10 +35,13 @@ std::string g_szMythHostname = DEFAULT_HOST; ///< std::string g_szMythHostEther = ""; ///< The Host MAC address of the mythtv server int g_iProtoPort = DEFAULT_PROTO_PORT; ///< The mythtv protocol port (default is 6543) int g_iWSApiPort = DEFAULT_WSAPI_PORT; ///< The mythtv sevice API port (default is 6544) +std::string g_szWSSecurityPin = DEFAULT_WSAPI_SECURITY_PIN; ///< The default security pin for the mythtv wsapi bool g_bExtraDebug = DEFAULT_EXTRA_DEBUG; ///< Output extensive debug information to the log bool g_bLiveTV = DEFAULT_LIVETV; ///< LiveTV support (or recordings only) bool g_bLiveTVPriority = DEFAULT_LIVETV_PRIORITY; ///< MythTV Backend setting to allow live TV to move scheduled shows int g_iLiveTVConflictStrategy = DEFAULT_LIVETV_CONFLICT_STRATEGY; ///< Conflict resolving strategy (0= +bool g_bChannelIcons = DEFAULT_CHANNEL_ICONS; ///< Load Channel Icons +bool g_bRecordingIcons = DEFAULT_RECORDING_ICONS; ///< Load Recording Icons (Fanart/Thumbnails) int g_iRecTemplateType = DEFAULT_RECORD_TEMPLATE; ///< Template type for new record (0=Internal, 1=MythTV) bool g_bRecAutoMetadata = true; bool g_bRecAutoCommFlag = false; @@ -170,6 +173,17 @@ ADDON_STATUS ADDON_Create(void *hdl, void *props) g_iWSApiPort = DEFAULT_WSAPI_PORT; } + /* Read setting "wssecuritypin" from settings.xml */ + if (XBMC->GetSetting("wssecuritypin", buffer)) + g_szWSSecurityPin = buffer; + else + { + /* If setting is unknown fallback to defaults */ + XBMC->Log(LOG_ERROR, "Couldn't get 'wssecuritypin' setting, falling back to '%s' as default", DEFAULT_WSAPI_SECURITY_PIN); + g_szWSSecurityPin = DEFAULT_WSAPI_SECURITY_PIN; + } + buffer[0] = 0; + /* Read setting "extradebug" from settings.xml */ if (!XBMC->GetSetting("extradebug", &g_bExtraDebug)) { @@ -271,6 +285,22 @@ ADDON_STATUS ADDON_Create(void *hdl, void *props) g_bBlockMythShutdown = DEFAULT_BLOCK_SHUTDOWN; } + /* Read setting "channel_icons" from settings.xml */ + if (!XBMC->GetSetting("channel_icons", &g_bChannelIcons)) + { + /* If setting is unknown fallback to defaults */ + XBMC->Log(LOG_ERROR, "Couldn't get 'channel_icons' setting, falling back to '%b' as default", DEFAULT_CHANNEL_ICONS); + g_bChannelIcons = DEFAULT_CHANNEL_ICONS; + } + + /* Read setting "recording_icons" from settings.xml */ + if (!XBMC->GetSetting("recording_icons", &g_bRecordingIcons)) + { + /* If setting is unknown fallback to defaults */ + XBMC->Log(LOG_ERROR, "Couldn't get 'recording_icons' setting, falling back to '%b' as default", DEFAULT_RECORDING_ICONS); + g_bRecordingIcons = DEFAULT_RECORDING_ICONS; + } + free (buffer); XBMC->Log(LOG_DEBUG, "Loading settings...done"); @@ -446,12 +476,33 @@ ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) return ADDON_STATUS_NEED_RESTART; } } + else if (str == "wssecuritypin") + { + std::string tmp_sWSSecurityPin; + XBMC->Log(LOG_INFO, "Changed Setting 'wssecuritypin' from %s to %s", g_szWSSecurityPin.c_str(), (const char*)settingValue); + tmp_sWSSecurityPin = g_szWSSecurityPin; + g_szWSSecurityPin = (const char*)settingValue; + if (tmp_sWSSecurityPin != g_szWSSecurityPin) + return ADDON_STATUS_NEED_RESTART; + } else if (str == "demuxing") { XBMC->Log(LOG_INFO, "Changed Setting 'demuxing' from %u to %u", g_bDemuxing, *(bool*)settingValue); if (g_bDemuxing != *(bool*)settingValue) return ADDON_STATUS_NEED_RESTART; } + else if (str == "channel_icons") + { + XBMC->Log(LOG_INFO, "Changed Setting 'channel_icons' from %u to %u", g_bChannelIcons, *(bool*)settingValue); + if (g_bChannelIcons != *(bool*)settingValue) + return ADDON_STATUS_NEED_RESTART; + } + else if (str == "recording_icons") + { + XBMC->Log(LOG_INFO, "Changed Setting 'recording_icons' from %u to %u", g_bRecordingIcons, *(bool*)settingValue); + if (g_bRecordingIcons != *(bool*)settingValue) + return ADDON_STATUS_NEED_RESTART; + } else if (str == "host_ether") { XBMC->Log(LOG_INFO, "Changed Setting 'host_ether' from %s to %s", g_szMythHostEther.c_str(), (const char*)settingValue); diff --git a/addons/pvr.mythtv/src/client.h b/addons/pvr.mythtv/src/client.h index c3e45d347..fb2106cd6 100644 --- a/addons/pvr.mythtv/src/client.h +++ b/addons/pvr.mythtv/src/client.h @@ -41,6 +41,9 @@ #define DEFAULT_LIVETV true #define DEFAULT_PROTO_PORT 6543 #define DEFAULT_WSAPI_PORT 6544 +#define DEFAULT_WSAPI_SECURITY_PIN "0000" +#define DEFAULT_CHANNEL_ICONS true +#define DEFAULT_RECORDING_ICONS true #define DEFAULT_RECORD_TEMPLATE 1 #define SUBTITLE_SEPARATOR " - " @@ -84,10 +87,13 @@ extern std::string g_szMythHostname; ///< The Host name or IP of the extern std::string g_szMythHostEther; ///< The Host MAC address of the mythtv server extern int g_iProtoPort; ///< The mythtv protocol port (default is 6543) extern int g_iWSApiPort; ///< The mythtv service API port (default is 6544) +extern std::string g_szWSSecurityPin; ///< The default security pin for the mythtv wsapi extern bool g_bExtraDebug; ///< Debug logging extern bool g_bLiveTV; ///< LiveTV support (or recordings only) extern bool g_bLiveTVPriority; ///< MythTV Backend setting to allow live TV to move scheduled shows extern int g_iLiveTVConflictStrategy; ///< Live TV conflict resolving strategy (0=Has later, 1=Stop TV, 2=Cancel recording) +extern bool g_bChannelIcons; ///< Load Channel Icons +extern bool g_bRecordingIcons; ///< Load Recording Icons (Fanart/Thumbnails) extern int g_iRecTemplateType; ///< Template type for new record (0=Internal, 1=MythTV) ///* Internal Record template */ extern bool g_bRecAutoMetadata; diff --git a/addons/pvr.mythtv/src/cppmyth/MythScheduleManager.cpp b/addons/pvr.mythtv/src/cppmyth/MythScheduleManager.cpp index 645a092e5..73cd8aaa7 100644 --- a/addons/pvr.mythtv/src/cppmyth/MythScheduleManager.cpp +++ b/addons/pvr.mythtv/src/cppmyth/MythScheduleManager.cpp @@ -105,14 +105,14 @@ bool MythRecordingRuleNode::IsInactiveRule() const //// MythScheduleManager //// -MythScheduleManager::MythScheduleManager(const std::string& server, unsigned protoPort, unsigned wsapiPort) +MythScheduleManager::MythScheduleManager(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin) : m_lock() , m_control(NULL) , m_protoVersion(0) , m_versionHelper(NULL) , m_showNotRecording(false) { - m_control = new Myth::Control(server, protoPort, wsapiPort); + m_control = new Myth::Control(server, protoPort, wsapiPort, wsapiSecurityPin); this->Update(); } @@ -140,7 +140,7 @@ void MythScheduleManager::Setup() } } -uint32_t MythScheduleManager::MakeIndex(ScheduledPtr scheduled) const +uint32_t MythScheduleManager::MakeIndex(const ScheduledPtr &scheduled) const { // Recordings must keep same identifier even after refreshing cache (cf Update). // Numeric hash of UID is used to make the constant numeric identifier. diff --git a/addons/pvr.mythtv/src/cppmyth/MythScheduleManager.h b/addons/pvr.mythtv/src/cppmyth/MythScheduleManager.h index 12bdbeed1..dffa78b13 100644 --- a/addons/pvr.mythtv/src/cppmyth/MythScheduleManager.h +++ b/addons/pvr.mythtv/src/cppmyth/MythScheduleManager.h @@ -78,7 +78,7 @@ class MythScheduleManager MSM_ERROR_SUCCESS = 1 }; - MythScheduleManager(const std::string& server, unsigned protoPort, unsigned wsapiPort); + MythScheduleManager(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin); ~MythScheduleManager(); // Called by GetTimers @@ -139,7 +139,7 @@ class MythScheduleManager VersionHelper *m_versionHelper; void Setup(); - uint32_t MakeIndex(ScheduledPtr scheduled) const; + uint32_t MakeIndex(const ScheduledPtr &scheduled) const; // The list of rule nodes typedef std::list NodeList; diff --git a/addons/pvr.mythtv/src/demux.cpp b/addons/pvr.mythtv/src/demux.cpp index 1beb8c2bc..f0e80d059 100644 --- a/addons/pvr.mythtv/src/demux.cpp +++ b/addons/pvr.mythtv/src/demux.cpp @@ -20,10 +20,10 @@ * */ -#include "platform/os.h" +#include -#include "libXBMC_pvr.h" -#include "xbmc_codec_types.h" +#include +#include #include "demux.h" #include "client.h" diff --git a/addons/pvr.mythtv/src/demuxer/tsDemuxer.h b/addons/pvr.mythtv/src/demuxer/tsDemuxer.h index 0c06f05a8..5be959bbe 100644 --- a/addons/pvr.mythtv/src/demuxer/tsDemuxer.h +++ b/addons/pvr.mythtv/src/demuxer/tsDemuxer.h @@ -25,7 +25,7 @@ #include "common.h" #include "tsPacket.h" #include "elementaryStream.h" -#include "platform/threads/mutex.h" +#include #include #include diff --git a/addons/pvr.mythtv/src/fileOps.cpp b/addons/pvr.mythtv/src/fileOps.cpp index 32bf86276..5c4488318 100644 --- a/addons/pvr.mythtv/src/fileOps.cpp +++ b/addons/pvr.mythtv/src/fileOps.cpp @@ -27,31 +27,35 @@ #include #include -#define FILEOPS_STREAM_BUFFER_SIZE 32000 // Buffer size to download artworks +#define FILEOPS_STREAM_BUFFER_SIZE 32000 // Buffer size to download artworks +#define FILEOPS_STAMP_FILENAME "stamp" // Base name for cache stamp file +#define FILEOPS_NOSTAMP (time_t)(-1) +#define FILEOPS_CHANNEL_DUMMY_ICON "channel.png" +#define FILEOPS_RECORDING_DUMMY_ICON "recording.png" using namespace ADDON; using namespace PLATFORM; -FileOps::FileOps(const std::string& server, unsigned wsapiport) +FileOps::FileOps(FileConsumer *consumer, const std::string& server, unsigned wsapiport, const std::string& wsapiSecurityPin) : CThread() +, m_consumer(consumer) , m_wsapi(NULL) , m_localBasePath(g_szUserPath.c_str()) +, m_localBaseStampName() +, m_localBaseStamp(FILEOPS_NOSTAMP) , m_queueContent() , m_jobQueue() { - m_localBasePath = m_localBasePath + "cache" + PATH_SEPARATOR_CHAR; - - // Create the cache directories if it does not exist - if (!XBMC->DirectoryExists(m_localBasePath.c_str()) && !XBMC->CreateDirectory(m_localBasePath.c_str())) - XBMC->Log(LOG_ERROR,"%s - Failed to create cache directory %s", __FUNCTION__, m_localBasePath.c_str()); - - m_wsapi = new Myth::WSAPI(server, wsapiport); + // Initialize base path for cache directories + m_localBasePath.append("cache").append(PATH_SEPARATOR_STRING); + m_localBaseStampName.append(m_localBasePath).append(FILEOPS_STAMP_FILENAME); + InitBasePath(); + m_wsapi = new Myth::WSAPI(server, wsapiport, wsapiSecurityPin); CreateThread(); } FileOps::~FileOps() { - CleanCache(); StopThread(-1); // Set stopping. don't wait as we need to signal the thread first m_queueContent.Signal(); StopThread(); // Wait for thread to stop @@ -62,6 +66,8 @@ std::string FileOps::GetChannelIconPath(const MythChannel& channel) { if (channel.IsNull() || channel.Icon().empty()) return ""; + if (!g_bChannelIcons) + return g_szClientPath + PATH_SEPARATOR_STRING + "resources" + PATH_SEPARATOR_STRING + FILEOPS_CHANNEL_DUMMY_ICON; std::string uid = Myth::IdToString(channel.ID()); if (g_bExtraDebug) @@ -92,6 +98,8 @@ std::string FileOps::GetPreviewIconPath(const MythProgramInfo& recording) { if (recording.IsNull()) return ""; + if (!g_bRecordingIcons) + return g_szClientPath + PATH_SEPARATOR_STRING + "resources" + PATH_SEPARATOR_STRING + FILEOPS_RECORDING_DUMMY_ICON; std::string uid = recording.UID(); if (g_bExtraDebug) @@ -122,6 +130,15 @@ std::string FileOps::GetArtworkPath(const MythProgramInfo& recording, FileType t { if (recording.IsNull()) return ""; + if (!g_bRecordingIcons) + switch (type) + { + case FileTypePreview: + case FileTypeCoverart: + return g_szClientPath + PATH_SEPARATOR_STRING + "resources" + PATH_SEPARATOR_STRING + FILEOPS_RECORDING_DUMMY_ICON; + default: + return ""; + } std::string uid = recording.UID(); if (g_bExtraDebug) @@ -184,6 +201,16 @@ void *FileOps::Process() // For caching new files, the tread is woken up by m_queueContent.Signal(); m_queueContent.Wait(c_timeoutProcess * 1000); + if (m_jobQueue.empty() && !IsStopped()) + { + if (m_localBaseStamp != FILEOPS_NOSTAMP && difftime(time(NULL), m_localBaseStamp) >= c_cacheMaxAge) + { + CleanCache(); + if (m_consumer) + m_consumer->HandleCleanedCache(); + } + } + while (!m_jobQueue.empty() && !IsStopped()) { CLockObject lock(m_lock); @@ -342,6 +369,70 @@ bool FileOps::CacheFile(void *file, Myth::Stream *source) return true; } +static void WriteCacheStamp(const char *path, time_t ts) +{ + void * hdl = XBMC->OpenFileForWrite(path, true); + if (hdl == NULL) + { + XBMC->Log(LOG_ERROR,"%s: Write stamp file %s failed", __FUNCTION__, path); + return; + } + std::string now(Myth::TimeToString(ts, true)); + XBMC->WriteFile(hdl, now.c_str(), now.length()); + XBMC->CloseFile(hdl); +} + +static time_t ReadCacheStamp(const char *path) +{ + time_t ts = FILEOPS_NOSTAMP; + char buf[21]; // Time string as ISO-8601/UTC: %y-%m-%d"T"%H:%M:%S"Z" + memset(buf, 0, sizeof(buf)); + void * hdl = XBMC->OpenFile(path, 0); + if (hdl == NULL) + { + XBMC->Log(LOG_ERROR,"%s: Read stamp file %s failed", __FUNCTION__, path); + // Try write a new one + ts = time(NULL); + WriteCacheStamp(path, ts); + return ts; + } + if (XBMC->ReadFile(hdl, (void*)buf, (int64_t)(sizeof(buf) - 1))) + ts = Myth::StringToTime(buf); // It returns FILEOPS_NOSTAMP for invalid buf + XBMC->CloseFile(hdl); + // If stamp is invalid we overwrite it + if (ts == FILEOPS_NOSTAMP) + { + XBMC->Log(LOG_ERROR,"%s: Bad stamp string '%s'", __FUNCTION__, buf); + ts = time(NULL); + WriteCacheStamp(path, ts); + } + return ts; +} + +void FileOps::InitBasePath() +{ + XBMC->Log(LOG_DEBUG, "%s: Configure cache directory %s", __FUNCTION__, m_localBasePath.c_str()); + + CLockObject lock(m_lock); + + // Create the cache directories if it does not exist + if (!XBMC->DirectoryExists(m_localBasePath.c_str()) && !XBMC->CreateDirectory(m_localBasePath.c_str())) + { + XBMC->Log(LOG_ERROR,"%s: Failed to create cache directory %s", __FUNCTION__, m_localBasePath.c_str()); + return; + } + if (!XBMC->FileExists(m_localBaseStampName.c_str(), false)) + { + m_localBaseStamp = time(NULL); + WriteCacheStamp(m_localBaseStampName.c_str(), m_localBaseStamp); + return; + } + m_localBaseStamp = ReadCacheStamp(m_localBaseStampName.c_str()); + XBMC->Log(LOG_DEBUG,"%s: Cache stamp is %s", __FUNCTION__, ctime(&m_localBaseStamp)); + if (difftime(time(NULL), m_localBaseStamp) >= c_cacheMaxAge) + CleanCache(); +} + void FileOps::CleanCache() { // Currently XBMC's addon lib doesn't provide a way to list files in a directory. @@ -375,7 +466,10 @@ void FileOps::CleanCache() m_preview.clear(); m_artworks.clear(); - XBMC->Log(LOG_DEBUG, "%s: Cleaned cache %s", __FUNCTION__, m_localBasePath.c_str()); + // Reset stamp file + m_localBaseStamp = time(NULL); + WriteCacheStamp(m_localBaseStampName.c_str(), m_localBaseStamp); + XBMC->Log(LOG_DEBUG, "%s: New cache stamp is %s", __FUNCTION__, ctime(&m_localBaseStamp)); } std::string FileOps::GetFileName(const std::string& path, char separator) diff --git a/addons/pvr.mythtv/src/fileOps.h b/addons/pvr.mythtv/src/fileOps.h index 00e0c0075..9fe83d4cb 100644 --- a/addons/pvr.mythtv/src/fileOps.h +++ b/addons/pvr.mythtv/src/fileOps.h @@ -32,6 +32,13 @@ #include #include +class FileConsumer +{ +public: + virtual ~FileConsumer() {}; + virtual void HandleCleanedCache() = 0; +}; + class FileOps : public PLATFORM::CThread { public: @@ -86,8 +93,9 @@ class FileOps : public PLATFORM::CThread static const int c_timeoutProcess = 10; // Wake the thread every 10s static const int c_maximumAttemptsOnReadError = 3; // Retry when reading file failed + static const int c_cacheMaxAge = 2635200; // Clean cache every 2635200s (30.5 days) - FileOps(const std::string& server, unsigned wsapiport); + FileOps(FileConsumer *consumer, const std::string& server, unsigned wsapiport, const std::string& wsapiSecurityPin); virtual ~FileOps(); std::string GetChannelIconPath(const MythChannel& channel); @@ -103,6 +111,7 @@ class FileOps : public PLATFORM::CThread bool CheckFile(const std::string &localFilename); void *OpenFile(const std::string &localFilename); bool CacheFile(void *file, Myth::Stream *source); + void InitBasePath(); void CleanCache(); static std::string GetFileName(const std::string& path, char separator = PATH_SEPARATOR_CHAR); @@ -112,8 +121,11 @@ class FileOps : public PLATFORM::CThread std::map m_preview; std::map, std::string> m_artworks; + FileConsumer *m_consumer; Myth::WSAPI *m_wsapi; std::string m_localBasePath; + std::string m_localBaseStampName; + time_t m_localBaseStamp; struct JobItem { JobItem(const std::string& localFilename, FileType type, const MythProgramInfo& recording) diff --git a/addons/pvr.mythtv/src/pvrclient-mythtv.cpp b/addons/pvr.mythtv/src/pvrclient-mythtv.cpp index 520e33a3d..4fed404a2 100644 --- a/addons/pvr.mythtv/src/pvrclient-mythtv.cpp +++ b/addons/pvr.mythtv/src/pvrclient-mythtv.cpp @@ -42,8 +42,6 @@ PVRClientMythTV::PVRClientMythTV() , m_powerSaving(false) , m_fileOps(NULL) , m_scheduleManager(NULL) -, m_categories() -, m_channelGroups() , m_demux(NULL) , m_recordingChangePinCount(0) { @@ -102,7 +100,7 @@ void PVRClientMythTV::SetDebug() bool PVRClientMythTV::Connect() { SetDebug(); - m_control = new Myth::Control(g_szMythHostname, g_iProtoPort, g_iWSApiPort, g_bBlockMythShutdown); + m_control = new Myth::Control(g_szMythHostname, g_iProtoPort, g_iWSApiPort, g_szWSSecurityPin, g_bBlockMythShutdown); if (!m_control->IsOpen()) { SAFE_DELETE(m_control); @@ -115,7 +113,7 @@ bool PVRClientMythTV::Connect() if (!m_control->CheckService()) { SAFE_DELETE(m_control); - XBMC->Log(LOG_ERROR,"Failed to connect to MythTV backend on %s:%d", g_szMythHostname.c_str(), g_iWSApiPort); + XBMC->Log(LOG_ERROR,"Failed to connect to MythTV backend on %s:%d with pin %s", g_szMythHostname.c_str(), g_iWSApiPort, g_szWSSecurityPin.c_str()); return false; } @@ -129,10 +127,10 @@ bool PVRClientMythTV::Connect() m_eventHandler->SubscribeForEvent(m_eventSubscriberId, Myth::EVENT_RECORDING_LIST_CHANGE); // Create schedule manager - m_scheduleManager = new MythScheduleManager(g_szMythHostname, g_iProtoPort, g_iWSApiPort); + m_scheduleManager = new MythScheduleManager(g_szMythHostname, g_iProtoPort, g_iWSApiPort, g_szWSSecurityPin); // Create file operation helper (image caching) - m_fileOps = new FileOps(g_szMythHostname, g_iWSApiPort); + m_fileOps = new FileOps(this, g_szMythHostname, g_iWSApiPort, g_szWSSecurityPin); // Start event handler m_eventHandler->Start(); @@ -257,6 +255,7 @@ void PVRClientMythTV::HandleBackendMessage(const Myth::EventMessage& msg) XBMC->QueueNotification(QUEUE_INFO, XBMC->GetLocalizedString(30303)); // Connection to MythTV restored } // Refreshing all + HandleChannelChange(); HandleScheduleChange(); HandleRecordingListChange(Myth::EventMessage()); } @@ -272,6 +271,13 @@ void PVRClientMythTV::HandleBackendMessage(const Myth::EventMessage& msg) } } +void PVRClientMythTV::HandleChannelChange() +{ + FillChannelsAndChannelGroups(); + PVR->TriggerChannelUpdate(); + PVR->TriggerChannelGroupsUpdate(); +} + void PVRClientMythTV::HandleScheduleChange() { if (!m_scheduleManager) @@ -416,6 +422,11 @@ void PVRClientMythTV::RunHouseKeeping() } } +void PVRClientMythTV::HandleCleanedCache() +{ + PVR->TriggerRecordingUpdate(); +} + PVR_ERROR PVRClientMythTV::GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) { if (g_bExtraDebug) @@ -438,7 +449,8 @@ PVR_ERROR PVRClientMythTV::GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANN // EPG_TAG expects strings as char* and not as copies (like the other PVR types). // Therefore we have to make sure that we don't pass invalid (freed) memory to TransferEpgEntry. // In particular we have to use local variables and must not pass returned string values directly. - tag.strTitle = it->second->title.c_str(); + std::string epgTitle = MakeProgramTitle(it->second->title, it->second->subTitle); + tag.strTitle = epgTitle.c_str(); tag.strPlot = it->second->description.c_str(); tag.strGenreDescription = it->second->category.c_str(); tag.iUniqueBroadcastId = MakeBroadcastID(it->second->channel.chanId, it->first); @@ -472,9 +484,8 @@ int PVRClientMythTV::GetNumChannels() if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, "%s", __FUNCTION__); - LoadChannelsAndChannelGroups(); - - return m_channelsById.size(); + CLockObject lock(m_channelsLock); + return m_PVRChannels.size(); } PVR_ERROR PVRClientMythTV::GetChannels(ADDON_HANDLE handle, bool bRadio) @@ -482,50 +493,39 @@ PVR_ERROR PVRClientMythTV::GetChannels(ADDON_HANDLE handle, bool bRadio) if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, "%s: radio: %s", __FUNCTION__, (bRadio ? "true" : "false")); - LoadChannelsAndChannelGroups(); - m_PVRChannelUidById.clear(); - - // Create a map<(sourceid, channum, callsign), chanid> to merge channels with same channum and callsign within same group - std::map >, unsigned int> channelIdentifiers; + CLockObject lock(m_channelsLock); + // Load channels list + if (m_PVRChannels.empty()) + FillChannelsAndChannelGroups(); // Transfer channels of the requested type (radio / tv) - for (ChannelIdMap::iterator it = m_channelsById.begin(); it != m_channelsById.end(); ++it) + for (PVRChannelList::const_iterator it = m_PVRChannels.begin(); it != m_PVRChannels.end(); ++it) { - if (it->second.IsRadio() == bRadio && !it->second.IsNull()) + if (it->bIsRadio == bRadio) { - // Skip channels with same channum and callsign - std::pair > channelIdentifier = std::make_pair(it->second.SourceID(), std::make_pair(it->second.Number(), it->second.Callsign())); - std::map >, unsigned int>::iterator itm = channelIdentifiers.find(channelIdentifier); - if (itm != channelIdentifiers.end()) + ChannelIdMap::const_iterator itm = m_channelsById.find(it->iUniqueId); + if (itm != m_channelsById.end() && !itm->second.IsNull()) { - XBMC->Log(LOG_DEBUG, "%s: skipping channel: %d", __FUNCTION__, it->second.ID()); - // Map channel with merged channel - m_PVRChannelUidById.insert(std::make_pair(it->first, itm->second)); - continue; - } - channelIdentifiers.insert(std::make_pair(channelIdentifier, it->first)); - // Map channel to itself - m_PVRChannelUidById.insert(std::make_pair(it->first, it->first)); + PVR_CHANNEL tag; + memset(&tag, 0, sizeof(PVR_CHANNEL)); - PVR_CHANNEL tag; - memset(&tag, 0, sizeof(PVR_CHANNEL)); + tag.iUniqueId = itm->first; + tag.iChannelNumber = itm->second.NumberMajor(); + tag.iSubChannelNumber = itm->second.NumberMinor(); + PVR_STRCPY(tag.strChannelName, itm->second.Name().c_str()); + tag.bIsHidden = !itm->second.Visible(); + tag.bIsRadio = itm->second.IsRadio(); - tag.iUniqueId = it->first; - tag.iChannelNumber = it->second.NumberMajor(); - tag.iSubChannelNumber = it->second.NumberMinor(); - PVR_STRCPY(tag.strChannelName, it->second.Name().c_str()); - tag.bIsHidden = !it->second.Visible(); - tag.bIsRadio = it->second.IsRadio(); + std::string icon = m_fileOps->GetChannelIconPath(itm->second); + PVR_STRCPY(tag.strIconPath, icon.c_str()); - std::string icon = m_fileOps->GetChannelIconPath(it->second); - PVR_STRCPY(tag.strIconPath, icon.c_str()); + // Unimplemented + PVR_STRCPY(tag.strStreamURL, ""); + PVR_STRCPY(tag.strInputFormat, ""); + tag.iEncryptionSystem = 0; - // Unimplemented - PVR_STRCPY(tag.strStreamURL, ""); - PVR_STRCPY(tag.strInputFormat, ""); - tag.iEncryptionSystem = 0; - - PVR->TransferChannelEntry(handle, &tag); + PVR->TransferChannelEntry(handle, &tag); + } } } @@ -540,9 +540,8 @@ int PVRClientMythTV::GetChannelGroupsAmount() if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, "%s", __FUNCTION__); - LoadChannelsAndChannelGroups(); - - return m_channelGroups.size(); + CLockObject lock(m_channelsLock); + return m_PVRChannelGroups.size(); } PVR_ERROR PVRClientMythTV::GetChannelGroups(ADDON_HANDLE handle, bool bRadio) @@ -550,22 +549,21 @@ PVR_ERROR PVRClientMythTV::GetChannelGroups(ADDON_HANDLE handle, bool bRadio) if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, "%s: radio: %s", __FUNCTION__, (bRadio ? "true" : "false")); - LoadChannelsAndChannelGroups(); + CLockObject lock(m_channelsLock); // Transfer channel groups of the given type (radio / tv) - for (ChannelGroupMap::iterator channelGroupsIt = m_channelGroups.begin(); channelGroupsIt != m_channelGroups.end(); ++channelGroupsIt) + for (PVRChannelGroupMap::iterator itg = m_PVRChannelGroups.begin(); itg != m_PVRChannelGroups.end(); ++itg) { PVR_CHANNEL_GROUP tag; memset(&tag, 0, sizeof(PVR_CHANNEL_GROUP)); - PVR_STRCPY(tag.strGroupName, channelGroupsIt->first.c_str()); + PVR_STRCPY(tag.strGroupName, itg->first.c_str()); tag.bIsRadio = bRadio; // Only add the group if we have at least one channel of the correct type - for (std::vector::iterator channelGroupIt = channelGroupsIt->second.begin(); channelGroupIt != channelGroupsIt->second.end(); ++channelGroupIt) + for (PVRChannelList::const_iterator itc = itg->second.begin(); itc != itg->second.end(); ++itc) { - ChannelIdMap::iterator channelIt = m_channelsById.find(*channelGroupIt); - if (channelIt != m_channelsById.end() && channelIt->second.IsRadio() == bRadio) + if (itc->bIsRadio == bRadio) { PVR->TransferChannelGroup(handle, &tag); break; @@ -584,10 +582,10 @@ PVR_ERROR PVRClientMythTV::GetChannelGroupMembers(ADDON_HANDLE handle, const PVR if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, "%s: group: %s", __FUNCTION__, group.strGroupName); - LoadChannelsAndChannelGroups(); + CLockObject lock(m_channelsLock); - ChannelGroupMap::iterator channelGroupsIt = m_channelGroups.find(group.strGroupName); - if (channelGroupsIt == m_channelGroups.end()) + PVRChannelGroupMap::iterator itg = m_PVRChannelGroups.find(group.strGroupName); + if (itg == m_PVRChannelGroups.end()) { XBMC->Log(LOG_ERROR,"%s: Channel group not found", __FUNCTION__); return PVR_ERROR_INVALID_PARAMETERS; @@ -595,16 +593,15 @@ PVR_ERROR PVRClientMythTV::GetChannelGroupMembers(ADDON_HANDLE handle, const PVR // Transfer the channel group members for the requested group unsigned channelNumber = 0; - for (std::vector::iterator channelGroupIt = channelGroupsIt->second.begin(); channelGroupIt != channelGroupsIt->second.end(); ++channelGroupIt) + for (PVRChannelList::const_iterator itc = itg->second.begin(); itc != itg->second.end(); ++itc) { - ChannelIdMap::iterator channelIt = m_channelsById.find(*channelGroupIt); - if (channelIt != m_channelsById.end() && channelIt->second.IsRadio() == group.bIsRadio) + if (itc->bIsRadio == group.bIsRadio) { PVR_CHANNEL_GROUP_MEMBER tag; memset(&tag, 0, sizeof(PVR_CHANNEL_GROUP_MEMBER)); tag.iChannelNumber = ++channelNumber; - tag.iChannelUniqueId = (unsigned)FindPVRChannelUid(channelIt->second.ID()); + tag.iChannelUniqueId = itc->iUniqueId; PVR_STRCPY(tag.strGroupName, group.strGroupName); PVR->TransferChannelGroupMember(handle, &tag); } @@ -616,42 +613,82 @@ PVR_ERROR PVRClientMythTV::GetChannelGroupMembers(ADDON_HANDLE handle, const PVR return PVR_ERROR_NO_ERROR; } -void PVRClientMythTV::LoadChannelsAndChannelGroups() +int PVRClientMythTV::FillChannelsAndChannelGroups() { - if (!m_channelsById.empty()) - return; + int count = 0; + XBMC->Log(LOG_DEBUG, "%s", __FUNCTION__); + + CLockObject lock(m_channelsLock); + m_PVRChannels.clear(); + m_PVRChannelGroups.clear(); + m_PVRChannelUidById.clear(); + m_channelsById.clear(); + + // Create a channels map to merge channels with same channum and callsign within same group + typedef std::pair chanuid_t; + typedef std::map mapuid_t; + mapuid_t channelIdentifiers; // For each source create a channels group Myth::VideoSourceListPtr sources = m_control->GetVideoSourceList(); for (Myth::VideoSourceList::iterator its = sources->begin(); its != sources->end(); ++its) { Myth::ChannelListPtr channels = m_control->GetChannelList((*its)->sourceId); - std::vector channelIDs; + PVRChannelList channelIDs; channelIDs.reserve(channels->size()); + channelIdentifiers.clear(); for (Myth::ChannelList::iterator itc = channels->begin(); itc != channels->end(); ++itc) { MythChannel channel((*itc)); - m_channelsById.insert(std::make_pair(channel.ID(), channel)); - m_channelsByNumber.insert(std::make_pair(channel.Number(), channel)); - channelIDs.push_back(channel.ID()); + PVRChannelItem item; + item.iUniqueId = channel.ID(); + item.bIsRadio = channel.IsRadio(); + m_channelsById.insert(std::make_pair(item.iUniqueId, channel)); + // Skip channels with same channum and callsign within group + chanuid_t channelIdentifier = std::make_pair(channel.Number(), channel.Callsign()); + mapuid_t::iterator itm = channelIdentifiers.find(channelIdentifier); + if (itm != channelIdentifiers.end()) + { + XBMC->Log(LOG_DEBUG, "%s: skipping channel: %d", __FUNCTION__, item.iUniqueId); + // Map channel with merged channel + m_PVRChannelUidById.insert(std::make_pair(item.iUniqueId, itm->second)); + } + else + { + // Add new channel in group + channelIDs.push_back(item); + channelIdentifiers.insert(std::make_pair(channelIdentifier, item.iUniqueId)); + // Map channel to itself + m_PVRChannelUidById.insert(std::make_pair(item.iUniqueId, item.iUniqueId)); + m_PVRChannels.push_back(item); + ++count; + } } - m_channelGroups.insert(std::make_pair((*its)->sourceName, channelIDs)); + m_PVRChannelGroups.insert(std::make_pair((*its)->sourceName, channelIDs)); } + + XBMC->Log(LOG_DEBUG, "%s: Loaded %d channel(s) %d group(s)", __FUNCTION__, count, (unsigned)m_PVRChannelGroups.size()); + return count; +} + +MythChannel PVRClientMythTV::FindChannel(uint32_t channelId) const +{ + CLockObject lock(m_channelsLock); + ChannelIdMap::const_iterator it = m_channelsById.find(channelId); + if (it != m_channelsById.end()) + return it->second; + return MythChannel(); } int PVRClientMythTV::FindPVRChannelUid(uint32_t channelId) const { + CLockObject lock(m_channelsLock); PVRChannelMap::const_iterator it = m_PVRChannelUidById.find(channelId); if (it != m_PVRChannelUidById.end()) return it->second; return -1; // PVR dummy channel UID } -void PVRClientMythTV::UpdateRecordings() -{ - PVR->TriggerRecordingUpdate(); -} - int PVRClientMythTV::GetRecordingsAmount(void) { int res = 0; @@ -660,16 +697,10 @@ int PVRClientMythTV::GetRecordingsAmount(void) CLockObject lock(m_recordingsLock); - if (m_recordings.empty()) - // Load recorings list - res = FillRecordings(); - else + for (ProgramInfoMap::iterator it = m_recordings.begin(); it != m_recordings.end(); ++it) { - for (ProgramInfoMap::iterator it = m_recordings.begin(); it != m_recordings.end(); ++it) - { - if (!it->second.IsNull() && it->second.IsVisible()) - res++; - } + if (!it->second.IsNull() && it->second.IsVisible()) + res++; } if (res == 0) XBMC->Log(LOG_INFO, "%s: No recording", __FUNCTION__); @@ -725,7 +756,7 @@ PVR_ERROR PVRClientMythTV::GetRecordings(ADDON_HANDLE handle) //@TODO: tag.iLastPlayedPosition std::string id = it->second.UID(); - std::string title = this->MakeProgramTitle(it->second.Title(), it->second.Subtitle()); + std::string title = MakeProgramTitle(it->second.Title(), it->second.Subtitle()); PVR_STRCPY(tag.strRecordingId, id.c_str()); PVR_STRCPY(tag.strTitle, title.c_str()); @@ -805,8 +836,7 @@ void PVRClientMythTV::ForceUpdateRecording(ProgramInfoMap::iterator it) int PVRClientMythTV::FillRecordings() { int count = 0; - if (g_bExtraDebug) - XBMC->Log(LOG_DEBUG, "%s", __FUNCTION__); + XBMC->Log(LOG_DEBUG, "%s", __FUNCTION__); // Check event connection if (!m_eventHandler->IsConnected()) @@ -823,6 +853,7 @@ int PVRClientMythTV::FillRecordings() if (prog.IsVisible() && !prog.IsLiveTV()) ++count; } + XBMC->Log(LOG_DEBUG, "%s: Loaded %d visible recording(s)", __FUNCTION__, count); return count; } @@ -1137,14 +1168,9 @@ PVR_ERROR PVRClientMythTV::GetRecordingEdl(const PVR_RECORDING &recording, PVR_E return PVR_ERROR_NO_ERROR; } -MythChannel PVRClientMythTV::FindRecordingChannel(const MythProgramInfo& programInfo) +MythChannel PVRClientMythTV::FindRecordingChannel(const MythProgramInfo& programInfo) const { - ChannelIdMap::iterator channelByIdIt = m_channelsById.find(programInfo.ChannelID()); - if (channelByIdIt != m_channelsById.end()) - { - return channelByIdIt->second; - } - return MythChannel(); + return FindChannel(programInfo.ChannelID()); } bool PVRClientMythTV::IsMyLiveRecording(const MythProgramInfo& programInfo) @@ -1188,7 +1214,7 @@ PVR_ERROR PVRClientMythTV::GetTimers(ADDON_HANDLE handle) std::string rulemarker = ""; tag.startTime = it->second->StartTime(); tag.endTime = it->second->EndTime(); - tag.iClientChannelUid = (int)FindPVRChannelUid(it->second->ChannelID()); + tag.iClientChannelUid = FindPVRChannelUid(it->second->ChannelID()); tag.iPriority = it->second->Priority(); int genre = m_categories.Category(it->second->Category()); tag.iGenreSubType = genre & 0x0F; @@ -1268,7 +1294,7 @@ PVR_ERROR PVRClientMythTV::GetTimers(ADDON_HANDLE handle) std::string title = it->second->Title(); if (!rulemarker.empty()) title.append(" ").append(rulemarker); - PVR_STRCPY(tag.strTitle, this->MakeProgramTitle(title, it->second->Subtitle()).c_str()); + PVR_STRCPY(tag.strTitle, MakeProgramTitle(title, it->second->Subtitle()).c_str()); // Summary PVR_STRCPY(tag.strSummary, it->second->Description().c_str()); @@ -1379,11 +1405,6 @@ MythRecordingRule PVRClientMythTV::PVRtoMythRecordingRule(const PVR_TIMER &timer time_t et = timer.endTime; time_t now = time(NULL); std::string title = timer.strTitle; - std::string cs; - - ChannelIdMap::iterator channelIt = m_channelsById.find(timer.iClientChannelUid); - if (channelIt != m_channelsById.end()) - cs = channelIt->second.Callsign(); // Fix timeslot as needed if (st == 0) @@ -1470,12 +1491,13 @@ MythRecordingRule PVRClientMythTV::PVRtoMythRecordingRule(const PVR_TIMER &timer if (!epgFound) { + MythChannel ch = FindChannel(timer.iClientChannelUid); rule.SetStartTime(st); rule.SetEndTime(et); rule.SetTitle(timer.strTitle); rule.SetCategory(m_categories.Category(timer.iGenreType)); rule.SetChannelID(timer.iClientChannelUid); - rule.SetCallsign(cs); + rule.SetCallsign(ch.Callsign()); } else { @@ -1574,16 +1596,8 @@ bool PVRClientMythTV::OpenLiveStream(const PVR_CHANNEL &channel) // Begin critical section CLockObject lock(m_lock); // First we have to get the selected channel - LoadChannelsAndChannelGroups(); - ChannelIdMap::iterator channelByIdIt = m_channelsById.find(channel.iUniqueId); - if (channelByIdIt == m_channelsById.end()) - { - XBMC->Log(LOG_ERROR,"%s: Channel not found", __FUNCTION__); - return false; - } - // Copy and check - Myth::ChannelPtr chan = channelByIdIt->second.GetPtr(); - if (!chan) + MythChannel chan = FindChannel(channel.iUniqueId); + if (chan.IsNull()) { XBMC->Log(LOG_ERROR,"%s: Invalid channel", __FUNCTION__); return false; @@ -1598,7 +1612,7 @@ bool PVRClientMythTV::OpenLiveStream(const PVR_CHANNEL &channel) // Set tuning delay m_liveStream->SetTuneDelay(g_iTuneDelay); // Try to open - if (m_liveStream->SpawnLiveTV(*chan)) + if (m_liveStream->SpawnLiveTV(*(chan.GetPtr()))) { if(g_bDemuxing) m_demux = new Demux(m_liveStream); @@ -1847,7 +1861,7 @@ bool PVRClientMythTV::OpenRecordedStream(const PVR_RECORDING &recording) m_recordingStream = new Myth::RecordingPlayback(*m_eventHandler); else { - // Query backend server IP + // Query backend server IP std::string backend_addr(m_control->GetBackendServerIP6(prog.HostName())); if (backend_addr.empty()) backend_addr = m_control->GetBackendServerIP(prog.HostName()); @@ -2091,6 +2105,7 @@ void PVRClientMythTV::AllowBackendShutdown() std::string PVRClientMythTV::MakeProgramTitle(const std::string& title, const std::string& subtitle) { + // Must contain the original title at the begining std::string epgtitle; if (subtitle.empty()) epgtitle = title; diff --git a/addons/pvr.mythtv/src/pvrclient-mythtv.h b/addons/pvr.mythtv/src/pvrclient-mythtv.h index 145c13ecd..98e3bc663 100644 --- a/addons/pvr.mythtv/src/pvrclient-mythtv.h +++ b/addons/pvr.mythtv/src/pvrclient-mythtv.h @@ -39,7 +39,7 @@ #include #include -class PVRClientMythTV : public Myth::EventSubscriber +class PVRClientMythTV : public Myth::EventSubscriber, FileConsumer { public: PVRClientMythTV(); @@ -59,11 +59,15 @@ class PVRClientMythTV : public Myth::EventSubscriber // Implements EventSubscriber void HandleBackendMessage(const Myth::EventMessage& msg); + void HandleChannelChange(); void HandleScheduleChange(); void HandleAskRecording(const Myth::EventMessage& msg); void HandleRecordingListChange(const Myth::EventMessage& msg); void RunHouseKeeping(); + // Implement FileConsumer + void HandleCleanedCache(); + // EPG PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd); @@ -77,7 +81,6 @@ class PVRClientMythTV : public Myth::EventSubscriber PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group); // Recordings - void UpdateRecordings(); int GetRecordingsAmount(void); PVR_ERROR GetRecordings(ADDON_HANDLE handle); PVR_ERROR DeleteRecording(const PVR_RECORDING &recording); @@ -148,15 +151,18 @@ class PVRClientMythTV : public Myth::EventSubscriber Categories m_categories; // Channels - typedef std::map ChannelIdMap; - typedef std::multimap ChannelNumberMap; - typedef std::map > ChannelGroupMap; + typedef std::map ChannelIdMap; ChannelIdMap m_channelsById; - ChannelNumberMap m_channelsByNumber; - ChannelGroupMap m_channelGroups; - typedef std::map PVRChannelMap; + typedef struct { unsigned int iUniqueId; bool bIsRadio; } PVRChannelItem; + typedef std::vector PVRChannelList; + typedef std::map PVRChannelGroupMap; + PVRChannelList m_PVRChannels; + PVRChannelGroupMap m_PVRChannelGroups; + typedef std::map PVRChannelMap; PVRChannelMap m_PVRChannelUidById; - void LoadChannelsAndChannelGroups(); + mutable PLATFORM::CMutex m_channelsLock; + int FillChannelsAndChannelGroups(); + MythChannel FindChannel(uint32_t channelId) const; int FindPVRChannelUid(uint32_t channelId) const; // Demuxer TS @@ -164,11 +170,11 @@ class PVRClientMythTV : public Myth::EventSubscriber // Recordings ProgramInfoMap m_recordings; - PLATFORM::CMutex m_recordingsLock; + mutable PLATFORM::CMutex m_recordingsLock; unsigned m_recordingChangePinCount; void ForceUpdateRecording(ProgramInfoMap::iterator it); int FillRecordings(); - MythChannel FindRecordingChannel(const MythProgramInfo& programInfo); + MythChannel FindRecordingChannel(const MythProgramInfo& programInfo) const; bool IsMyLiveRecording(const MythProgramInfo& programInfo); // Timers diff --git a/lib/cppmyth/configure.ac b/lib/cppmyth/configure.ac index b9e1db289..920e98da5 100644 --- a/lib/cppmyth/configure.ac +++ b/lib/cppmyth/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.60]) -AC_INIT([cppmyth], [1.0], [jlbarriere68@gmail.com]) +AC_INIT([cppmyth], [1.1], [jlbarriere68@gmail.com]) AM_INIT_AUTOMAKE([1.10 foreign]) diff --git a/lib/cppmyth/cppmyth/CMakeLists.txt b/lib/cppmyth/cppmyth/CMakeLists.txt index bbc149af7..802d0ea18 100644 --- a/lib/cppmyth/cppmyth/CMakeLists.txt +++ b/lib/cppmyth/cppmyth/CMakeLists.txt @@ -2,63 +2,63 @@ cmake_minimum_required (VERSION 2.6 FATAL_ERROR) cmake_policy (VERSION 2.6) project (cppmyth) -include (GNUInstallDirs) +#include (GNUInstallDirs) # Options OPTION (BUILD_SHARED_LIBS "Build shared libraries." OFF) if (MSVC) # This option must match the settings used in your program, in particular if you # are linking statically - OPTION( STATIC_CRT "Link the static CRT libraries" OFF ) -endif (MSVC) + OPTION (STATIC_CRT "Link the static CRT libraries" OFF) +endif () ############################################################################### # set lib version here -set (GENERIC_LIB_VERSION "1.0.7") -set (GENERIC_LIB_SOVERSION "1") +set (CPPMYTH_LIB_VERSION "1.1.0") +set (CPPMYTH_LIB_SOVERSION "1.1") ############################################################################### # add definitions if (MSVC) # Turn off Microsofts "security" warnings. - add_definitions( "/W3 /D_USE_32BIT_TIME_T /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo" ) + add_definitions("/W3 /D_USE_32BIT_TIME_T /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo") if (STATIC_CRT) - set(CMAKE_C_FLAGS_RELEASE "/MT") - set(CMAKE_C_FLAGS_DEBUG "/MTd") - endif (STATIC_CRT) -endif (MSVC) + set (CMAKE_C_FLAGS_RELEASE "/MT") + set (CMAKE_C_FLAGS_DEBUG "/MTd") + endif () +endif () if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) set (CMAKE_C_FLAGS "-fPIC") set (CMAKE_CXX_FLAGS "-fPIC") -endif (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) +endif () ############################################################################### # configure -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include (CheckFunctionExists) include (CheckFunctionKeywords) check_function_exists (timegm CHK_TIMEGM) if (CHK_TIMEGM) - set(HAVE_TIMEGM 1) -else (CHK_TIMEGM) - set(HAVE_TIMEGM 0) -endif (CHK_TIMEGM) + set (HAVE_TIMEGM 1) +else () + set (HAVE_TIMEGM 0) +endif () check_function_exists (localtime_r CHK_LOCALTIME_R) if (CHK_LOCALTIME_R) - set(HAVE_LOCALTIME_R 1) -else (CHK_LOCALTIME_R) - set(HAVE_LOCALTIME_R 0) -endif (CHK_LOCALTIME_R) + set (HAVE_LOCALTIME_R 1) +else () + set (HAVE_LOCALTIME_R 0) +endif () check_function_exists (gmtime_r CHK_GMTIME_R) if (CHK_GMTIME_R) - set(HAVE_GMTIME_R 1) -else (CHK_GMTIME_R) - set(HAVE_GMTIME_R 0) -endif (CHK_GMTIME_R) + set (HAVE_GMTIME_R 1) +else () + set (HAVE_GMTIME_R 0) +endif () # Check what the inline keyword is. check_function_keywords ("inline") @@ -70,13 +70,13 @@ elseif (HAVE___INLINE) set (CC_INLINE __inline) elseif (HAVE___INLINE__) set (CC_INLINE __inline__) -else (HAVE_INLINE) +else () # no inline on this platform set (CC_INLINE) -endif (HAVE_INLINE) +endif () # configure the public config file -configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/src/cppmyth_config.h.in +configure_file (${CMAKE_CURRENT_SOURCE_DIR}/src/cppmyth_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/cppmyth_config.h) # Copy the header files to the public include folder @@ -138,7 +138,7 @@ file (GLOB HDR_FILES if (MSVC) file (GLOB PLATFORM_SRC_FILES src/private/platform/windows/*.cpp) -endif (MSVC) +endif () set (CPPMYTH_SOURCES ${SRC_FILES} ${HDR_FILES} ${PLATFORM_SRC_FILES}) @@ -149,19 +149,36 @@ if (BUILD_SHARED_LIBS) add_library (cppmyth SHARED ${CPPMYTH_SOURCES}) target_link_libraries (cppmyth pthread jansson) set_target_properties (cppmyth PROPERTIES - VERSION "${GENERIC_LIB_VERSION}" - SOVERSION "${GENERIC_LIB_SOVERSION}") -else (BUILD_SHARED_LIBS) + VERSION "${CPPMYTH_LIB_VERSION}" + SOVERSION "${CPPMYTH_LIB_SOVERSION}") +else () add_library(cppmyth STATIC ${CPPMYTH_SOURCES}) -endif (BUILD_SHARED_LIBS) +endif () ############################################################################### # install targets +# Create pkg-conf file. +# (We use the same files as ./configure does, so we +# have to defined the same variables used there). +if (NOT DEFINED CMAKE_INSTALL_BINDIR) + set(CMAKE_INSTALL_BINDIR bin) +endif() +if (NOT DEFINED CMAKE_INSTALL_LIBDIR) + set(CMAKE_INSTALL_LIBDIR lib) +endif () +if (NOT DEFINED CMAKE_INSTALL_INCLUDEDIR) + set(CMAKE_INSTALL_INCLUDEDIR include) +endif() +set(prefix ${CMAKE_INSTALL_PREFIX}) +set(exec_prefix ${CMAKE_INSTALL_PREFIX}) +set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) +set(VERSION ${CPPMYTH_LIB_VERSION}) +configure_file (cppmyth.pc.in cppmyth.pc @ONLY) + install (TARGETS cppmyth RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/include/cppmyth_config.h @@ -178,6 +195,7 @@ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/include/mythstream.h ${CMAKE_CURRENT_BINARY_DIR}/include/mythwsstream.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cppmyth/) + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/include/proto/mythprotobase.h ${CMAKE_CURRENT_BINARY_DIR}/include/proto/mythprotomonitor.h @@ -187,12 +205,6 @@ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/include/proto/mythprototransfer.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cppmyth/proto/) -foreach (p LIB INCLUDE) - set (var CMAKE_INSTALL_${p}DIR) - if (NOT IS_ABSOLUTE "${${var}}") - set (${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") - endif () -endforeach () - -configure_file (cppmyth.pc.in cppmyth.pc @ONLY) -install (FILES ${CMAKE_CURRENT_BINARY_DIR}/cppmyth.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +install (FILES + ${CMAKE_CURRENT_BINARY_DIR}/cppmyth.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) diff --git a/lib/cppmyth/cppmyth/cppmyth.pc.in b/lib/cppmyth/cppmyth/cppmyth.pc.in index eef10c4a4..b411d14cc 100644 --- a/lib/cppmyth/cppmyth/cppmyth.pc.in +++ b/lib/cppmyth/cppmyth/cppmyth.pc.in @@ -1,10 +1,10 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=${prefix} -libdir=@CMAKE_INSTALL_LIBDIR@ -includedir=@CMAKE_INSTALL_INCLUDEDIR@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=${prefix}/include Name: cppmyth Description: C++ MythClient -Version: @GENERIC_LIB_VERSION@ +Version: @VERSION@ Libs: -L${libdir} -lcppmyth Cflags: -I${includedir} diff --git a/lib/cppmyth/cppmyth/src/mythcontrol.cpp b/lib/cppmyth/cppmyth/src/mythcontrol.cpp index 15f572a37..dcfe1501c 100644 --- a/lib/cppmyth/cppmyth/src/mythcontrol.cpp +++ b/lib/cppmyth/cppmyth/src/mythcontrol.cpp @@ -23,16 +23,16 @@ using namespace Myth; -Control::Control(const std::string& server, unsigned protoPort, unsigned wsapiPort) +Control::Control(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin) : m_monitor(server, protoPort) -, m_wsapi(server, wsapiPort) +, m_wsapi(server, wsapiPort, wsapiSecurityPin) { Open(); } -Control::Control(const std::string& server, unsigned protoPort, unsigned wsapiPort, bool blockShutdown) +Control::Control(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin, bool blockShutdown) : m_monitor(server, protoPort, blockShutdown) -, m_wsapi(server, wsapiPort) +, m_wsapi(server, wsapiPort, wsapiSecurityPin) { Open(); } diff --git a/lib/cppmyth/cppmyth/src/mythcontrol.h b/lib/cppmyth/cppmyth/src/mythcontrol.h index de0609ca6..fdb3eebd5 100644 --- a/lib/cppmyth/cppmyth/src/mythcontrol.h +++ b/lib/cppmyth/cppmyth/src/mythcontrol.h @@ -32,8 +32,8 @@ namespace Myth class Control { public: - Control(const std::string& server, unsigned protoPort, unsigned wsapiPort); - Control(const std::string& server, unsigned protoPort, unsigned wsapiPort, bool blockShutdown); + Control(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin); + Control(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin, bool blockShutdown); ~Control(); bool Open(); diff --git a/lib/cppmyth/cppmyth/src/mythtypes.h b/lib/cppmyth/cppmyth/src/mythtypes.h index 74da459e7..b5c464a08 100644 --- a/lib/cppmyth/cppmyth/src/mythtypes.h +++ b/lib/cppmyth/cppmyth/src/mythtypes.h @@ -194,6 +194,11 @@ namespace Myth { uint32_t count; uint32_t protoVer; + + ItemList() + : count(0) + , protoVer(0) + {} }; struct Version @@ -201,6 +206,11 @@ namespace Myth std::string version; uint32_t protocol; uint32_t schema; + + Version() + : protocol(0) + , schema(0) + {} }; typedef MYTH_SHARED_PTR VersionPtr; @@ -240,6 +250,14 @@ namespace Myth uint32_t sourceId; uint32_t inputId; bool visible; + + Channel() + : chanId(0) + , mplexId(0) + , sourceId(0) + , inputId(0) + , visible(true) + {} }; typedef MYTH_SHARED_PTR ChannelPtr; @@ -262,6 +280,19 @@ namespace Myth std::string storageGroup; std::string playGroup; uint32_t recordedId; // Since proto 82 + + Recording() + : recordId(0) + , priority(0) + , status(0) + , encoderId(0) + , recType(0) + , dupInType(DI_InRecorded) + , dupMethod(DM_CheckNone) + , startTs(0) + , endTs(0) + , recordedId(0) + {} }; typedef MYTH_SHARED_PTR RecordingPtr; @@ -296,6 +327,21 @@ namespace Myth Channel channel; Recording recording; std::vector artwork; + + Program() + : startTime(0) + , endTime(0) + , season(0) + , episode(0) + , fileSize(0) + , repeat(false) + , programFlags(0) + , lastModified(0) + , airdate(0) + , audioProps(0) + , videoProps(0) + , subProps(0) + {} }; typedef MYTH_SHARED_PTR ProgramPtr; @@ -309,6 +355,10 @@ namespace Myth uint32_t cardId; std::string cardType; std::string hostName; + + CaptureCard() + : cardId(0) + {} }; typedef MYTH_SHARED_PTR CaptureCardPtr; @@ -323,6 +373,14 @@ namespace Myth uint32_t mplexId; std::string inputName; uint8_t liveTVOrder; + + CardInput() + : inputId(0) + , cardId(0) + , sourceId(0) + , mplexId(0) + , liveTVOrder(0) + {} }; typedef MYTH_SHARED_PTR CardInputPtr; @@ -333,6 +391,10 @@ namespace Myth { uint32_t sourceId; std::string sourceName; + + VideoSource() + : sourceId(0) + {} }; typedef MYTH_SHARED_PTR VideoSourcePtr; @@ -387,6 +449,38 @@ namespace Myth bool autoUserJob3; bool autoUserJob4; uint32_t transcoder; + + RecordSchedule() + : recordId(0) + , startTime(0) + , endTime(0) + , chanId(0) + , findDay(0) + , parentId(0) + , inactive(false) + , season(0) + , episode(0) + , type_t(RT_NotRecording) + , searchType_t(ST_NoSearch) + , recPriority(0) + , preferredInput(0) + , startOffset(0) + , endOffset(0) + , dupMethod_t(DM_CheckNone) + , dupIn_t(DI_InRecorded) + , filter(0) + , autoExpire(false) + , maxEpisodes(0) + , maxNewest(false) + , autoCommflag(false) + , autoTranscode(false) + , autoMetaLookup(false) + , autoUserJob1(false) + , autoUserJob2(false) + , autoUserJob3(false) + , autoUserJob4(false) + , transcoder(0) + {} }; typedef MYTH_SHARED_PTR RecordSchedulePtr; @@ -400,6 +494,14 @@ namespace Myth int snr; long ber; long ucb; + + SignalStatus() + : lock(false) + , signal(0) + , snr(0) + , ber(0) + , ucb(0) + {} }; typedef MYTH_SHARED_PTR SignalStatusPtr; @@ -410,6 +512,10 @@ namespace Myth std::vector subject; ProgramPtr program; SignalStatusPtr signal; + + EventMessage() + : event(EVENT_UNKNOWN) + {} }; struct StorageGroupFile @@ -419,6 +525,11 @@ namespace Myth std::string hostName; time_t lastModified; int64_t size; + + StorageGroupFile() + : lastModified(0) + , size(0) + {} }; typedef MYTH_SHARED_PTR StorageGroupFilePtr; @@ -451,6 +562,11 @@ namespace Myth { MARK_t markType; int64_t markValue; + + Mark() + : markType(MARK_CUT_END) + , markValue(0) + {} }; typedef MYTH_SHARED_PTR MarkPtr; diff --git a/lib/cppmyth/cppmyth/src/mythwsapi.cpp b/lib/cppmyth/cppmyth/src/mythwsapi.cpp index 053a60bce..d876a8058 100644 --- a/lib/cppmyth/cppmyth/src/mythwsapi.cpp +++ b/lib/cppmyth/cppmyth/src/mythwsapi.cpp @@ -45,10 +45,11 @@ using namespace Myth; #define WS_ROOT_CONTENT "/Content" #define WS_ROOT_DVR "/Dvr" -WSAPI::WSAPI(const std::string& server, unsigned port) +WSAPI::WSAPI(const std::string& server, unsigned port, const std::string& securityPin) : m_mutex(new PLATFORM::CMutex) , m_server(server) , m_port(port) +, m_securityPin(securityPin) , m_checked(false) , m_version() , m_serverHostName() @@ -181,6 +182,11 @@ bool WSAPI::CheckVersion2_0() WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Myth/GetConnectionInfo"); + if (!m_securityPin.empty()) + { + // Skip if null or empty + req.SetContentParam("Pin", m_securityPin); + } WSResponse resp(req); if (!resp.IsSuccessful()) { diff --git a/lib/cppmyth/cppmyth/src/mythwsapi.h b/lib/cppmyth/cppmyth/src/mythwsapi.h index d0a4ba1f9..c394e3c75 100644 --- a/lib/cppmyth/cppmyth/src/mythwsapi.h +++ b/lib/cppmyth/cppmyth/src/mythwsapi.h @@ -57,7 +57,7 @@ namespace Myth class WSAPI { public: - WSAPI(const std::string& server, unsigned port); + WSAPI(const std::string& server, unsigned port, const std::string& securityPin); ~WSAPI(); unsigned CheckService(); @@ -354,6 +354,7 @@ namespace Myth PLATFORM::CMutex *m_mutex; std::string m_server; unsigned m_port; + std::string m_securityPin; bool m_checked; Version m_version; std::string m_serverHostName; diff --git a/lib/cppmyth/cppmyth/src/private/platform/posix/os-types.h b/lib/cppmyth/cppmyth/src/private/platform/posix/os-types.h index 5617b0f7f..9d2ffe0f7 100644 --- a/lib/cppmyth/cppmyth/src/private/platform/posix/os-types.h +++ b/lib/cppmyth/cppmyth/src/private/platform/posix/os-types.h @@ -151,10 +151,8 @@ inline unsigned long GetTickCount(void) }; #endif /* TARGET_LINUX || TARGET_DARWIN */ -/* Handling of 2-byte Windows wchar strings on non-Windows targets - * Used by The MediaPortal and ForTheRecord pvr addons - */ -typedef uint16_t Wchar_t; /* sizeof(wchar_t) = 4 bytes on Linux, but the MediaPortal buffer files have 2-byte wchars */ +/* Handling of 2-byte Windows wchar strings on non-Windows targets */ +typedef uint16_t Wchar_t; /* sizeof(wchar_t) = 4 bytes on Linux */ /* This is a replacement of the Windows wcslen() function which assumes that * wchar_t is a 2-byte character. diff --git a/lib/cppmyth/cppmyth/src/proto/mythprotoevent.h b/lib/cppmyth/cppmyth/src/proto/mythprotoevent.h index e333be1a3..00dd42a6c 100644 --- a/lib/cppmyth/cppmyth/src/proto/mythprotoevent.h +++ b/lib/cppmyth/cppmyth/src/proto/mythprotoevent.h @@ -34,8 +34,8 @@ namespace Myth public: ProtoEvent(const std::string& server, unsigned port); - bool Open(); - void Close(); + virtual bool Open(); + virtual void Close(); /** * @brief Wait for new backend message from event connection diff --git a/lib/cppmyth/cppmyth/src/proto/mythprotomonitor.h b/lib/cppmyth/cppmyth/src/proto/mythprotomonitor.h index c2dc58c9a..191c406a1 100644 --- a/lib/cppmyth/cppmyth/src/proto/mythprotomonitor.h +++ b/lib/cppmyth/cppmyth/src/proto/mythprotomonitor.h @@ -36,9 +36,9 @@ namespace Myth ProtoMonitor(const std::string& server, unsigned port); ProtoMonitor(const std::string& server, unsigned port, bool blockShutdown); - bool Open(); - void Close(); - bool IsOpen(); + virtual bool Open(); + virtual void Close(); + virtual bool IsOpen(); ProtoRecorderPtr GetNextFreeRecorder(int rnum) { diff --git a/lib/cppmyth/cppmyth/src/proto/mythprotoplayback.h b/lib/cppmyth/cppmyth/src/proto/mythprotoplayback.h index 8ecd8de5a..d5f7f8a27 100644 --- a/lib/cppmyth/cppmyth/src/proto/mythprotoplayback.h +++ b/lib/cppmyth/cppmyth/src/proto/mythprotoplayback.h @@ -35,9 +35,9 @@ namespace Myth public: ProtoPlayback(const std::string& server, unsigned port); - bool Open(); - void Close(); - bool IsOpen(); + virtual bool Open(); + virtual void Close(); + virtual bool IsOpen(); void TransferDone(ProtoTransfer& transfer) { diff --git a/lib/cppmyth/cppmyth/src/proto/mythprotorecorder.h b/lib/cppmyth/cppmyth/src/proto/mythprotorecorder.h index db97c8fb7..b50fff158 100644 --- a/lib/cppmyth/cppmyth/src/proto/mythprotorecorder.h +++ b/lib/cppmyth/cppmyth/src/proto/mythprotorecorder.h @@ -34,7 +34,7 @@ namespace Myth { public: ProtoRecorder(int num, const std::string& server, unsigned port); - ~ProtoRecorder(); + virtual ~ProtoRecorder(); int GetNum() const; bool IsPlaying() const; @@ -57,22 +57,6 @@ namespace Myth { return GetCurrentRecording75(); } - void TransferDone(ProtoTransfer& transfer) - { - ProtoPlayback::TransferDone(transfer); - } - bool TransferIsOpen(ProtoTransfer& transfer) - { - return ProtoPlayback::TransferIsOpen(transfer); - } - int TransferRequestBlock(ProtoTransfer& transfer, void *buffer, unsigned n) - { - return ProtoPlayback::TransferRequestBlock(transfer, buffer, n); - } - int64_t TransferSeek(ProtoTransfer& transfer, int64_t offset, WHENCE_t whence) - { - return ProtoPlayback::TransferSeek(transfer, offset, whence); - } int64_t GetFilePosition() { return GetFilePosition75(); diff --git a/lib/cppmyth/cppmyth/src/proto/mythprototransfer.h b/lib/cppmyth/cppmyth/src/proto/mythprototransfer.h index 99be526a1..7e485281d 100644 --- a/lib/cppmyth/cppmyth/src/proto/mythprototransfer.h +++ b/lib/cppmyth/cppmyth/src/proto/mythprototransfer.h @@ -37,8 +37,8 @@ namespace Myth public: ProtoTransfer(const std::string& server, unsigned port, const std::string& pathname, const std::string& sgname); - bool Open(); - void Close(); + virtual bool Open(); + virtual void Close(); void Lock(); void Unlock(); diff --git a/lib/cppmyth/jansson/.gitignore b/lib/cppmyth/jansson/.gitignore index 9189a9312..e6533b4d2 100644 --- a/lib/cppmyth/jansson/.gitignore +++ b/lib/cppmyth/jansson/.gitignore @@ -19,10 +19,15 @@ install-sh libtool ltmain.sh missing +compile +test-driver *.lo *.la stamp-h1 *.pyc *.pc /src/jansson_config.h +/jansson_private_config.h.in +/jansson_private_config.h +/build *.exe diff --git a/lib/cppmyth/jansson/.travis.yml b/lib/cppmyth/jansson/.travis.yml index 1cca27456..452ed1754 100644 --- a/lib/cppmyth/jansson/.travis.yml +++ b/lib/cppmyth/jansson/.travis.yml @@ -1,5 +1,14 @@ +env: + matrix: + - JANSSON_BUILD_METHOD=cmake JANSSON_CMAKE_OPTIONS="-DJANSSON_TEST_WITH_VALGRIND=ON" JANSSON_EXTRA_INSTALL="valgrind" + - JANSSON_BUILD_METHOD=autotools language: c compiler: - gcc - clang -script: autoreconf -f -i && CFLAGS=-Werror ./configure && make check +install: + - sudo apt-get update -qq + - sudo apt-get install -y -qq cmake $JANSSON_EXTRA_INSTALL +script: + - if [ "$JANSSON_BUILD_METHOD" = "autotools" ]; then autoreconf -f -i && CFLAGS=-Werror ./configure && make check; fi + - if [ "$JANSSON_BUILD_METHOD" = "cmake" ]; then mkdir build && cd build && cmake .. $JANSSON_CMAKE_OPTIONS && cmake --build . && ctest --output-on-failure; fi diff --git a/lib/cppmyth/jansson/Android.mk b/lib/cppmyth/jansson/Android.mk index eb4fed7f2..e3b09e72c 100644 --- a/lib/cppmyth/jansson/Android.mk +++ b/lib/cppmyth/jansson/Android.mk @@ -7,6 +7,7 @@ LOCAL_SRC_FILES := \ src/dump.c \ src/error.c \ src/hashtable.c \ + src/hashtable_seed.c \ src/load.c \ src/memory.c \ src/pack_unpack.c \ @@ -22,7 +23,7 @@ LOCAL_C_INCLUDES += \ LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := libc -LOCAL_CFLAGS += -O3 +LOCAL_CFLAGS += -O3 -DHAVE_STDINT_H=1 LOCAL_MODULE:= libjansson diff --git a/lib/cppmyth/jansson/CHANGES b/lib/cppmyth/jansson/CHANGES index 99d1647d7..0fadd33b4 100644 --- a/lib/cppmyth/jansson/CHANGES +++ b/lib/cppmyth/jansson/CHANGES @@ -1,3 +1,99 @@ +Version 2.7 +=========== + +Released 2014-10-02 + +* New features: + + - `json_pack()` and friends: Add format specifiers ``s%`` and ``+%`` + for a size_t string length (#141). + + - `json_unpack()` and friends: Add format specifier ``s%`` for + unpacking the string length along with the string itself (#141). + + - Add length-aware string constructors `json_stringn()` and + `json_stringn_nocheck()`, length-aware string mutators + `json_string_setn()` and `json_string_setn_nocheck()`, and a + function for getting string's length `json_string_length()` (#141, + #143). + + - Support ``\u0000`` escapes in the decoder. The support can be + enabled by using the ``JSON_ALLOW_NUL`` decoding flag (#141). + + - Add `json_boolean_value()` as an alias for `json_is_true()` + (#146). + + - Add JSON_REAL_PRECISION encoding flag/macro for controlling real + number precision (#178). + + - Define the maximum indentation as JSON_MAX_INDENT (#191). + +* Bug fixes: + + - Some malformed ``\uNNNN`` escapes could crash the decoder with an + assertion failure. + + - Avoid integer overflows with very long strings in UTF-8 decoder and + hashtable. + + - Check for *NULL* key in `json_object_get()` and + `json_object_del()` (#151). + + - Enhance hashtable seeding on Windows (#162). + + - `json_unpack()`: Allow mixing JSON_STRICT with optional keys + (#162, #163). + + - Fix int/int32 mismatch (#142). + + - Parse subnormal numbers correctly (#202). + +* Build: + + - Remove VS2010 build files. CMake should be used on Windows instead + (#165). + + - Fix CMake build flags for MinGW (#193). + + - Add CMake config files for find_package. Rename config.h to + jansson_private_config.h (#157, #159). + + - Make Valgrind checks work with CMake (#160). + + - Fix feature checks to use correct __ATOMIC flags. + + - Fix CMake checks for uint16_t and uint8_t support (#177). + + - Make Jansson build on SmartOS/Solaris (#171). + + - Work around a GCC bug on Solaris (#175). + + - Fix autoreconf on Debian (#182). + + - Don't use GNU make specific export for global AM_CFLAGS (#203, + #204). + + - Fix building on Android using the supplied Android.mk (#166, + #174). + + - Android.mk: Add -DHAVE_STDINT_H to LOCAL_CFLAGS (#200). + +* Documentation: + + - Document JANSSON_BUILD_SHARED_LIBS CMake option (#187). + +* Tests: + + - Close file handles correctly (#198). + +* Other changes: + + - ``\uNNNN`` escapes are now encoded in upper case for better + readability. + + - Enable usage of AddressSanitizer (#180). + + Version 2.6 =========== diff --git a/lib/cppmyth/jansson/CMakeLists.txt b/lib/cppmyth/jansson/CMakeLists.txt index c7be3f04b..d725a4f72 100644 --- a/lib/cppmyth/jansson/CMakeLists.txt +++ b/lib/cppmyth/jansson/CMakeLists.txt @@ -51,26 +51,26 @@ cmake_minimum_required (VERSION 2.8) project (jansson C) # Options -OPTION (BUILD_SHARED_LIBS "Build shared libraries." OFF) -OPTION (USE_URANDOM "Use /dev/urandom to seed the hash function." ON) -OPTION (USE_WINDOWS_CRYPTOAPI "Use CryptGenRandom to seed the hash function." ON) +option(JANSSON_BUILD_SHARED_LIBS "Build shared libraries." OFF) +option(USE_URANDOM "Use /dev/urandom to seed the hash function." ON) +option(USE_WINDOWS_CRYPTOAPI "Use CryptGenRandom to seed the hash function." ON) if (MSVC) # This option must match the settings used in your program, in particular if you # are linking statically - OPTION( STATIC_CRT "Link the static CRT libraries" OFF ) + option(JANSSON_STATIC_CRT "Link the static CRT libraries" OFF ) endif () # Set some nicer output dirs. -SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) -SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) -SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) # Give the debug version a different postfix for windows, # so both the debug and release version can be built in the # same build-tree on Windows (MSVC). if (WIN32) - SET (CMAKE_DEBUG_POSTFIX "_d") + set(CMAKE_DEBUG_POSTFIX "_d") else (WIN32) endif (WIN32) @@ -78,16 +78,16 @@ endif (WIN32) # set (JANSSON_VERSION "2.3.1") # set (JANSSON_SOVERSION 2) -set(JANSSON_DISPLAY_VERSION "2.6") +set(JANSSON_DISPLAY_VERSION "2.7") # This is what is required to match the same numbers as automake's -set (JANSSON_VERSION "4.6.0") -set (JANSSON_SOVERSION 4) +set(JANSSON_VERSION "4.7.0") +set(JANSSON_SOVERSION 4) # for CheckFunctionKeywords set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -INCLUDE (CheckCSourceCompiles) +include (CheckCSourceCompiles) include (CheckFunctionExists) include (CheckFunctionKeywords) include (CheckIncludeFiles) @@ -96,16 +96,16 @@ include (CheckTypeSize) if (MSVC) # Turn off Microsofts "security" warnings. add_definitions( "/W3 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo" ) - - if (STATIC_CRT) - set(CMAKE_C_FLAGS_RELEASE "/MT") - set(CMAKE_C_FLAGS_DEBUG "/MTd") + + if (JANSSON_STATIC_CRT) + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd") endif() - + endif() -if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) - set(CMAKE_C_FLAGS "-fPIC") +if (NOT WIN32 AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)) + add_definitions("-fPIC") endif() check_include_files (endian.h HAVE_ENDIAN_H) @@ -149,10 +149,12 @@ else () message (FATAL_ERROR "Could not detect a valid 32-bit integer type") endif () -check_type_size (uint32_t UINT32_T) -check_type_size (__uint32 __UINT32) check_type_size ("unsigned long" UNSIGNED_LONG_INT) check_type_size ("unsigned int" UNSIGNED_INT) +check_type_size ("unsigned short" UNSIGNED_SHORT) + +check_type_size (uint32_t UINT32_T) +check_type_size (__uint32 __UINT32) if (HAVE_UINT32_T) set (JSON_UINT32 uint32_t) elseif (HAVE___UINT32) @@ -165,6 +167,30 @@ else () message (FATAL_ERROR "Could not detect a valid unsigned 32-bit integer type") endif () +check_type_size (uint16_t UINT16_T) +check_type_size (__uint16 __UINT16) +if (HAVE_UINT16_T) + set (JSON_UINT16 uint16_t) +elseif (HAVE___UINT16) + set (JSON_UINT16 __uint16) +elseif (HAVE_UNSIGNED_INT AND (${UNSIGNED_INT} EQUAL 2)) + set (JSON_UINT16 "unsigned int") +elseif (HAVE_UNSIGNED_SHORT AND (${UNSIGNED_SHORT} EQUAL 2)) + set (JSON_UINT16 "unsigned short") +else () + message (FATAL_ERROR "Could not detect a valid unsigned 16-bit integer type") +endif () + +check_type_size (uint8_t UINT8_T) +check_type_size (__uint8 __UINT8) +if (HAVE_UINT8_T) + set (JSON_UINT8 uint8_t) +elseif (HAVE___UINT8) + set (JSON_UINT8 __uint8) +else () + set (JSON_UINT8 "unsigned char") +endif () + # Check for ssize_t and SSIZE_T existance. check_type_size(ssize_t SSIZE_T) check_type_size(SSIZE_T UPPERCASE_SSIZE_T) @@ -232,10 +258,10 @@ if (HAVE_LOCALECONV AND HAVE_LOCALE_H) set (JSON_HAVE_LOCALECONV 1) else () set (JSON_HAVE_LOCALECONV 0) -endif () +endif() # check if we have setlocale -check_function_exists (setlocale HAVE_SETLOCALE) +check_function_exists(setlocale HAVE_SETLOCALE) # Check what the inline keyword is. # Note that the original JSON_INLINE was always set to just 'inline', so this goes further. @@ -244,24 +270,24 @@ check_function_keywords("__inline") check_function_keywords("__inline__") if (HAVE_INLINE) - set (JSON_INLINE inline) + set(JSON_INLINE inline) elseif (HAVE___INLINE) - set (JSON_INLINE __inline) + set(JSON_INLINE __inline) elseif (HAVE___INLINE__) - set (JSON_INLINE __inline__) -else (HAVE_INLINE) + set(JSON_INLINE __inline__) +else() # no inline on this platform set (JSON_INLINE) -endif (HAVE_INLINE) +endif() # Find our snprintf check_function_exists (snprintf HAVE_SNPRINTF) check_function_exists (_snprintf HAVE__SNPRINTF) if (HAVE_SNPRINTF) - set (JSON_SNPRINTF snprintf) + set(JSON_SNPRINTF snprintf) elseif (HAVE__SNPRINTF) - set (JSON_SNPRINTF _snprintf) + set(JSON_SNPRINTF _snprintf) endif () check_c_source_compiles ("int main() { unsigned long val; __sync_bool_compare_and_swap(&val, 0, 1); return 0; } " HAVE_SYNC_BUILTINS) @@ -288,63 +314,66 @@ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/jansson_config.h.cmake file (COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/jansson.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/) +add_definitions(-DJANSSON_USING_CMAKE) # configure the private config file -configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/config.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/private_include/config.h) +configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/jansson_private_config.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/private_include/jansson_private_config.h) # and tell the source code to include it -add_definitions (-DHAVE_CONFIG_H) +add_definitions(-DHAVE_CONFIG_H) include_directories (${CMAKE_CURRENT_BINARY_DIR}/include) include_directories (${CMAKE_CURRENT_BINARY_DIR}/private_include) # Add the lib sources. -file (GLOB C_FILES src/*.c) - -if (BUILD_SHARED_LIBS) - - add_library (jansson SHARED ${C_FILES} src/jansson.def) - - set_target_properties (jansson PROPERTIES +file(GLOB JANSSON_SRC src/*.c) + +set(JANSSON_HDR_PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/hashtable.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/jansson_private.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/strbuffer.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/utf.h + ${CMAKE_CURRENT_BINARY_DIR}/private_include/jansson_private_config.h) + +set(JANSSON_HDR_PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/include/jansson_config.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/jansson.h) + +source_group("Library Sources" FILES ${JANSSON_SRC}) +source_group("Library Private Headers" FILES ${JANSSON_HDR_PRIVATE}) +source_group("Library Public Headers" FILES ${JANSSON_HDR_PUBLIC}) + +if(JANSSON_BUILD_SHARED_LIBS) + add_library(jansson SHARED + ${JANSSON_SRC} + ${JANSSON_HDR_PRIVATE} + ${JANSSON_HDR_PUBLIC} + src/jansson.def) + + set_target_properties(jansson PROPERTIES VERSION ${JANSSON_VERSION} SOVERSION ${JANSSON_SOVERSION}) +else() + add_library(jansson + ${JANSSON_SRC} + ${JANSSON_HDR_PRIVATE} + ${JANSSON_HDR_PUBLIC}) +endif() -else () - - add_library (jansson ${C_FILES}) - -endif () - -# LIBRARY for linux -# RUNTIME for windows (when building shared) -install (TARGETS jansson - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION bin -) - -install (FILES - ${CMAKE_CURRENT_BINARY_DIR}/include/jansson_config.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/jansson.h - DESTINATION include) - -install (FILES - ${CMAKE_CURRENT_BINARY_DIR}/jansson.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) # For building Documentation (uses Sphinx) -OPTION (BUILD_DOCS "Build documentation (uses python-sphinx)." ON) -if (BUILD_DOCS) +option(JANSSON_BUILD_DOCS "Build documentation (uses python-sphinx)." OFF) +if (JANSSON_BUILD_DOCS) find_package(Sphinx) if (NOT SPHINX_FOUND) - message(WARNING "Sphinx not found. Cannot generate documentation! - Set -DBUILD_DOCS=0 to get rid of this message.") + message(WARNING "Sphinx not found. Cannot generate documentation! + Set -DJANSSON_BUILD_DOCS=OFF to get rid of this message.") else() if (Sphinx_VERSION_STRING VERSION_LESS 1.0) - message(WARNING "Your Sphinx version is too old! - This project requires Sphinx v1.0 or above to produce + message(WARNING "Your Sphinx version is too old! + This project requires Sphinx v1.0 or above to produce proper documentation (you have v${Sphinx_VERSION_STRING}). You will get output but it will have errors.") endif() @@ -375,9 +404,9 @@ if (BUILD_DOCS) # Add documentation targets. set(DOC_TARGETS html) - OPTION(BUILD_MAN "Create a target for building man pages." ON) + option(JANSSON_BUILD_MAN "Create a target for building man pages." ON) - if (BUILD_MAN) + if (JANSSON_BUILD_MAN) if (Sphinx_VERSION_STRING VERSION_LESS 1.0) message(WARNING "Sphinx version 1.0 > is required to build man pages. You have v${Sphinx_VERSION_STRING}.") else() @@ -385,9 +414,9 @@ if (BUILD_DOCS) endif() endif() - OPTION(BUILD_LATEX "Create a target for building latex docs (to create PDF)." OFF) + option(JANSSON_BUILD_LATEX "Create a target for building latex docs (to create PDF)." OFF) - if (BUILD_LATEX) + if (JANSSON_BUILD_LATEX) find_package(LATEX) if (NOT LATEX_COMPILER) @@ -397,7 +426,7 @@ if (BUILD_DOCS) list(APPEND DOC_TARGETS latex) endif() endif() - + # The doc target will build all documentation targets. add_custom_target(doc) @@ -420,14 +449,14 @@ if (BUILD_DOCS) endif () -OPTION (WITHOUT_TESTS "Don't build tests ('make test' to execute tests)" OFF) +option(JANSSON_WITHOUT_TESTS "Don't build tests ('make test' to execute tests)" OFF) -if (NOT WITHOUT_TESTS) - OPTION (TEST_WITH_VALGRIND "Enable valgrind tests." OFF) +if (NOT JANSSON_WITHOUT_TESTS) + option(JANSSON_TEST_WITH_VALGRIND "Enable valgrind tests." OFF) ENABLE_TESTING() - if (TEST_WITH_VALGRIND) + if (JANSSON_TEST_WITH_VALGRIND) # TODO: Add FindValgrind.cmake instead of having a hardcoded path. add_definitions(-DVALGRIND) @@ -435,7 +464,7 @@ if (NOT WITHOUT_TESTS) # enable valgrind set(CMAKE_MEMORYCHECK_COMMAND valgrind) set(CMAKE_MEMORYCHECK_COMMAND_OPTIONS - "--leak-check=full --show-reachable=yes --track-origins=yes -q") + "--error-exitcode=1 --leak-check=full --show-reachable=yes --track-origins=yes -q") set(MEMCHECK_COMMAND "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS}") @@ -446,7 +475,7 @@ if (NOT WITHOUT_TESTS) # Test suites. # if (CMAKE_COMPILER_IS_GNUCC) - add_definitions(-Wall -Wextra -Wdeclaration-after-statement -Werror) + add_definitions(-Wall -Wextra -Wdeclaration-after-statement) endif () set(api_tests @@ -479,11 +508,12 @@ if (NOT WITHOUT_TESTS) # Create executables and tests/valgrind tests for API tests. foreach (test ${api_tests}) build_testprog(${test} ${PROJECT_SOURCE_DIR}/test/suites/api) - add_test(${test} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test}) - if (TEST_WITH_VALGRIND) - add_test(memcheck_${test} ${MEMCHECK_COMMAND} - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test}) + if (JANSSON_TEST_WITH_VALGRIND) + add_test(memcheck__${test} + ${MEMCHECK_COMMAND} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test}) + else() + add_test(${test} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test}) endif () endforeach () @@ -493,20 +523,136 @@ if (NOT WITHOUT_TESTS) set(SUITES encoding-flags valid invalid invalid-unicode) foreach (SUITE ${SUITES}) file(GLOB TESTDIRS ${jansson_SOURCE_DIR}/test/suites/${SUITE}/*) + foreach (TESTDIR ${TESTDIRS}) if (IS_DIRECTORY ${TESTDIR}) get_filename_component(TNAME ${TESTDIR} NAME) - add_test(${SUITE}__${TNAME} - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/json_process ${TESTDIR}) + + set(SUITE_TEST_CMD ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/json_process) + + if (JANSSON_TEST_WITH_VALGRIND) + add_test(memcheck__${SUITE}__${TNAME} + ${MEMCHECK_COMMAND} ${SUITE_TEST_CMD} ${TESTDIR}) + else() + add_test(${SUITE}__${TNAME} + ${SUITE_TEST_CMD} ${TESTDIR}) + endif() + if ((${SUITE} STREQUAL "valid" OR ${SUITE} STREQUAL "invalid") AND NOT EXISTS ${TESTDIR}/nostrip) - add_test(${SUITE}__${TNAME}__strip - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/json_process --strip ${TESTDIR}) + if (JANSSON_TEST_WITH_VALGRIND) + add_test(memcheck__${SUITE}__${TNAME}__strip + ${MEMCHECK_COMMAND} ${SUITE_TEST_CMD} --strip ${TESTDIR}) + else() + add_test(${SUITE}__${TNAME}__strip + ${SUITE_TEST_CMD} --strip ${TESTDIR}) + endif() endif () endif () endforeach () endforeach () - add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} + add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS json_process ${api_tests}) endif () +# +# Installation preparation. +# + +# Allow the user to override installation directories. +set(JANSSON_INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries") +set(JANSSON_INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables") +set(JANSSON_INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files") + +if(WIN32 AND NOT CYGWIN) + set(DEF_INSTALL_CMAKE_DIR cmake) +else() + set(DEF_INSTALL_CMAKE_DIR lib/cmake/jansson) +endif() + +set(JANSSON_INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") + +# Make sure the paths are absolute. +foreach(p LIB BIN INCLUDE CMAKE) + set(var JANSSON_INSTALL_${p}_DIR) + if(NOT IS_ABSOLUTE "${${var}}") + set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") + endif() +endforeach() + +# Export targets (This is used for other CMake projects to easily find the libraries and include files). +export(TARGETS jansson + FILE "${PROJECT_BINARY_DIR}/JanssonTargets.cmake") +export(PACKAGE jansson) + +# Generate the config file for the build-tree. +set(JANSSON__INCLUDE_DIRS + "${PROJECT_SOURCE_DIR}/include" + "${PROJECT_BINARY_DIR}/include") +set(JANSSON_INCLUDE_DIRS ${JANSSON__INCLUDE_DIRS} CACHE PATH "Jansson include directories") +configure_file(${PROJECT_SOURCE_DIR}/cmake/JanssonConfig.cmake.in + ${PROJECT_BINARY_DIR}/JanssonConfig.cmake + @ONLY) + +# Generate the config file for the installation tree. +file(RELATIVE_PATH + REL_INCLUDE_DIR + "${JANSSON_INSTALL_CMAKE_DIR}" + "${JANSSON_INSTALL_INCLUDE_DIR}") # Calculate the relative directory from the Cmake dir. + +# Note the EVENT_CMAKE_DIR is defined in JanssonConfig.cmake.in, +# we escape it here so it's evaluated when it is included instead +# so that the include dirs are given relative to where the +# config file is located. +set(JANSSON__INCLUDE_DIRS + "\${JANSSON_CMAKE_DIR}/${REL_INCLUDE_DIR}") +configure_file(${PROJECT_SOURCE_DIR}/cmake/JanssonConfig.cmake.in + ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/JanssonConfig.cmake + @ONLY) + +# Generate version info for both build-tree and install-tree. +configure_file(${PROJECT_SOURCE_DIR}/cmake/JanssonConfigVersion.cmake.in + ${PROJECT_BINARY_DIR}/JanssonConfigVersion.cmake + @ONLY) + +# Define the public headers. +set_target_properties(jansson PROPERTIES PUBLIC_HEADER "${JANSSON_HDR_PUBLIC}") +#TODO: fix this. + +# Create pkg-conf file. +# (We use the same files as ./configure does, so we +# have to defined the same variables used there). +set(prefix ${CMAKE_INSTALL_PREFIX}) +set(exec_prefix ${CMAKE_INSTALL_PREFIX}) +set(libdir ${CMAKE_INSTALL_PREFIX}/${JANSSON_INSTALL_LIB_DIR}) +set(VERSION ${JANSSON_DISPLAY_VERSION}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/jansson.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/jansson.pc @ONLY) + +# +# Install targets. +# +install(TARGETS jansson + EXPORT JanssonTargets + LIBRARY DESTINATION "${JANSSON_INSTALL_LIB_DIR}" COMPONENT lib + ARCHIVE DESTINATION "${JANSSON_INSTALL_LIB_DIR}" COMPONENT lib + RUNTIME DESTINATION "${JANSSON_INSTALL_BIN_DIR}" COMPONENT lib # Windows DLLs + PUBLIC_HEADER DESTINATION "${JANSSON_INSTALL_INCLUDE_DIR}" COMPONENT dev) + +# Install the pkg-config. +install (FILES + ${CMAKE_CURRENT_BINARY_DIR}/jansson.pc + DESTINATION ${JANSSON_INSTALL_LIB_DIR}/pkgconfig COMPONENT dev) + +# Install the configs. +install(FILES + ${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/JanssonConfig.cmake + ${PROJECT_BINARY_DIR}/JanssonConfigVersion.cmake + DESTINATION "${JANSSON_INSTALL_CMAKE_DIR}" COMPONENT dev) + +# Install exports for the install-tree. +install(EXPORT JanssonTargets + DESTINATION "${JANSSON_INSTALL_CMAKE_DIR}" COMPONENT dev) + +# For use when simply using add_library from a parent project to build jansson. +set(JANSSON_LIBRARIES jansson CACHE STRING "Jansson libraries") diff --git a/lib/cppmyth/jansson/LICENSE b/lib/cppmyth/jansson/LICENSE index a8fb5b82f..8ae43e02e 100644 --- a/lib/cppmyth/jansson/LICENSE +++ b/lib/cppmyth/jansson/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009-2013 Petri Lehtinen +Copyright (c) 2009-2014 Petri Lehtinen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/lib/cppmyth/jansson/Makefile.am b/lib/cppmyth/jansson/Makefile.am index 788f9ac12..ccd70e977 100644 --- a/lib/cppmyth/jansson/Makefile.am +++ b/lib/cppmyth/jansson/Makefile.am @@ -1,4 +1,4 @@ -EXTRA_DIST = CHANGES LICENSE README.rst win32 CMakeLists.txt cmake +EXTRA_DIST = CHANGES LICENSE README.rst CMakeLists.txt cmake android SUBDIRS = doc src test # "make distcheck" builds the dvi target, so use it to check that the @@ -8,8 +8,3 @@ dvi: pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = jansson.pc - -if GCC -# These flags are gcc specific -export AM_CFLAGS = -Wall -Wextra -Wdeclaration-after-statement -endif diff --git a/lib/cppmyth/jansson/README.rst b/lib/cppmyth/jansson/README.rst index a01cbc02d..bedc43910 100644 --- a/lib/cppmyth/jansson/README.rst +++ b/lib/cppmyth/jansson/README.rst @@ -2,8 +2,10 @@ Jansson README ============== .. image:: https://travis-ci.org/akheron/jansson.png - :alt: Build status :target: https://travis-ci.org/akheron/jansson + +.. image:: https://ci.appveyor.com/api/projects/status/lmhkkc4q8cwc65ko + :target: https://ci.appveyor.com/project/akheron/jansson Jansson_ is a C library for encoding, decoding and manipulating JSON data. Its main features and design principles are: @@ -46,8 +48,7 @@ use autoreconf:: Documentation ------------- -Prebuilt HTML documentation is available at -http://www.digip.org/jansson/doc/. +Documentation is available at http://jansson.readthedocs.org/en/latest/. The documentation source is in the ``doc/`` subdirectory. To generate HTML documentation, invoke:: diff --git a/lib/cppmyth/jansson/android/jansson_config.h b/lib/cppmyth/jansson/android/jansson_config.h index c76940b4e..0a313a09e 100644 --- a/lib/cppmyth/jansson/android/jansson_config.h +++ b/lib/cppmyth/jansson/android/jansson_config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Petri Lehtinen + * Copyright (c) 2010-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/appveyor.yml b/lib/cppmyth/jansson/appveyor.yml new file mode 100644 index 000000000..566333415 --- /dev/null +++ b/lib/cppmyth/jansson/appveyor.yml @@ -0,0 +1,6 @@ +build_script: + - md build + - cd build + - cmake .. + - cmake --build . --config Release + - ctest --output-on-failure \ No newline at end of file diff --git a/lib/cppmyth/jansson/cmake/JanssonConfig.cmake.in b/lib/cppmyth/jansson/cmake/JanssonConfig.cmake.in new file mode 100644 index 000000000..d00b3c402 --- /dev/null +++ b/lib/cppmyth/jansson/cmake/JanssonConfig.cmake.in @@ -0,0 +1,17 @@ +# - Config file for the jansson package +# It defines the following variables +# JANSSON_INCLUDE_DIRS - include directories for FooBar +# JANSSON_LIBRARIES - libraries to link against + +# Get the path of the current file. +get_filename_component(JANSSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +# Set the include directories. +set(JANSSON_INCLUDE_DIRS "@JANSSON__INCLUDE_DIRS@") + +# Include the project Targets file, this contains definitions for IMPORTED targets. +include(${JANSSON_CMAKE_DIR}/JanssonTargets.cmake) + +# IMPORTED targets from JanssonTargets.cmake +set(JANSSON_LIBRARIES jansson) + diff --git a/lib/cppmyth/jansson/cmake/JanssonConfigVersion.cmake.in b/lib/cppmyth/jansson/cmake/JanssonConfigVersion.cmake.in new file mode 100644 index 000000000..83b0d74de --- /dev/null +++ b/lib/cppmyth/jansson/cmake/JanssonConfigVersion.cmake.in @@ -0,0 +1,11 @@ +set(PACKAGE_VERSION "@JANSSON_DISPLAY_VERSION@") + +# Check whether the requested PACKAGE_FIND_VERSION is compatible +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/lib/cppmyth/jansson/cmake/jansson_config.h.cmake b/lib/cppmyth/jansson/cmake/jansson_config.h.cmake index 8c500b5da..43e36c573 100644 --- a/lib/cppmyth/jansson/cmake/jansson_config.h.cmake +++ b/lib/cppmyth/jansson/cmake/jansson_config.h.cmake @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Petri Lehtinen + * Copyright (c) 2010-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -17,7 +17,9 @@ #define JANSSON_CONFIG_H /* Define this so that we can disable scattered automake configuration in source files */ +#ifndef JANSSON_USING_CMAKE #define JANSSON_USING_CMAKE +#endif /* Note: when using cmake, JSON_INTEGER_IS_LONG_LONG is not defined nor used, * as we will also check for __int64 etc types. diff --git a/lib/cppmyth/jansson/cmake/config.h.cmake b/lib/cppmyth/jansson/cmake/jansson_private_config.h.cmake similarity index 85% rename from lib/cppmyth/jansson/cmake/config.h.cmake rename to lib/cppmyth/jansson/cmake/jansson_private_config.h.cmake index b27b9a3a8..16e7eb798 100644 --- a/lib/cppmyth/jansson/cmake/config.h.cmake +++ b/lib/cppmyth/jansson/cmake/jansson_private_config.h.cmake @@ -31,6 +31,16 @@ # define uint32_t @JSON_UINT32@ #endif +#cmakedefine HAVE_UINT16_T 1 +#ifndef HAVE_UINT16_T +# define uint16_t @JSON_UINT16@ +#endif + +#cmakedefine HAVE_UINT8_T 1 +#ifndef HAVE_UINT8_T +# define uint8_t @JSON_UINT8@ +#endif + #cmakedefine HAVE_SSIZE_T 1 #ifndef HAVE_SSIZE_T diff --git a/lib/cppmyth/jansson/configure.ac b/lib/cppmyth/jansson/configure.ac index 68d6fd6dd..433b49928 100644 --- a/lib/cppmyth/jansson/configure.ac +++ b/lib/cppmyth/jansson/configure.ac @@ -1,10 +1,11 @@ AC_PREREQ([2.60]) -AC_INIT([jansson], [2.6], [petri@digip.org]) +AC_INIT([jansson], [2.7], [petri@digip.org]) +AC_CONFIG_AUX_DIR([.]) AM_INIT_AUTOMAKE([1.10 foreign]) AC_CONFIG_SRCDIR([src/value.c]) -AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_HEADERS([jansson_private_config.h]) # Checks for programs. AC_PROG_CC @@ -19,6 +20,8 @@ AC_CHECK_HEADERS([endian.h fcntl.h locale.h sched.h unistd.h sys/param.h sys/sta # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_INT32_T AC_TYPE_UINT32_T +AC_TYPE_UINT16_T +AC_TYPE_UINT8_T AC_TYPE_LONG_LONG_INT AC_C_INLINE @@ -89,6 +92,11 @@ AC_DEFINE([USE_WINDOWS_CRYPTOAPI], [1], [Define to 1 if CryptGenRandom should be used for seeding the hash function]) fi +if test x$GCC = xyes; then + AM_CFLAGS="-Wall -Wextra -Wdeclaration-after-statement" +fi +AC_SUBST([AM_CFLAGS]) + AC_CONFIG_FILES([ jansson.pc Makefile diff --git a/lib/cppmyth/jansson/doc/apiref.rst b/lib/cppmyth/jansson/doc/apiref.rst index 60ad48ac9..b60a521d2 100644 --- a/lib/cppmyth/jansson/doc/apiref.rst +++ b/lib/cppmyth/jansson/doc/apiref.rst @@ -150,6 +150,13 @@ functions: Returns true for types ``JSON_TRUE`` and ``JSON_FALSE``, and false for values of other types and for *NULL*. +.. function:: json_boolean_value(const json_t *json) + + Alias of :func:`json_is_true()`, i.e. returns 1 for ``JSON_TRUE`` + and 0 otherwise. + + .. versionadded:: 2.7 + .. _apiref-reference-count: @@ -292,17 +299,23 @@ String ====== Jansson uses UTF-8 as the character encoding. All JSON strings must be -valid UTF-8 (or ASCII, as it's a subset of UTF-8). Normal null -terminated C strings are used, so JSON strings may not contain -embedded null characters. All other Unicode codepoints U+0001 through -U+10FFFF are allowed. +valid UTF-8 (or ASCII, as it's a subset of UTF-8). All Unicode +codepoints U+0000 through U+10FFFF are allowed, but you must use +length-aware functions if you wish to embed NUL bytes in strings. .. function:: json_t *json_string(const char *value) .. refcounting:: new Returns a new JSON string, or *NULL* on error. *value* must be a - valid UTF-8 encoded Unicode string. + valid null terminated UTF-8 encoded Unicode string. + +.. function:: json_t *json_stringn(const char *value, size_t len) + + .. refcounting:: new + + Like :func:`json_string`, but with explicit length, so *value* may + contain null characters or not be null terminated. .. function:: json_t *json_string_nocheck(const char *value) @@ -312,6 +325,13 @@ U+10FFFF are allowed. UTF-8. Use this function only if you are certain that this really is the case (e.g. you have already checked it by other means). +.. function:: json_t *json_stringn_nocheck(const char *value, size_t len) + + .. refcounting:: new + + Like :func:`json_string_nocheck`, but with explicit length, so + *value* may contain null characters or not be null terminated. + .. function:: const char *json_string_value(const json_t *string) Returns the associated value of *string* as a null terminated UTF-8 @@ -321,12 +341,22 @@ U+10FFFF are allowed. the user. It is valid as long as *string* exists, i.e. as long as its reference count has not dropped to zero. +.. function:: size_t json_string_length(const json_t *string) + + Returns the length of *string* in its UTF-8 presentation, or zero + if *string* is not a JSON string. + .. function:: int json_string_set(const json_t *string, const char *value) Sets the associated value of *string* to *value*. *value* must be a valid UTF-8 encoded Unicode string. Returns 0 on success and -1 on error. +.. function:: int json_string_setn(json_t *string, const char *value, size_t len) + + Like :func:`json_string_set`, but with explicit length, so *value* + may contain null characters or not be null terminated. + .. function:: int json_string_set_nocheck(const json_t *string, const char *value) Like :func:`json_string_set`, but doesn't check that *value* is @@ -334,6 +364,11 @@ U+10FFFF are allowed. really is the case (e.g. you have already checked it by other means). +.. function:: int json_string_setn_nocheck(json_t *string, const char *value, size_t len) + + Like :func:`json_string_set_nocheck`, but with explicit length, + so *value* may contain null characters or not be null terminated. + Number ====== @@ -539,6 +574,9 @@ Object A JSON object is a dictionary of key-value pairs, where the key is a Unicode string and the value is any JSON value. +Even though NUL bytes are allowed in string values, they are not +allowed in object keys. + .. function:: json_t *json_object(void) .. refcounting:: new @@ -828,6 +866,12 @@ can be ORed together to obtain *flags*. output. If ``JSON_INDENT`` is not used or *n* is 0, no newlines are inserted between array and object items. + The ``JSON_MAX_INDENT`` constant defines the maximum indentation + that can be used, and its value is 31. + + .. versionchanged:: 2.7 + Added ``JSON_MAX_INDENT``. + ``JSON_COMPACT`` This flag enables a compact representation, i.e. sets the separator between array and object items to ``","`` and between object keys @@ -867,6 +911,16 @@ can be ORed together to obtain *flags*. .. versionadded:: 2.4 +``JSON_REAL_PRECISION(n)`` + Output all real numbers with at most *n* digits of precision. The + valid range for *n* is between 0 and 31 (inclusive), and other + values result in an undefined behavior. + + By default, the precision is 17, to correctly and losslessly encode + all IEEE 754 double precision floating point numbers. + + .. versionadded:: 2.7 + The following functions perform the actual JSON encoding. The result is in UTF-8. @@ -984,6 +1038,19 @@ macros can be ORed together to obtain *flags*. .. versionadded:: 2.5 +``JSON_ALLOW_NUL`` + Allow ``\u0000`` escape inside string values. This is a safety + measure; If you know your input can contain NUL bytes, use this + flag. If you don't use this flag, you don't have to worry about NUL + bytes inside strings unless you explicitly create themselves by + using e.g. :func:`json_stringn()` or ``s#`` format specifier for + :func:`json_pack()`. + + Object keys cannot have embedded NUL bytes even if this flag is + used. + + .. versionadded:: 2.6 + Each function also takes an optional :type:`json_error_t` parameter that is filled with error information if decoding fails. It's also updated on success; the number of bytes of input read is written to @@ -1110,6 +1177,11 @@ arguments. .. versionadded:: 2.5 +``s%`` (string) [const char \*, size_t] + Like ``s#`` but the length argument is of type :type:`size_t`. + + .. versionadded:: 2.6 + ``+`` [const char \*] Like ``s``, but concatenate to the previous string. Only valid after ``s``, ``s#``, ``+`` or ``+#``. @@ -1122,6 +1194,11 @@ arguments. .. versionadded:: 2.5 +``+%`` (string) [const char \*, size_t] + Like ``+#`` but the length argument is of type :type:`size_t`. + + .. versionadded:: 2.6 + ``n`` (null) Output a JSON null value. No argument is consumed. @@ -1236,6 +1313,12 @@ type whose address should be passed. :func:`json_string_value()` internally, so it exists as long as there are still references to the corresponding JSON string. +``s%`` (string) [const char \*, size_t \*] + Convert a JSON string to a pointer to a NULL terminated UTF-8 + string and its length. + + .. versionadded:: 2.6 + ``n`` (null) Expect a JSON null value. Nothing is extracted. diff --git a/lib/cppmyth/jansson/doc/conf.py b/lib/cppmyth/jansson/doc/conf.py index 98d03f80e..e7ad4051d 100644 --- a/lib/cppmyth/jansson/doc/conf.py +++ b/lib/cppmyth/jansson/doc/conf.py @@ -41,14 +41,14 @@ # General information about the project. project = u'Jansson' -copyright = u'2009-2013, Petri Lehtinen' +copyright = u'2009-2014, Petri Lehtinen' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '2.6' +version = '2.7' # The full version, including alpha/beta/rc tags. release = version diff --git a/lib/cppmyth/jansson/doc/conformance.rst b/lib/cppmyth/jansson/doc/conformance.rst index 19f603d62..de3947d40 100644 --- a/lib/cppmyth/jansson/doc/conformance.rst +++ b/lib/cppmyth/jansson/doc/conformance.rst @@ -19,15 +19,11 @@ Strings ======= JSON strings are mapped to C-style null-terminated character arrays, -and UTF-8 encoding is used internally. Strings may not contain -embedded null characters, not even escaped ones. +and UTF-8 encoding is used internally. -For example, trying to decode the following JSON text leads to a parse -error:: - - ["this string contains the null character: \u0000"] - -All other Unicode codepoints U+0001 through U+10FFFF are allowed. +All Unicode codepoints U+0000 through U+10FFFF are allowed in string +values. However, U+0000 is not allowed in object keys because of API +restrictions. Unicode normalization or any other transformation is never performed on any strings (string values or object keys). When checking for diff --git a/lib/cppmyth/jansson/doc/ext/refcounting.py b/lib/cppmyth/jansson/doc/ext/refcounting.py index 4af308467..b714c882c 100644 --- a/lib/cppmyth/jansson/doc/ext/refcounting.py +++ b/lib/cppmyth/jansson/doc/ext/refcounting.py @@ -19,7 +19,7 @@ - :copyright: Copyright (c) 2009-2013 Petri Lehtinen + :copyright: Copyright (c) 2009-2014 Petri Lehtinen :license: MIT, see LICENSE for details. """ diff --git a/lib/cppmyth/jansson/doc/gettingstarted.rst b/lib/cppmyth/jansson/doc/gettingstarted.rst index 4e59e519e..078d2fcc4 100644 --- a/lib/cppmyth/jansson/doc/gettingstarted.rst +++ b/lib/cppmyth/jansson/doc/gettingstarted.rst @@ -140,7 +140,7 @@ By default the CMake_ project will generate build files for building the static library. To build the shared version use:: ... - cmake -DBUILD_SHARED=1 .. + cmake -DJANSSON_BUILD_SHARED_LIBS=1 .. Changing install directory (same as autoconf --prefix) """""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -154,6 +154,7 @@ in CMake_ is:: .. _CMake: http://www.cmake.org + Android ------- @@ -162,17 +163,6 @@ source root directory. The configuration header file is located in the ``android`` directory in the source distribution. -Windows -------- - -**This method is deprecated**. Using :ref:`CMake ` is now -preferred. - -Jansson can be built with Visual Studio 2010 (and probably newer -versions, too). The solution and project files are in the -``win32/vs2010/`` directory in the source distribution. - - Other Systems ------------- diff --git a/lib/cppmyth/jansson/doc/github_commits.c b/lib/cppmyth/jansson/doc/github_commits.c index 94fb8b71d..a1136d6dc 100644 --- a/lib/cppmyth/jansson/doc/github_commits.c +++ b/lib/cppmyth/jansson/doc/github_commits.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/src/Makefile.am b/lib/cppmyth/jansson/src/Makefile.am index 6a497f10b..bfec6072d 100644 --- a/lib/cppmyth/jansson/src/Makefile.am +++ b/lib/cppmyth/jansson/src/Makefile.am @@ -24,4 +24,4 @@ libjansson_la_SOURCES = \ libjansson_la_LDFLAGS = \ -no-undefined \ -export-symbols-regex '^json_' \ - -version-info 10:0:6 + -version-info 11:0:7 diff --git a/lib/cppmyth/jansson/src/dump.c b/lib/cppmyth/jansson/src/dump.c index 3b19c73be..a0932e0f1 100644 --- a/lib/cppmyth/jansson/src/dump.c +++ b/lib/cppmyth/jansson/src/dump.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -22,6 +22,9 @@ #define MAX_INTEGER_STR_LENGTH 100 #define MAX_REAL_STR_LENGTH 100 +#define FLAGS_TO_INDENT(f) ((f) & 0x1F) +#define FLAGS_TO_PRECISION(f) (((f) >> 11) & 0x1F) + struct object_key { size_t serial; const char *key; @@ -45,9 +48,9 @@ static const char whitespace[] = " "; static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t dump, void *data) { - if(JSON_INDENT(flags) > 0) + if(FLAGS_TO_INDENT(flags) > 0) { - int i, ws_count = JSON_INDENT(flags); + int i, ws_count = FLAGS_TO_INDENT(flags); if(dump("\n", 1, data)) return -1; @@ -65,24 +68,25 @@ static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t return 0; } -static int dump_string(const char *str, json_dump_callback_t dump, void *data, size_t flags) +static int dump_string(const char *str, size_t len, json_dump_callback_t dump, void *data, size_t flags) { - const char *pos, *end; + const char *pos, *end, *lim; int32_t codepoint; if(dump("\"", 1, data)) return -1; end = pos = str; + lim = str + len; while(1) { const char *text; char seq[13]; int length; - while(*end) + while(end < lim) { - end = utf8_iterate(pos, &codepoint); + end = utf8_iterate(pos, lim - pos, &codepoint); if(!end) return -1; @@ -126,7 +130,7 @@ static int dump_string(const char *str, json_dump_callback_t dump, void *data, s /* codepoint is in BMP */ if(codepoint < 0x10000) { - sprintf(seq, "\\u%04x", codepoint); + sprintf(seq, "\\u%04X", codepoint); length = 6; } @@ -139,7 +143,7 @@ static int dump_string(const char *str, json_dump_callback_t dump, void *data, s first = 0xD800 | ((codepoint & 0xffc00) >> 10); last = 0xDC00 | (codepoint & 0x003ff); - sprintf(seq, "\\u%04x\\u%04x", first, last); + sprintf(seq, "\\u%04X\\u%04X", first, last); length = 12; } @@ -207,7 +211,8 @@ static int do_dump(const json_t *json, size_t flags, int depth, int size; double value = json_real_value(json); - size = jsonp_dtostr(buffer, MAX_REAL_STR_LENGTH, value); + size = jsonp_dtostr(buffer, MAX_REAL_STR_LENGTH, value, + FLAGS_TO_PRECISION(flags)); if(size < 0) return -1; @@ -215,12 +220,13 @@ static int do_dump(const json_t *json, size_t flags, int depth, } case JSON_STRING: - return dump_string(json_string_value(json), dump, data, flags); + return dump_string(json_string_value(json), json_string_length(json), dump, data, flags); case JSON_ARRAY: { - int i; - int n; + size_t n; + size_t i; + json_array_t *array; /* detect circular references */ @@ -336,7 +342,7 @@ static int do_dump(const json_t *json, size_t flags, int depth, value = json_object_get(json, key); assert(value); - dump_string(key, dump, data, flags); + dump_string(key, strlen(key), dump, data, flags); if(dump(separator, separator_length, data) || do_dump(value, flags, depth + 1, dump, data)) { @@ -372,8 +378,9 @@ static int do_dump(const json_t *json, size_t flags, int depth, while(iter) { void *next = json_object_iter_next((json_t *)json, iter); + const char *key = json_object_iter_key(iter); - dump_string(json_object_iter_key(iter), dump, data, flags); + dump_string(key, strlen(key), dump, data, flags); if(dump(separator, separator_length, data) || do_dump(json_object_iter_value(iter), flags, depth + 1, dump, data)) diff --git a/lib/cppmyth/jansson/src/error.c b/lib/cppmyth/jansson/src/error.c index a544a59fb..2ba8d82ce 100644 --- a/lib/cppmyth/jansson/src/error.c +++ b/lib/cppmyth/jansson/src/error.c @@ -56,7 +56,7 @@ void jsonp_error_vset(json_error_t *error, int line, int column, error->line = line; error->column = column; - error->position = position; + error->position = (int)position; vsnprintf(error->text, JSON_ERROR_TEXT_LENGTH, msg, ap); error->text[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; diff --git a/lib/cppmyth/jansson/src/hashtable.c b/lib/cppmyth/jansson/src/hashtable.c index abd4bf11f..4c4b56563 100644 --- a/lib/cppmyth/jansson/src/hashtable.c +++ b/lib/cppmyth/jansson/src/hashtable.c @@ -1,12 +1,12 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * This library is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #if HAVE_CONFIG_H -#include +#include #endif #include @@ -234,7 +234,14 @@ int hashtable_set(hashtable_t *hashtable, /* offsetof(...) returns the size of pair_t without the last, flexible member. This way, the correct amount is allocated. */ - pair = jsonp_malloc(offsetof(pair_t, key) + strlen(key) + 1); + + size_t len = strlen(key); + if(len >= (size_t)-1 - offsetof(pair_t, key)) { + /* Avoid an overflow if the key is very long */ + return -1; + } + + pair = jsonp_malloc(offsetof(pair_t, key) + len + 1); if(!pair) return -1; diff --git a/lib/cppmyth/jansson/src/hashtable.h b/lib/cppmyth/jansson/src/hashtable.h index 469c6ecd8..f54c3fe05 100644 --- a/lib/cppmyth/jansson/src/hashtable.h +++ b/lib/cppmyth/jansson/src/hashtable.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * This library is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/src/hashtable_seed.c b/lib/cppmyth/jansson/src/hashtable_seed.c index cb5f3106e..751e0e326 100644 --- a/lib/cppmyth/jansson/src/hashtable_seed.c +++ b/lib/cppmyth/jansson/src/hashtable_seed.c @@ -3,7 +3,7 @@ */ #ifdef HAVE_CONFIG_H -#include +#include #endif #include @@ -38,8 +38,8 @@ #endif #if defined(_WIN32) -/* For _getpid() */ -#include +/* For GetModuleHandle(), GetProcAddress() and GetCurrentProcessId() */ +#include #endif #include "jansson.h" @@ -95,7 +95,6 @@ static int seed_from_urandom(uint32_t *seed) { /* Windows Crypto API */ #if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI) -#include #include typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv, LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags); @@ -112,7 +111,7 @@ static int seed_from_windows_cryptoapi(uint32_t *seed) BYTE data[sizeof(uint32_t)]; int ok; - hAdvAPI32 = GetModuleHandle("advapi32.dll"); + hAdvAPI32 = GetModuleHandle(TEXT("advapi32.dll")); if(hAdvAPI32 == NULL) return 1; @@ -131,7 +130,7 @@ static int seed_from_windows_cryptoapi(uint32_t *seed) if (!pCryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) return 1; - ok = CryptGenRandom(hCryptProv, sizeof(uint32_t), data); + ok = pCryptGenRandom(hCryptProv, sizeof(uint32_t), data); pCryptReleaseContext(hCryptProv, 0); if (!ok) @@ -156,7 +155,7 @@ static int seed_from_timestamp_and_pid(uint32_t *seed) { /* XOR with PID for more randomness */ #if defined(_WIN32) - *seed ^= (uint32_t)_getpid(); + *seed ^= (uint32_t)GetCurrentProcessId(); #elif defined(HAVE_GETPID) *seed ^= (uint32_t)getpid(); #endif diff --git a/lib/cppmyth/jansson/src/jansson.def b/lib/cppmyth/jansson/src/jansson.def index 19096d420..da4cfd40d 100644 --- a/lib/cppmyth/jansson/src/jansson.def +++ b/lib/cppmyth/jansson/src/jansson.def @@ -4,10 +4,15 @@ EXPORTS json_false json_null json_string + json_stringn json_string_nocheck + json_stringn_nocheck json_string_value + json_string_length json_string_set + json_string_setn json_string_set_nocheck + json_string_setn_nocheck json_integer json_integer_value json_integer_set diff --git a/lib/cppmyth/jansson/src/jansson.h b/lib/cppmyth/jansson/src/jansson.h index 3f67edf19..b06ab9c18 100644 --- a/lib/cppmyth/jansson/src/jansson.h +++ b/lib/cppmyth/jansson/src/jansson.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -21,11 +21,11 @@ extern "C" { /* version */ #define JANSSON_MAJOR_VERSION 2 -#define JANSSON_MINOR_VERSION 6 +#define JANSSON_MINOR_VERSION 7 #define JANSSON_MICRO_VERSION 0 /* Micro version is omitted if it's 0 */ -#define JANSSON_VERSION "2.6" +#define JANSSON_VERSION "2.7" /* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */ @@ -67,23 +67,26 @@ typedef long json_int_t; #endif #define json_typeof(json) ((json)->type) -#define json_is_object(json) (json && json_typeof(json) == JSON_OBJECT) -#define json_is_array(json) (json && json_typeof(json) == JSON_ARRAY) -#define json_is_string(json) (json && json_typeof(json) == JSON_STRING) -#define json_is_integer(json) (json && json_typeof(json) == JSON_INTEGER) -#define json_is_real(json) (json && json_typeof(json) == JSON_REAL) +#define json_is_object(json) ((json) && json_typeof(json) == JSON_OBJECT) +#define json_is_array(json) ((json) && json_typeof(json) == JSON_ARRAY) +#define json_is_string(json) ((json) && json_typeof(json) == JSON_STRING) +#define json_is_integer(json) ((json) && json_typeof(json) == JSON_INTEGER) +#define json_is_real(json) ((json) && json_typeof(json) == JSON_REAL) #define json_is_number(json) (json_is_integer(json) || json_is_real(json)) -#define json_is_true(json) (json && json_typeof(json) == JSON_TRUE) -#define json_is_false(json) (json && json_typeof(json) == JSON_FALSE) +#define json_is_true(json) ((json) && json_typeof(json) == JSON_TRUE) +#define json_is_false(json) ((json) && json_typeof(json) == JSON_FALSE) +#define json_boolean_value json_is_true #define json_is_boolean(json) (json_is_true(json) || json_is_false(json)) -#define json_is_null(json) (json && json_typeof(json) == JSON_NULL) +#define json_is_null(json) ((json) && json_typeof(json) == JSON_NULL) /* construction, destruction, reference counting */ json_t *json_object(void); json_t *json_array(void); json_t *json_string(const char *value); +json_t *json_stringn(const char *value, size_t len); json_t *json_string_nocheck(const char *value); +json_t *json_stringn_nocheck(const char *value, size_t len); json_t *json_integer(json_int_t value); json_t *json_real(double value); json_t *json_true(void); @@ -200,16 +203,18 @@ int json_array_insert(json_t *array, size_t ind, json_t *value) } const char *json_string_value(const json_t *string); +size_t json_string_length(const json_t *string); json_int_t json_integer_value(const json_t *integer); double json_real_value(const json_t *real); double json_number_value(const json_t *json); int json_string_set(json_t *string, const char *value); +int json_string_setn(json_t *string, const char *value, size_t len); int json_string_set_nocheck(json_t *string, const char *value); +int json_string_setn_nocheck(json_t *string, const char *value, size_t len); int json_integer_set(json_t *integer, json_int_t value); int json_real_set(json_t *real, double value); - /* pack, unpack */ json_t *json_pack(const char *fmt, ...); @@ -241,6 +246,7 @@ json_t *json_deep_copy(const json_t *value); #define JSON_DISABLE_EOF_CHECK 0x2 #define JSON_DECODE_ANY 0x4 #define JSON_DECODE_INT_AS_REAL 0x8 +#define JSON_ALLOW_NUL 0x10 typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data); @@ -253,13 +259,15 @@ json_t *json_load_callback(json_load_callback_t callback, void *data, size_t fla /* encoding */ -#define JSON_INDENT(n) (n & 0x1F) -#define JSON_COMPACT 0x20 -#define JSON_ENSURE_ASCII 0x40 -#define JSON_SORT_KEYS 0x80 -#define JSON_PRESERVE_ORDER 0x100 -#define JSON_ENCODE_ANY 0x200 -#define JSON_ESCAPE_SLASH 0x400 +#define JSON_MAX_INDENT 0x1F +#define JSON_INDENT(n) ((n) & JSON_MAX_INDENT) +#define JSON_COMPACT 0x20 +#define JSON_ENSURE_ASCII 0x40 +#define JSON_SORT_KEYS 0x80 +#define JSON_PRESERVE_ORDER 0x100 +#define JSON_ENCODE_ANY 0x200 +#define JSON_ESCAPE_SLASH 0x400 +#define JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11) typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data); diff --git a/lib/cppmyth/jansson/src/jansson_config.h.in b/lib/cppmyth/jansson/src/jansson_config.h.in index 785801f27..12580a0a8 100644 --- a/lib/cppmyth/jansson/src/jansson_config.h.in +++ b/lib/cppmyth/jansson/src/jansson_config.h.in @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Petri Lehtinen + * Copyright (c) 2010-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/src/jansson_private.h b/lib/cppmyth/jansson/src/jansson_private.h index 403b53a4d..e10072608 100644 --- a/lib/cppmyth/jansson/src/jansson_private.h +++ b/lib/cppmyth/jansson/src/jansson_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -49,6 +49,7 @@ typedef struct { typedef struct { json_t json; char *value; + size_t length; } json_string_t; typedef struct { @@ -64,9 +65,13 @@ typedef struct { #define json_to_object(json_) container_of(json_, json_object_t, json) #define json_to_array(json_) container_of(json_, json_array_t, json) #define json_to_string(json_) container_of(json_, json_string_t, json) -#define json_to_real(json_) container_of(json_, json_real_t, json) +#define json_to_real(json_) container_of(json_, json_real_t, json) #define json_to_integer(json_) container_of(json_, json_integer_t, json) +/* Create a string by taking ownership of an existing buffer */ +json_t *jsonp_stringn_nocheck_own(const char *value, size_t len); + +/* Error message formatting */ void jsonp_error_init(json_error_t *error, const char *source); void jsonp_error_set_source(json_error_t *error, const char *source); void jsonp_error_set(json_error_t *error, int line, int column, @@ -76,13 +81,14 @@ void jsonp_error_vset(json_error_t *error, int line, int column, /* Locale independent string<->double conversions */ int jsonp_strtod(strbuffer_t *strbuffer, double *out); -int jsonp_dtostr(char *buffer, size_t size, double value); +int jsonp_dtostr(char *buffer, size_t size, double value, int prec); /* Wrappers for custom memory functions */ void* jsonp_malloc(size_t size); void jsonp_free(void *ptr); char *jsonp_strndup(const char *str, size_t length); char *jsonp_strdup(const char *str); +char *jsonp_strndup(const char *str, size_t len); /* Windows compatibility */ #ifdef _WIN32 diff --git a/lib/cppmyth/jansson/src/load.c b/lib/cppmyth/jansson/src/load.c index c5536f586..e96f8feb2 100644 --- a/lib/cppmyth/jansson/src/load.c +++ b/lib/cppmyth/jansson/src/load.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -63,7 +63,10 @@ typedef struct { strbuffer_t saved_text; int token; union { - char *string; + struct { + char *val; + size_t len; + } string; json_int_t integer; double real; } value; @@ -166,7 +169,7 @@ static int stream_get(stream_t *stream, json_error_t *error) if(0x80 <= c && c <= 0xFF) { /* multi-byte UTF-8 sequence */ - int i, count; + size_t i, count; count = utf8_check_first(c); if(!count) @@ -262,7 +265,7 @@ static void lex_unget_unsave(lex_t *lex, int c) #endif stream_unget(&lex->stream, c); #ifndef NDEBUG - d = + d = #endif strbuffer_pop(&lex->saved_text); assert(c == d); @@ -279,6 +282,13 @@ static void lex_save_cached(lex_t *lex) } } +static void lex_free_string(lex_t *lex) +{ + jsonp_free(lex->value.string.val); + lex->value.string.val = NULL; + lex->value.string.len = 0; +} + /* assumes that str points to 'u' plus at least 4 valid hex digits */ static int32_t decode_unicode_escape(const char *str) { @@ -297,7 +307,7 @@ static int32_t decode_unicode_escape(const char *str) else if(l_isupper(c)) value += c - 'A' + 10; else - assert(0); + return -1; } return value; @@ -310,7 +320,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error) char *t; int i; - lex->value.string = NULL; + lex->value.string.val = NULL; lex->token = TOKEN_INVALID; c = lex_get_save(lex, error); @@ -365,14 +375,12 @@ static void lex_scan_string(lex_t *lex, json_error_t *error) - two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair are converted to 4 bytes */ - lex->value.string = jsonp_malloc(lex->saved_text.length + 1); - if(!lex->value.string) { + t = jsonp_malloc(lex->saved_text.length + 1); + if(!t) { /* this is not very nice, since TOKEN_INVALID is returned */ goto out; } - - /* the target */ - t = lex->value.string; + lex->value.string.val = t; /* + 1 to skip the " */ p = strbuffer_value(&lex->saved_text) + 1; @@ -381,17 +389,24 @@ static void lex_scan_string(lex_t *lex, json_error_t *error) if(*p == '\\') { p++; if(*p == 'u') { - char buffer[4]; - int length; + size_t length; int32_t value; value = decode_unicode_escape(p); + if(value < 0) { + error_set(error, lex, "invalid Unicode escape '%.6s'", p - 1); + goto out; + } p += 5; if(0xD800 <= value && value <= 0xDBFF) { /* surrogate pair */ if(*p == '\\' && *(p + 1) == 'u') { int32_t value2 = decode_unicode_escape(++p); + if(value2 < 0) { + error_set(error, lex, "invalid Unicode escape '%.6s'", p - 1); + goto out; + } p += 5; if(0xDC00 <= value2 && value2 <= 0xDFFF) { @@ -420,16 +435,9 @@ static void lex_scan_string(lex_t *lex, json_error_t *error) error_set(error, lex, "invalid Unicode '\\u%04X'", value); goto out; } - else if(value == 0) - { - error_set(error, lex, "\\u0000 is not allowed"); - goto out; - } - if(utf8_encode(value, buffer, &length)) + if(utf8_encode(value, t, &length)) assert(0); - - memcpy(t, buffer, length); t += length; } else { @@ -451,11 +459,12 @@ static void lex_scan_string(lex_t *lex, json_error_t *error) *(t++) = *(p++); } *t = '\0'; + lex->value.string.len = t - lex->value.string.val; lex->token = TOKEN_STRING; return; out: - jsonp_free(lex->value.string); + lex_free_string(lex); } #ifndef JANSSON_USING_CMAKE /* disabled if using cmake */ @@ -474,7 +483,7 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error) { const char *saved_text; char *end; - double value; + double doubleval; lex->token = TOKEN_INVALID; @@ -499,16 +508,16 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error) } if(c != '.' && c != 'E' && c != 'e') { - json_int_t value; + json_int_t intval; lex_unget_unsave(lex, c); saved_text = strbuffer_value(&lex->saved_text); errno = 0; - value = json_strtoint(saved_text, &end, 10); + intval = json_strtoint(saved_text, &end, 10); if(errno == ERANGE) { - if(value < 0) + if(intval < 0) error_set(error, lex, "too big negative integer"); else error_set(error, lex, "too big integer"); @@ -518,7 +527,7 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error) assert(end == saved_text + lex->saved_text.length); lex->token = TOKEN_INTEGER; - lex->value.integer = value; + lex->value.integer = intval; return 0; } @@ -552,13 +561,13 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error) lex_unget_unsave(lex, c); - if(jsonp_strtod(&lex->saved_text, &value)) { + if(jsonp_strtod(&lex->saved_text, &doubleval)) { error_set(error, lex, "real number overflow"); goto out; } lex->token = TOKEN_REAL; - lex->value.real = value; + lex->value.real = doubleval; return 0; out: @@ -571,10 +580,8 @@ static int lex_scan(lex_t *lex, json_error_t *error) strbuffer_clear(&lex->saved_text); - if(lex->token == TOKEN_STRING) { - jsonp_free(lex->value.string); - lex->value.string = NULL; - } + if(lex->token == TOKEN_STRING) + lex_free_string(lex); c = lex_get(lex, error); while(c == ' ' || c == '\t' || c == '\n' || c == '\r') @@ -635,13 +642,14 @@ static int lex_scan(lex_t *lex, json_error_t *error) return lex->token; } -static char *lex_steal_string(lex_t *lex) +static char *lex_steal_string(lex_t *lex, size_t *out_len) { char *result = NULL; - if(lex->token == TOKEN_STRING) - { - result = lex->value.string; - lex->value.string = NULL; + if(lex->token == TOKEN_STRING) { + result = lex->value.string.val; + *out_len = lex->value.string.len; + lex->value.string.val = NULL; + lex->value.string.len = 0; } return result; } @@ -659,7 +667,7 @@ static int lex_init(lex_t *lex, get_func get, void *data) static void lex_close(lex_t *lex) { if(lex->token == TOKEN_STRING) - jsonp_free(lex->value.string); + lex_free_string(lex); strbuffer_close(&lex->saved_text); } @@ -680,6 +688,7 @@ static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error) while(1) { char *key; + size_t len; json_t *value; if(lex->token != TOKEN_STRING) { @@ -687,9 +696,14 @@ static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error) goto error; } - key = lex_steal_string(lex); + key = lex_steal_string(lex, &len); if(!key) return NULL; + if (memchr(key, '\0', len)) { + jsonp_free(key); + error_set(error, lex, "NUL byte in object key not supported"); + goto error; + } if(flags & JSON_REJECT_DUPLICATES) { if(json_object_get(object, key)) { @@ -788,7 +802,21 @@ static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error) switch(lex->token) { case TOKEN_STRING: { - json = json_string_nocheck(lex->value.string); + const char *value = lex->value.string.val; + size_t len = lex->value.string.len; + + if(!(flags & JSON_ALLOW_NUL)) { + if(memchr(value, '\0', len)) { + error_set(error, lex, "\\u0000 is not allowed without JSON_ALLOW_NUL"); + return NULL; + } + } + + json = jsonp_stringn_nocheck_own(value, len); + if(json) { + lex->value.string.val = NULL; + lex->value.string.len = 0; + } break; } @@ -872,7 +900,7 @@ static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error) if(error) { /* Save the position even though there was no error */ - error->position = lex->stream.position; + error->position = (int)lex->stream.position; } return result; diff --git a/lib/cppmyth/jansson/src/lookup3.h b/lib/cppmyth/jansson/src/lookup3.h index dc76138c9..522a41ae6 100644 --- a/lib/cppmyth/jansson/src/lookup3.h +++ b/lib/cppmyth/jansson/src/lookup3.h @@ -37,7 +37,7 @@ on 1 byte), but shoehorning those bytes into integers efficiently is messy. #include #ifdef HAVE_CONFIG_H -#include +#include #endif #ifdef HAVE_STDINT_H @@ -205,7 +205,22 @@ static uint32_t hashlittle(const void *key, size_t length, uint32_t initval) if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ +/* Detect Valgrind or AddressSanitizer */ #ifdef VALGRIND +# define NO_MASKING_TRICK 1 +#else +# if defined(__has_feature) /* Clang */ +# if __has_feature(address_sanitizer) /* is ASAN enabled? */ +# define NO_MASKING_TRICK 1 +# endif +# else +# if defined(__SANITIZE_ADDRESS__) /* GCC 4.8.x, is ASAN enabled? */ +# define NO_MASKING_TRICK 1 +# endif +# endif +#endif + +#ifdef NO_MASKING_TRICK const uint8_t *k8; #endif @@ -230,7 +245,7 @@ static uint32_t hashlittle(const void *key, size_t length, uint32_t initval) * still catch it and complain. The masking trick does make the hash * noticably faster for short strings (like English words). */ -#ifndef VALGRIND +#ifndef NO_MASKING_TRICK switch(length) { diff --git a/lib/cppmyth/jansson/src/memory.c b/lib/cppmyth/jansson/src/memory.c index eb6cec542..ca44d6b23 100644 --- a/lib/cppmyth/jansson/src/memory.c +++ b/lib/cppmyth/jansson/src/memory.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * Copyright (c) 2011-2012 Basile Starynkevitch * * Jansson is free software; you can redistribute it and/or modify it @@ -12,6 +12,10 @@ #include "jansson.h" #include "jansson_private.h" +/* C89 allows these to be macros */ +#undef malloc +#undef free + /* memory function pointers */ static json_malloc_t do_malloc = malloc; static json_free_t do_free = free; @@ -34,18 +38,19 @@ void jsonp_free(void *ptr) char *jsonp_strdup(const char *str) { - char *new_str; - size_t len; + return jsonp_strndup(str, strlen(str)); +} - len = strlen(str); - if(len == (size_t)-1) - return NULL; +char *jsonp_strndup(const char *str, size_t len) +{ + char *new_str; new_str = jsonp_malloc(len + 1); if(!new_str) return NULL; - memcpy(new_str, str, len + 1); + memcpy(new_str, str, len); + new_str[len] = '\0'; return new_str; } diff --git a/lib/cppmyth/jansson/src/pack_unpack.c b/lib/cppmyth/jansson/src/pack_unpack.c index 0d932f791..af381a50b 100644 --- a/lib/cppmyth/jansson/src/pack_unpack.c +++ b/lib/cppmyth/jansson/src/pack_unpack.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * Copyright (c) 2011-2012 Graeme Smecher * * Jansson is free software; you can redistribute it and/or modify @@ -125,19 +125,18 @@ static json_t *pack(scanner_t *s, va_list *ap); /* ours will be set to 1 if jsonp_free() must be called for the result afterwards */ static char *read_string(scanner_t *s, va_list *ap, - const char *purpose, int *ours) + const char *purpose, size_t *out_len, int *ours) { char t; strbuffer_t strbuff; const char *str; size_t length; - char *result; next_token(s); t = token(s); prev_token(s); - if(t != '#' && t != '+') { + if(t != '#' && t != '%' && t != '+') { /* Optimize the simple case */ str = va_arg(*ap, const char *); @@ -146,11 +145,14 @@ static char *read_string(scanner_t *s, va_list *ap, return NULL; } - if(!utf8_check_string(str, -1)) { + length = strlen(str); + + if(!utf8_check_string(str, length)) { set_error(s, "", "Invalid UTF-8 %s", purpose); return NULL; } + *out_len = length; *ours = 0; return (char *)str; } @@ -170,6 +172,9 @@ static char *read_string(scanner_t *s, va_list *ap, if(token(s) == '#') { length = va_arg(*ap, int); } + else if(token(s) == '%') { + length = va_arg(*ap, size_t); + } else { prev_token(s); length = strlen(str); @@ -188,15 +193,15 @@ static char *read_string(scanner_t *s, va_list *ap, } } - result = strbuffer_steal_value(&strbuff); - - if(!utf8_check_string(result, -1)) { + if(!utf8_check_string(strbuff.value, strbuff.length)) { set_error(s, "", "Invalid UTF-8 %s", purpose); + strbuffer_close(&strbuff); return NULL; } + *out_len = strbuff.length; *ours = 1; - return result; + return strbuffer_steal_value(&strbuff); } static json_t *pack_object(scanner_t *s, va_list *ap) @@ -206,6 +211,7 @@ static json_t *pack_object(scanner_t *s, va_list *ap) while(token(s) != '}') { char *key; + size_t len; int ours; json_t *value; @@ -219,15 +225,19 @@ static json_t *pack_object(scanner_t *s, va_list *ap) goto error; } - key = read_string(s, ap, "object key", &ours); + key = read_string(s, ap, "object key", &len, &ours); if(!key) goto error; next_token(s); value = pack(s, ap); - if(!value) + if(!value) { + if(ours) + jsonp_free(key); + goto error; + } if(json_object_set_new_nocheck(object, key, value)) { if(ours) @@ -290,20 +300,20 @@ static json_t *pack(scanner_t *s, va_list *ap) case '[': return pack_array(s, ap); - case 's': { /* string */ + case 's': /* string */ + { char *str; + size_t len; int ours; - json_t *result; - str = read_string(s, ap, "string", &ours); + str = read_string(s, ap, "string", &len, &ours); if(!str) return NULL; - result = json_string_nocheck(str); - if(ours) - jsonp_free(str); - - return result; + if (ours) + return jsonp_stringn_nocheck_own(str, len); + else + return json_stringn_nocheck(str, len); } case 'n': /* null */ @@ -340,6 +350,7 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap) { int ret = -1; int strict = 0; + int gotopt = 0; /* Use a set (emulated by a hashtable) to check that all object keys are accessed. Checking that the correct number of keys @@ -396,7 +407,7 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap) next_token(s); if(token(s) == '?') { - opt = 1; + opt = gotopt = 1; next_token(s); } @@ -422,10 +433,26 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap) if(strict == 0 && (s->flags & JSON_STRICT)) strict = 1; - if(root && strict == 1 && key_set.size != json_object_size(root)) { - long diff = (long)json_object_size(root) - (long)key_set.size; - set_error(s, "", "%li object item(s) left unpacked", diff); - goto out; + if(root && strict == 1) { + /* We need to check that all non optional items have been parsed */ + const char *key; + json_t *value; + long unpacked = 0; + if (gotopt) { + /* We have optional keys, we need to iter on each key */ + json_object_foreach(root, key, value) { + if(!hashtable_get(&key_set, key)) { + unpacked++; + } + } + } else { + /* No optional keys, we can just compare the number of items */ + unpacked = (long)json_object_size(root) - (long)key_set.size; + } + if (unpacked) { + set_error(s, "", "%li object item(s) left unpacked", unpacked); + goto out; + } } ret = 0; @@ -523,16 +550,32 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap) } if(!(s->flags & JSON_VALIDATE_ONLY)) { - const char **target; + const char **str_target; + size_t *len_target = NULL; - target = va_arg(*ap, const char **); - if(!target) { + str_target = va_arg(*ap, const char **); + if(!str_target) { set_error(s, "", "NULL string argument"); return -1; } - if(root) - *target = json_string_value(root); + next_token(s); + + if(token(s) == '%') { + len_target = va_arg(*ap, size_t *); + if(!len_target) { + set_error(s, "", "NULL string length argument"); + return -1; + } + } + else + prev_token(s); + + if(root) { + *str_target = json_string_value(root); + if(len_target) + *len_target = json_string_length(root); + } } return 0; diff --git a/lib/cppmyth/jansson/src/strbuffer.c b/lib/cppmyth/jansson/src/strbuffer.c index 2d6ff3105..b3ddd0e73 100644 --- a/lib/cppmyth/jansson/src/strbuffer.c +++ b/lib/cppmyth/jansson/src/strbuffer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/src/strbuffer.h b/lib/cppmyth/jansson/src/strbuffer.h index 06fd065bb..fc11ec064 100644 --- a/lib/cppmyth/jansson/src/strbuffer.h +++ b/lib/cppmyth/jansson/src/strbuffer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/src/strconv.c b/lib/cppmyth/jansson/src/strconv.c index 3e2cb7c4c..c3563b9d0 100644 --- a/lib/cppmyth/jansson/src/strconv.c +++ b/lib/cppmyth/jansson/src/strconv.c @@ -2,12 +2,13 @@ #include #include #include +#include #include "jansson_private.h" #include "strbuffer.h" -/* need config.h to get the correct snprintf */ +/* need jansson_private_config.h to get the correct snprintf */ #ifdef HAVE_CONFIG_H -#include +#include #endif #if JSON_HAVE_LOCALECONV @@ -69,7 +70,7 @@ int jsonp_strtod(strbuffer_t *strbuffer, double *out) value = strtod(strbuffer->value, &end); assert(end == strbuffer->value + strbuffer->length); - if(errno == ERANGE && value != 0) { + if((value == HUGE_VAL || value == -HUGE_VAL) && errno == ERANGE) { /* Overflow */ return -1; } @@ -78,13 +79,16 @@ int jsonp_strtod(strbuffer_t *strbuffer, double *out) return 0; } -int jsonp_dtostr(char *buffer, size_t size, double value) +int jsonp_dtostr(char *buffer, size_t size, double value, int precision) { int ret; char *start, *end; size_t length; - ret = snprintf(buffer, size, "%.17g", value); + if (precision == 0) + precision = 17; + + ret = snprintf(buffer, size, "%.*g", precision, value); if(ret < 0) return -1; diff --git a/lib/cppmyth/jansson/src/utf.c b/lib/cppmyth/jansson/src/utf.c index 65b849b89..b56e1250f 100644 --- a/lib/cppmyth/jansson/src/utf.c +++ b/lib/cppmyth/jansson/src/utf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -8,7 +8,7 @@ #include #include "utf.h" -int utf8_encode(int32_t codepoint, char *buffer, int *size) +int utf8_encode(int32_t codepoint, char *buffer, size_t *size) { if(codepoint < 0) return -1; @@ -44,7 +44,7 @@ int utf8_encode(int32_t codepoint, char *buffer, int *size) return 0; } -int utf8_check_first(char byte) +size_t utf8_check_first(char byte) { unsigned char u = (unsigned char)byte; @@ -80,9 +80,9 @@ int utf8_check_first(char byte) } } -int utf8_check_full(const char *buffer, int size, int32_t *codepoint) +size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint) { - int i; + size_t i; int32_t value = 0; unsigned char u = (unsigned char)buffer[0]; @@ -136,12 +136,12 @@ int utf8_check_full(const char *buffer, int size, int32_t *codepoint) return 1; } -const char *utf8_iterate(const char *buffer, int32_t *codepoint) +const char *utf8_iterate(const char *buffer, size_t bufsize, int32_t *codepoint) { - int count; + size_t count; int32_t value; - if(!*buffer) + if(!bufsize) return buffer; count = utf8_check_first(buffer[0]); @@ -152,7 +152,7 @@ const char *utf8_iterate(const char *buffer, int32_t *codepoint) value = (unsigned char)buffer[0]; else { - if(!utf8_check_full(buffer, count, &value)) + if(count > bufsize || !utf8_check_full(buffer, count, &value)) return NULL; } @@ -162,21 +162,18 @@ const char *utf8_iterate(const char *buffer, int32_t *codepoint) return buffer + count; } -int utf8_check_string(const char *string, int length) +int utf8_check_string(const char *string, size_t length) { - int i; - - if(length == -1) - length = strlen(string); + size_t i; for(i = 0; i < length; i++) { - int count = utf8_check_first(string[i]); + size_t count = utf8_check_first(string[i]); if(count == 0) return 0; else if(count > 1) { - if(i + count > length) + if(count > length - i) return 0; if(!utf8_check_full(&string[i], count, NULL)) diff --git a/lib/cppmyth/jansson/src/utf.h b/lib/cppmyth/jansson/src/utf.h index b4f109143..2cebea012 100644 --- a/lib/cppmyth/jansson/src/utf.h +++ b/lib/cppmyth/jansson/src/utf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -9,19 +9,19 @@ #define UTF_H #ifdef HAVE_CONFIG_H -#include +#include #endif #ifdef HAVE_STDINT_H #include #endif -int utf8_encode(int codepoint, char *buffer, int *size); +int utf8_encode(int32_t codepoint, char *buffer, size_t *size); -int utf8_check_first(char byte); -int utf8_check_full(const char *buffer, int size, int32_t *codepoint); -const char *utf8_iterate(const char *buffer, int32_t *codepoint); +size_t utf8_check_first(char byte); +size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint); +const char *utf8_iterate(const char *buffer, size_t size, int32_t *codepoint); -int utf8_check_string(const char *string, int length); +int utf8_check_string(const char *string, size_t length); #endif diff --git a/lib/cppmyth/jansson/src/value.c b/lib/cppmyth/jansson/src/value.c index 1b02d90aa..333d0af37 100644 --- a/lib/cppmyth/jansson/src/value.c +++ b/lib/cppmyth/jansson/src/value.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -10,7 +10,7 @@ #endif #ifdef HAVE_CONFIG_H -#include +#include #endif #include @@ -29,8 +29,10 @@ /* Work around nonstandard isnan() and isinf() implementations */ #ifndef isnan +#ifndef __sun static JSON_INLINE int isnan(double x) { return x != x; } #endif +#endif #ifndef isinf static JSON_INLINE int isinf(double x) { return !isnan(x) && isnan(x - x); } #endif @@ -92,7 +94,7 @@ json_t *json_object_get(const json_t *json, const char *key) { json_object_t *object; - if(!json_is_object(json)) + if(!key || !json_is_object(json)) return NULL; object = json_to_object(json); @@ -124,7 +126,7 @@ int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value) int json_object_set_new(json_t *json, const char *key, json_t *value) { - if(!key || !utf8_check_string(key, -1)) + if(!key || !utf8_check_string(key, strlen(key))) { json_decref(value); return -1; @@ -137,7 +139,7 @@ int json_object_del(json_t *json, const char *key) { json_object_t *object; - if(!json_is_object(json)) + if(!key || !json_is_object(json)) return -1; object = json_to_object(json); @@ -636,33 +638,68 @@ static json_t *json_array_deep_copy(const json_t *array) /*** string ***/ -json_t *json_string_nocheck(const char *value) +static json_t *string_create(const char *value, size_t len, int own) { + char *v; json_string_t *string; if(!value) return NULL; + if(own) + v = (char *)value; + else { + v = jsonp_strndup(value, len); + if(!v) + return NULL; + } + string = jsonp_malloc(sizeof(json_string_t)); - if(!string) + if(!string) { + if(!own) + jsonp_free(v); return NULL; + } json_init(&string->json, JSON_STRING); + string->value = v; + string->length = len; - string->value = jsonp_strdup(value); - if(!string->value) { - jsonp_free(string); + return &string->json; +} + +json_t *json_string_nocheck(const char *value) +{ + if(!value) return NULL; - } - return &string->json; + return string_create(value, strlen(value), 0); +} + +json_t *json_stringn_nocheck(const char *value, size_t len) +{ + return string_create(value, len, 0); +} + +/* this is private; "steal" is not a public API concept */ +json_t *jsonp_stringn_nocheck_own(const char *value, size_t len) +{ + return string_create(value, len, 1); } json_t *json_string(const char *value) { - if(!value || !utf8_check_string(value, -1)) + if(!value) return NULL; - return json_string_nocheck(value); + return json_stringn(value, strlen(value)); +} + +json_t *json_stringn(const char *value, size_t len) +{ + if(!value || !utf8_check_string(value, len)) + return NULL; + + return json_stringn_nocheck(value, len); } const char *json_string_value(const json_t *json) @@ -673,7 +710,23 @@ const char *json_string_value(const json_t *json) return json_to_string(json)->value; } +size_t json_string_length(const json_t *json) +{ + if(!json_is_string(json)) + return 0; + + return json_to_string(json)->length; +} + int json_string_set_nocheck(json_t *json, const char *value) +{ + if(!value) + return -1; + + return json_string_setn_nocheck(json, value, strlen(value)); +} + +int json_string_setn_nocheck(json_t *json, const char *value, size_t len) { char *dup; json_string_t *string; @@ -681,23 +734,32 @@ int json_string_set_nocheck(json_t *json, const char *value) if(!json_is_string(json) || !value) return -1; - dup = jsonp_strdup(value); + dup = jsonp_strndup(value, len); if(!dup) return -1; string = json_to_string(json); jsonp_free(string->value); string->value = dup; + string->length = len; return 0; } int json_string_set(json_t *json, const char *value) { - if(!value || !utf8_check_string(value, -1)) + if(!value) + return -1; + + return json_string_setn(json, value, strlen(value)); +} + +int json_string_setn(json_t *json, const char *value, size_t len) +{ + if(!value || !utf8_check_string(value, len)) return -1; - return json_string_set_nocheck(json, value); + return json_string_setn_nocheck(json, value, len); } static void json_delete_string(json_string_t *string) @@ -708,12 +770,25 @@ static void json_delete_string(json_string_t *string) static int json_string_equal(json_t *string1, json_t *string2) { - return strcmp(json_string_value(string1), json_string_value(string2)) == 0; + json_string_t *s1, *s2; + + if(!json_is_string(string1) || !json_is_string(string2)) + return 0; + + s1 = json_to_string(string1); + s2 = json_to_string(string2); + return s1->length == s2->length && !memcmp(s1->value, s2->value, s1->length); } static json_t *json_string_copy(const json_t *string) { - return json_string_nocheck(json_string_value(string)); + json_string_t *s; + + if(!json_is_string(string)) + return NULL; + + s = json_to_string(string); + return json_stringn_nocheck(s->value, s->length); } diff --git a/lib/cppmyth/jansson/test/bin/json_process.c b/lib/cppmyth/jansson/test/bin/json_process.c index e2c54bd12..bbb7da8c9 100644 --- a/lib/cppmyth/jansson/test/bin/json_process.c +++ b/lib/cppmyth/jansson/test/bin/json_process.c @@ -1,12 +1,12 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifdef HAVE_CONFIG_H -#include +#include #endif #include @@ -39,6 +39,7 @@ struct config { int use_env; int have_hashseed; int hashseed; + int precision; } conf; #define l_isspace(c) ((c) == ' ' || (c) == '\n' || (c) == '\r' || (c) == '\t') @@ -108,6 +109,8 @@ static void read_conf(FILE *conffile) conf.preserve_order = atoi(val); if (!strcmp(line, "JSON_SORT_KEYS")) conf.sort_keys = atoi(val); + if (!strcmp(line, "JSON_REAL_PRECISION")) + conf.precision = atoi(val); if (!strcmp(line, "STRIP")) conf.strip = atoi(val); if (!strcmp(line, "HASHSEED")) { @@ -176,11 +179,11 @@ int use_conf(char *test_path) fclose(conffile); } - if (conf.indent < 0 || conf.indent > 255) { + if (conf.indent < 0 || conf.indent > 31) { fprintf(stderr, "invalid value for JSON_INDENT: %d\n", conf.indent); + fclose(infile); return 2; } - if (conf.indent) flags |= JSON_INDENT(conf.indent); @@ -196,6 +199,15 @@ int use_conf(char *test_path) if (conf.sort_keys) flags |= JSON_SORT_KEYS; + if (conf.precision < 0 || conf.precision > 31) { + fprintf(stderr, "invalid value for JSON_REAL_PRECISION: %d\n", + conf.precision); + fclose(infile); + return 2; + } + if (conf.precision) + flags |= JSON_REAL_PRECISION(conf.precision); + if (conf.have_hashseed) json_object_seed(conf.hashseed); @@ -245,7 +257,7 @@ static int getenv_int(const char *name) int use_env() { - int indent; + int indent, precision; size_t flags = 0; json_t *json; json_error_t error; @@ -258,11 +270,10 @@ int use_env() #endif indent = getenv_int("JSON_INDENT"); - if(indent < 0 || indent > 255) { + if(indent < 0 || indent > 31) { fprintf(stderr, "invalid value for JSON_INDENT: %d\n", indent); return 2; } - if(indent > 0) flags |= JSON_INDENT(indent); @@ -278,23 +289,35 @@ int use_env() if(getenv_int("JSON_SORT_KEYS")) flags |= JSON_SORT_KEYS; + precision = getenv_int("JSON_REAL_PRECISION"); + if(precision < 0 || precision > 31) { + fprintf(stderr, "invalid value for JSON_REAL_PRECISION: %d\n", + precision); + return 2; + } + if(getenv("HASHSEED")) json_object_seed(getenv_int("HASHSEED")); + if(precision > 0) + flags |= JSON_REAL_PRECISION(precision); + if(getenv_int("STRIP")) { /* Load to memory, strip leading and trailing whitespace */ size_t size = 0, used = 0; - char *buffer = NULL; + char *buffer = NULL, *buf_ck = NULL; while(1) { size_t count; size = (size == 0 ? 128 : size * 2); - buffer = realloc(buffer, size); - if(!buffer) { + buf_ck = realloc(buffer, size); + if(!buf_ck) { fprintf(stderr, "Unable to allocate %d bytes\n", (int)size); + free(buffer); return 1; } + buffer = buf_ck; count = fread(buffer + used, 1, size - used, stdin); if(count < size - used) { diff --git a/lib/cppmyth/jansson/test/run-suites b/lib/cppmyth/jansson/test/run-suites index 4cbaa8b14..fd1b89b5a 100755 --- a/lib/cppmyth/jansson/test/run-suites +++ b/lib/cppmyth/jansson/test/run-suites @@ -34,15 +34,15 @@ failed=0 for suite in $SUITES; do echo "Suite: $suite" if $suites_srcdir/$suite/run $suite; then - passed=$(($passed+1)) + passed=`expr $passed + 1` else - failed=$(($failed+1)) + failed=`expr $failed + 1` [ $STOP -eq 1 ] && break fi done if [ $failed -gt 0 ]; then - echo "$failed of $((passed+failed)) test suites failed" + echo "$failed of `expr $passed + $failed` test suites failed" exit 1 else echo "$passed test suites passed" diff --git a/lib/cppmyth/jansson/test/scripts/run-tests.sh b/lib/cppmyth/jansson/test/scripts/run-tests.sh index 5ed3b9f73..b4433cb85 100644 --- a/lib/cppmyth/jansson/test/scripts/run-tests.sh +++ b/lib/cppmyth/jansson/test/scripts/run-tests.sh @@ -1,4 +1,4 @@ -# Copyright (c) 2009-2013 Petri Lehtinen +# Copyright (c) 2009-2014 Petri Lehtinen # # Jansson is free software; you can redistribute it and/or modify # it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/scripts/valgrind.sh b/lib/cppmyth/jansson/test/scripts/valgrind.sh index 9b0043885..7ddc7ea7a 100644 --- a/lib/cppmyth/jansson/test/scripts/valgrind.sh +++ b/lib/cppmyth/jansson/test/scripts/valgrind.sh @@ -1,4 +1,4 @@ -# Copyright (c) 2009-2013 Petri Lehtinen +# Copyright (c) 2009-2014 Petri Lehtinen # # Jansson is free software; you can redistribute it and/or modify # it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/api/run b/lib/cppmyth/jansson/test/suites/api/run index 5f8e95939..c127f3aee 100755 --- a/lib/cppmyth/jansson/test/suites/api/run +++ b/lib/cppmyth/jansson/test/suites/api/run @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2009-2013 Petri Lehtinen +# Copyright (c) 2009-2014 Petri Lehtinen # # Jansson is free software; you can redistribute it and/or modify # it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/api/test_array.c b/lib/cppmyth/jansson/test/suites/api/test_array.c index 0a9447fc8..f4927b4e7 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_array.c +++ b/lib/cppmyth/jansson/test/suites/api/test_array.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/api/test_copy.c b/lib/cppmyth/jansson/test/suites/api/test_copy.c index 580488d82..cf1f25a00 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_copy.c +++ b/lib/cppmyth/jansson/test/suites/api/test_copy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/api/test_dump.c b/lib/cppmyth/jansson/test/suites/api/test_dump.c index 64c086305..8731752ea 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_dump.c +++ b/lib/cppmyth/jansson/test/suites/api/test_dump.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -180,6 +180,20 @@ static void escape_slashes() json_decref(json); } +static void encode_nul_byte() +{ + json_t *json; + char *result; + + json = json_stringn("nul byte \0 in string", 20); + result = json_dumps(json, JSON_ENCODE_ANY); + if(!result || memcmp(result, "\"nul byte \\u0000 in string\"", 27)) + fail("json_dumps failed to dump an embedded NUL byte"); + + free(result); + json_decref(json); +} + static void run_tests() { encode_null(); @@ -187,4 +201,5 @@ static void run_tests() circular_references(); encode_other_than_array_or_object(); escape_slashes(); + encode_nul_byte(); } diff --git a/lib/cppmyth/jansson/test/suites/api/test_dump_callback.c b/lib/cppmyth/jansson/test/suites/api/test_dump_callback.c index 4536d5608..33c3c864c 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_dump_callback.c +++ b/lib/cppmyth/jansson/test/suites/api/test_dump_callback.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/api/test_equal.c b/lib/cppmyth/jansson/test/suites/api/test_equal.c index 354e5c9ea..31c43ba57 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_equal.c +++ b/lib/cppmyth/jansson/test/suites/api/test_equal.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/api/test_load.c b/lib/cppmyth/jansson/test/suites/api/test_load.c index 944b4d8f0..d4518534d 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_load.c +++ b/lib/cppmyth/jansson/test/suites/api/test_load.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -115,6 +115,26 @@ static void decode_int_as_real() #endif } +static void allow_nul() +{ + const char *text = "\"nul byte \\u0000 in string\""; + const char *expected = "nul byte \0 in string"; + size_t len = 20; + json_t *json; + + json = json_loads(text, JSON_ALLOW_NUL | JSON_DECODE_ANY, NULL); + if(!json || !json_is_string(json)) + fail("unable to decode embedded NUL byte"); + + if(json_string_length(json) != len) + fail("decoder returned wrong string length"); + + if(memcmp(json_string_value(json), expected, len + 1)) + fail("decoder returned wrong string content"); + + json_decref(json); +} + static void load_wrong_args() { json_t *json; @@ -161,6 +181,7 @@ static void run_tests() disable_eof_check(); decode_any(); decode_int_as_real(); + allow_nul(); load_wrong_args(); position(); } diff --git a/lib/cppmyth/jansson/test/suites/api/test_loadb.c b/lib/cppmyth/jansson/test/suites/api/test_loadb.c index fa5e96762..589f484b4 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_loadb.c +++ b/lib/cppmyth/jansson/test/suites/api/test_loadb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/api/test_number.c b/lib/cppmyth/jansson/test/suites/api/test_number.c index b506a2bcf..4651819d9 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_number.c +++ b/lib/cppmyth/jansson/test/suites/api/test_number.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/api/test_object.c b/lib/cppmyth/jansson/test/suites/api/test_object.c index 92e520822..5b30738f7 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_object.c +++ b/lib/cppmyth/jansson/test/suites/api/test_object.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/api/test_pack.c b/lib/cppmyth/jansson/test/suites/api/test_pack.c index b6ac2e55e..9a8a62c4c 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_pack.c +++ b/lib/cppmyth/jansson/test/suites/api/test_pack.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * Copyright (c) 2010-2012 Graeme Smecher * * Jansson is free software; you can redistribute it and/or modify @@ -7,7 +7,7 @@ */ #ifdef HAVE_CONFIG_H -#include +#include #endif #include @@ -83,7 +83,7 @@ static void run_tests() fail("json_pack string refcount failed"); json_decref(value); - /* string and length */ + /* string and length (int) */ value = json_pack("s#", "test asdf", 4); if(!json_is_string(value) || strcmp("test", json_string_value(value))) fail("json_pack string and length failed"); @@ -91,14 +91,30 @@ static void run_tests() fail("json_pack string and length refcount failed"); json_decref(value); - /* string and length, non-NUL terminated string */ - value = json_pack("s#", buffer, 4); + /* string and length (size_t) */ + value = json_pack("s%", "test asdf", (size_t)4); if(!json_is_string(value) || strcmp("test", json_string_value(value))) fail("json_pack string and length failed"); if(value->refcount != (size_t)1) fail("json_pack string and length refcount failed"); json_decref(value); + /* string and length (int), non-NUL terminated string */ + value = json_pack("s#", buffer, 4); + if(!json_is_string(value) || strcmp("test", json_string_value(value))) + fail("json_pack string and length (int) failed"); + if(value->refcount != (size_t)1) + fail("json_pack string and length (int) refcount failed"); + json_decref(value); + + /* string and length (size_t), non-NUL terminated string */ + value = json_pack("s%", buffer, (size_t)4); + if(!json_is_string(value) || strcmp("test", json_string_value(value))) + fail("json_pack string and length (size_t) failed"); + if(value->refcount != (size_t)1) + fail("json_pack string and length (size_t) refcount failed"); + json_decref(value); + /* string concatenation */ value = json_pack("s++", "te", "st", "ing"); if(!json_is_string(value) || strcmp("testing", json_string_value(value))) @@ -107,12 +123,20 @@ static void run_tests() fail("json_pack string concatenation refcount failed"); json_decref(value); - /* string concatenation and length */ + /* string concatenation and length (int) */ value = json_pack("s#+#+", "test", 1, "test", 2, "test"); if(!json_is_string(value) || strcmp("ttetest", json_string_value(value))) - fail("json_pack string concatenation and length failed"); + fail("json_pack string concatenation and length (int) failed"); + if(value->refcount != (size_t)1) + fail("json_pack string concatenation and length (int) refcount failed"); + json_decref(value); + + /* string concatenation and length (size_t) */ + value = json_pack("s%+%+", "test", (size_t)1, "test", (size_t)2, "test"); + if(!json_is_string(value) || strcmp("ttetest", json_string_value(value))) + fail("json_pack string concatenation and length (size_t) failed"); if(value->refcount != (size_t)1) - fail("json_pack string concatenation and length refcount failed"); + fail("json_pack string concatenation and length (size_t) refcount failed"); json_decref(value); /* empty object */ diff --git a/lib/cppmyth/jansson/test/suites/api/test_simple.c b/lib/cppmyth/jansson/test/suites/api/test_simple.c index d24d84e6b..8b5695444 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_simple.c +++ b/lib/cppmyth/jansson/test/suites/api/test_simple.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -27,6 +27,8 @@ static void run_tests() value = json_boolean(0); if(!json_is_false(value)) fail("json_boolean(0) failed"); + if(json_boolean_value(value) != 0) + fail("json_boolean_value failed"); json_decref(value); @@ -72,11 +74,22 @@ static void run_tests() fail("json_string failed"); if(strcmp(json_string_value(value), "foo")) fail("invalid string value"); + if (json_string_length(value) != 3) + fail("invalid string length"); - if(json_string_set(value, "bar")) + if(json_string_set(value, "barr")) fail("json_string_set failed"); - if(strcmp(json_string_value(value), "bar")) + if(strcmp(json_string_value(value), "barr")) fail("invalid string value"); + if (json_string_length(value) != 4) + fail("invalid string length"); + + if(json_string_setn(value, "hi\0ho", 5)) + fail("json_string_set failed"); + if(memcmp(json_string_value(value), "hi\0ho\0", 6)) + fail("invalid string value"); + if (json_string_length(value) != 5) + fail("invalid string length"); json_decref(value); @@ -94,11 +107,22 @@ static void run_tests() fail("json_string_nocheck failed"); if(strcmp(json_string_value(value), "foo")) fail("invalid string value"); + if (json_string_length(value) != 3) + fail("invalid string length"); - if(json_string_set_nocheck(value, "bar")) + if(json_string_set_nocheck(value, "barr")) fail("json_string_set_nocheck failed"); - if(strcmp(json_string_value(value), "bar")) + if(strcmp(json_string_value(value), "barr")) + fail("invalid string value"); + if (json_string_length(value) != 4) + fail("invalid string length"); + + if(json_string_setn_nocheck(value, "hi\0ho", 5)) + fail("json_string_set failed"); + if(memcmp(json_string_value(value), "hi\0ho\0", 6)) fail("invalid string value"); + if (json_string_length(value) != 5) + fail("invalid string length"); json_decref(value); @@ -108,11 +132,15 @@ static void run_tests() fail("json_string_nocheck failed"); if(strcmp(json_string_value(value), "qu\xff")) fail("invalid string value"); + if (json_string_length(value) != 3) + fail("invalid string length"); if(json_string_set_nocheck(value, "\xfd\xfe\xff")) fail("json_string_set_nocheck failed"); if(strcmp(json_string_value(value), "\xfd\xfe\xff")) fail("invalid string value"); + if (json_string_length(value) != 3) + fail("invalid string length"); json_decref(value); diff --git a/lib/cppmyth/jansson/test/suites/api/test_unpack.c b/lib/cppmyth/jansson/test/suites/api/test_unpack.c index bec866618..6b7610629 100644 --- a/lib/cppmyth/jansson/test/suites/api/test_unpack.c +++ b/lib/cppmyth/jansson/test/suites/api/test_unpack.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * Copyright (c) 2010-2012 Graeme Smecher * * Jansson is free software; you can redistribute it and/or modify @@ -17,6 +17,7 @@ static void run_tests() int i1, i2, i3; json_int_t I1; int rv; + size_t z; double f; char *s; @@ -81,6 +82,13 @@ static void run_tests() fail("json_unpack string failed"); json_decref(j); + /* string with length (size_t) */ + j = json_string("foo"); + rv = json_unpack(j, "s%", &s, &z); + if(rv || strcmp(s, "foo") || z != 3) + fail("json_unpack string with length (size_t) failed"); + json_decref(j); + /* empty object */ j = json_object(); if(json_unpack(j, "{}")) @@ -370,4 +378,23 @@ static void run_tests() if(i1 != 42) fail("json_unpack failed to unpack"); json_decref(j); + + /* Combine ? and ! */ + j = json_pack("{si}", "foo", 42); + i1 = i2 = 0; + if(json_unpack(j, "{sis?i!}", "foo", &i1, "bar", &i2)) + fail("json_unpack failed for optional values with strict mode"); + if(i1 != 42) + fail("json_unpack failed to unpack"); + if(i2 != 0) + fail("json_unpack failed to unpack"); + json_decref(j); + + /* But don't compensate a missing key with an optional one. */ + j = json_pack("{sisi}", "foo", 42, "baz", 43); + i1 = i2 = i3 = 0; + if(!json_unpack_ex(j, &error, 0, "{sis?i!}", "foo", &i1, "bar", &i2)) + fail("json_unpack failed for optional values with strict mode and compensation"); + check_error("1 object item(s) left unpacked", "", 1, 8, 8); + json_decref(j); } diff --git a/lib/cppmyth/jansson/test/suites/api/util.h b/lib/cppmyth/jansson/test/suites/api/util.h index b86a5463d..1bc4c9c7a 100644 --- a/lib/cppmyth/jansson/test/suites/api/util.h +++ b/lib/cppmyth/jansson/test/suites/api/util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Petri Lehtinen + * Copyright (c) 2009-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -9,7 +9,7 @@ #define UTIL_H #ifdef HAVE_CONFIG_H -#include +#include #endif #include @@ -20,7 +20,7 @@ #include -#define failhdr fprintf(stderr, "%s:%s:%d: ", __FILE__, __FUNCTION__, __LINE__) +#define failhdr fprintf(stderr, "%s:%d: ", __FILE__, __LINE__) #define fail(msg) \ do { \ diff --git a/lib/cppmyth/jansson/test/suites/encoding-flags/ensure-ascii/output b/lib/cppmyth/jansson/test/suites/encoding-flags/ensure-ascii/output index 36f8eb5e2..94fa79d2d 100644 --- a/lib/cppmyth/jansson/test/suites/encoding-flags/ensure-ascii/output +++ b/lib/cppmyth/jansson/test/suites/encoding-flags/ensure-ascii/output @@ -1 +1 @@ -["foo", "\u00e5 \u00e4 \u00f6", "foo \u00e5\u00e4", "\u00e5\u00e4 foo", "\u00e5 foo \u00e4", "clef g: \ud834\udd1e"] \ No newline at end of file +["foo", "\u00E5 \u00E4 \u00F6", "foo \u00E5\u00E4", "\u00E5\u00E4 foo", "\u00E5 foo \u00E4", "clef g: \uD834\uDD1E"] \ No newline at end of file diff --git a/lib/cppmyth/jansson/test/suites/encoding-flags/real-precision/env b/lib/cppmyth/jansson/test/suites/encoding-flags/real-precision/env new file mode 100644 index 000000000..9c52cbcd6 --- /dev/null +++ b/lib/cppmyth/jansson/test/suites/encoding-flags/real-precision/env @@ -0,0 +1,2 @@ +JSON_REAL_PRECISION=4 +export JSON_REAL_PRECISION diff --git a/lib/cppmyth/jansson/test/suites/encoding-flags/real-precision/input b/lib/cppmyth/jansson/test/suites/encoding-flags/real-precision/input new file mode 100644 index 000000000..e291165c1 --- /dev/null +++ b/lib/cppmyth/jansson/test/suites/encoding-flags/real-precision/input @@ -0,0 +1 @@ +[1.23456789, 1.0, 1.0000000000000002] diff --git a/lib/cppmyth/jansson/test/suites/encoding-flags/real-precision/output b/lib/cppmyth/jansson/test/suites/encoding-flags/real-precision/output new file mode 100644 index 000000000..f273c73e5 --- /dev/null +++ b/lib/cppmyth/jansson/test/suites/encoding-flags/real-precision/output @@ -0,0 +1 @@ +[1.235, 1.0, 1.0] \ No newline at end of file diff --git a/lib/cppmyth/jansson/test/suites/encoding-flags/run b/lib/cppmyth/jansson/test/suites/encoding-flags/run index 1920f7fc6..e1c88c9ee 100755 --- a/lib/cppmyth/jansson/test/suites/encoding-flags/run +++ b/lib/cppmyth/jansson/test/suites/encoding-flags/run @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2009-2013 Petri Lehtinen +# Copyright (c) 2009-2014 Petri Lehtinen # # Jansson is free software; you can redistribute it and/or modify # it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/invalid-unicode/run b/lib/cppmyth/jansson/test/suites/invalid-unicode/run index ac584f6fd..b2c664873 100755 --- a/lib/cppmyth/jansson/test/suites/invalid-unicode/run +++ b/lib/cppmyth/jansson/test/suites/invalid-unicode/run @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2009-2013 Petri Lehtinen +# Copyright (c) 2009-2014 Petri Lehtinen # # Jansson is free software; you can redistribute it and/or modify # it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/invalid/escaped-null-byte-in-string/error b/lib/cppmyth/jansson/test/suites/invalid/escaped-null-byte-in-string/error deleted file mode 100644 index 9795f1885..000000000 --- a/lib/cppmyth/jansson/test/suites/invalid/escaped-null-byte-in-string/error +++ /dev/null @@ -1,2 +0,0 @@ -1 33 33 -\u0000 is not allowed diff --git a/lib/cppmyth/jansson/test/suites/invalid/escaped-null-byte-in-string/input b/lib/cppmyth/jansson/test/suites/invalid/escaped-null-byte-in-string/input deleted file mode 100644 index 22ae82b2a..000000000 --- a/lib/cppmyth/jansson/test/suites/invalid/escaped-null-byte-in-string/input +++ /dev/null @@ -1 +0,0 @@ -["\u0000 (null byte not allowed)"] diff --git a/lib/cppmyth/jansson/test/suites/invalid/null-byte-in-object-key/error b/lib/cppmyth/jansson/test/suites/invalid/null-byte-in-object-key/error new file mode 100644 index 000000000..3ec685b5d --- /dev/null +++ b/lib/cppmyth/jansson/test/suites/invalid/null-byte-in-object-key/error @@ -0,0 +1,2 @@ +1 15 15 +NUL byte in object key not supported near '"foo\u0000bar"' diff --git a/lib/cppmyth/jansson/test/suites/invalid/null-byte-in-object-key/input b/lib/cppmyth/jansson/test/suites/invalid/null-byte-in-object-key/input new file mode 100644 index 000000000..593f0f67f --- /dev/null +++ b/lib/cppmyth/jansson/test/suites/invalid/null-byte-in-object-key/input @@ -0,0 +1 @@ +{"foo\u0000bar": 42} \ No newline at end of file diff --git a/lib/cppmyth/jansson/test/suites/invalid/run b/lib/cppmyth/jansson/test/suites/invalid/run index a640ea0ea..4f2325b7e 100755 --- a/lib/cppmyth/jansson/test/suites/invalid/run +++ b/lib/cppmyth/jansson/test/suites/invalid/run @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2009-2013 Petri Lehtinen +# Copyright (c) 2009-2014 Petri Lehtinen # # Jansson is free software; you can redistribute it and/or modify # it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/test/suites/valid/real-subnormal-number/input b/lib/cppmyth/jansson/test/suites/valid/real-subnormal-number/input new file mode 100644 index 000000000..df6065345 --- /dev/null +++ b/lib/cppmyth/jansson/test/suites/valid/real-subnormal-number/input @@ -0,0 +1 @@ +[1.8011670033376514e-308] diff --git a/lib/cppmyth/jansson/test/suites/valid/real-subnormal-number/output b/lib/cppmyth/jansson/test/suites/valid/real-subnormal-number/output new file mode 100644 index 000000000..e6b0a58e8 --- /dev/null +++ b/lib/cppmyth/jansson/test/suites/valid/real-subnormal-number/output @@ -0,0 +1 @@ +[1.8011670033376514e-308] \ No newline at end of file diff --git a/lib/cppmyth/jansson/test/suites/valid/run b/lib/cppmyth/jansson/test/suites/valid/run index c30d94a73..72f1918f7 100755 --- a/lib/cppmyth/jansson/test/suites/valid/run +++ b/lib/cppmyth/jansson/test/suites/valid/run @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2009-2013 Petri Lehtinen +# Copyright (c) 2009-2014 Petri Lehtinen # # Jansson is free software; you can redistribute it and/or modify # it under the terms of the MIT license. See LICENSE for details. diff --git a/lib/cppmyth/jansson/win32/jansson_config.h b/lib/cppmyth/jansson/win32/jansson_config.h deleted file mode 100644 index ab1da5dd3..000000000 --- a/lib/cppmyth/jansson/win32/jansson_config.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2010-2013 Petri Lehtinen - * - * Jansson is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See LICENSE for details. - * - * - * This file specifies a part of the site-specific configuration for - * Jansson, namely those things that affect the public API in - * jansson.h. - * - * The configure script copies this file to jansson_config.h and - * replaces @var@ substitutions by values that fit your system. If you - * cannot run the configure script, you can do the value substitution - * by hand. - */ - -#ifndef JANSSON_CONFIG_H -#define JANSSON_CONFIG_H - -/* If your compiler supports the inline keyword in C, JSON_INLINE is - defined to `inline', otherwise empty. In C++, the inline is always - supported. */ -#ifdef __cplusplus -#define JSON_INLINE inline -#else -#define JSON_INLINE __inline -#endif - -/* If your compiler supports the `long long` type and the strtoll() - library function, JSON_INTEGER_IS_LONG_LONG is defined to 1, - otherwise to 0. */ -#define JSON_INTEGER_IS_LONG_LONG 1 - -/* If locale.h and localeconv() are available, define to 1, - otherwise to 0. */ -#define JSON_HAVE_LOCALECONV 1 - -#endif diff --git a/lib/cppmyth/jansson/win32/vs2010/jansson.sln b/lib/cppmyth/jansson/win32/vs2010/jansson.sln deleted file mode 100644 index 58f911ba8..000000000 --- a/lib/cppmyth/jansson/win32/vs2010/jansson.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jansson", "jansson.vcxproj", "{76226D20-1972-4789-A595-EDACC7A76DC3}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {76226D20-1972-4789-A595-EDACC7A76DC3}.Debug|Win32.ActiveCfg = Debug|Win32 - {76226D20-1972-4789-A595-EDACC7A76DC3}.Debug|Win32.Build.0 = Debug|Win32 - {76226D20-1972-4789-A595-EDACC7A76DC3}.Release|Win32.ActiveCfg = Release|Win32 - {76226D20-1972-4789-A595-EDACC7A76DC3}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/lib/cppmyth/jansson/win32/vs2010/jansson.vcxproj b/lib/cppmyth/jansson/win32/vs2010/jansson.vcxproj deleted file mode 100644 index d5b2a8796..000000000 --- a/lib/cppmyth/jansson/win32/vs2010/jansson.vcxproj +++ /dev/null @@ -1,108 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - - - - - {76226D20-1972-4789-A595-EDACC7A76DC3} - Win32Proj - jansson_dll - jansson - - - - DynamicLibrary - true - Unicode - - - DynamicLibrary - false - true - Unicode - - - - - - - - - - - - - true - Output\$(Configuration)\ - Build\$(Configuration)\ - - - false - Output\$(Configuration)\ - Build\$(Configuration)\ - - - - NotUsing - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;JANSSON_DLL_EXPORTS;%(PreprocessorDefinitions) - .. - 4996 - - - Windows - true - ../../src/jansson.def - - - - - Level3 - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;JANSSON_DLL_EXPORTS;%(PreprocessorDefinitions) - .. - 4996 - - - Windows - true - true - true - ../../src/jansson.def - - - - - - \ No newline at end of file diff --git a/lib/cppmyth/jansson/win32/vs2010/jansson.vcxproj.filters b/lib/cppmyth/jansson/win32/vs2010/jansson.vcxproj.filters deleted file mode 100644 index f8eee304a..000000000 --- a/lib/cppmyth/jansson/win32/vs2010/jansson.vcxproj.filters +++ /dev/null @@ -1,69 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/lib/cppmyth/project/VS2010Express/cppmyth.sln b/lib/cppmyth/project/VS2010Express/cppmyth.sln new file mode 100644 index 000000000..fc0d958d2 --- /dev/null +++ b/lib/cppmyth/project/VS2010Express/cppmyth.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Express 2013 for Windows Desktop +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libjansson", "jansson\libjansson.vcxproj", "{E95631F0-9035-4BE4-B8E1-E2C6B0E3F0C3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcppmyth", "cppmyth\libcppmyth.vcxproj", "{086B2F32-C84B-481C-BB7E-ACCB4B2A0671}" + ProjectSection(ProjectDependencies) = postProject + {E95631F0-9035-4BE4-B8E1-E2C6B0E3F0C3} = {E95631F0-9035-4BE4-B8E1-E2C6B0E3F0C3} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + MinSizeRel|Win32 = MinSizeRel|Win32 + Release|Win32 = Release|Win32 + RelWithDebInfo|Win32 = RelWithDebInfo|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E95631F0-9035-4BE4-B8E1-E2C6B0E3F0C3}.Debug|Win32.ActiveCfg = Debug|Win32 + {E95631F0-9035-4BE4-B8E1-E2C6B0E3F0C3}.Debug|Win32.Build.0 = Debug|Win32 + {E95631F0-9035-4BE4-B8E1-E2C6B0E3F0C3}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {E95631F0-9035-4BE4-B8E1-E2C6B0E3F0C3}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {E95631F0-9035-4BE4-B8E1-E2C6B0E3F0C3}.Release|Win32.ActiveCfg = Release|Win32 + {E95631F0-9035-4BE4-B8E1-E2C6B0E3F0C3}.Release|Win32.Build.0 = Release|Win32 + {E95631F0-9035-4BE4-B8E1-E2C6B0E3F0C3}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {E95631F0-9035-4BE4-B8E1-E2C6B0E3F0C3}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {086B2F32-C84B-481C-BB7E-ACCB4B2A0671}.Debug|Win32.ActiveCfg = Debug|Win32 + {086B2F32-C84B-481C-BB7E-ACCB4B2A0671}.Debug|Win32.Build.0 = Debug|Win32 + {086B2F32-C84B-481C-BB7E-ACCB4B2A0671}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {086B2F32-C84B-481C-BB7E-ACCB4B2A0671}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {086B2F32-C84B-481C-BB7E-ACCB4B2A0671}.Release|Win32.ActiveCfg = Release|Win32 + {086B2F32-C84B-481C-BB7E-ACCB4B2A0671}.Release|Win32.Build.0 = Release|Win32 + {086B2F32-C84B-481C-BB7E-ACCB4B2A0671}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {086B2F32-C84B-481C-BB7E-ACCB4B2A0671}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/lib/cppmyth/project/VS2010Express/jansson/include/jansson_config.h b/lib/cppmyth/project/VS2010Express/jansson/include/jansson_config.h index 1d8250074..2507ca31a 100755 --- a/lib/cppmyth/project/VS2010Express/jansson/include/jansson_config.h +++ b/lib/cppmyth/project/VS2010Express/jansson/include/jansson_config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Petri Lehtinen + * Copyright (c) 2010-2014 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -9,15 +9,38 @@ * Jansson, namely those things that affect the public API in * jansson.h. * - * The configure script copies this file to jansson_config.h and - * replaces @var@ substitutions by values that fit your system. If you - * cannot run the configure script, you can do the value substitution - * by hand. + * The CMake system will generate the jansson_config.h file and + * copy it to the build and install directories. */ #ifndef JANSSON_CONFIG_H #define JANSSON_CONFIG_H +/* Define this so that we can disable scattered automake configuration in source files */ +#ifndef JANSSON_USING_CMAKE +#define JANSSON_USING_CMAKE +#endif + +/* Note: when using cmake, JSON_INTEGER_IS_LONG_LONG is not defined nor used, + * as we will also check for __int64 etc types. + * (the definition was used in the automake system) */ + +/* Bring in the cmake-detected defines */ +#define HAVE_STDINT_H 1 +/* #undef HAVE_INTTYPES_H */ +/* #undef HAVE_SYS_TYPES_H */ + +/* Include our standard type header for the integer typedef */ + +#if defined(HAVE_STDINT_H) +# include +#elif defined(HAVE_INTTYPES_H) +# include +#elif defined(HAVE_SYS_TYPES_H) +# include +#endif + + /* If your compiler supports the inline keyword in C, JSON_INLINE is defined to `inline', otherwise empty. In C++, the inline is always supported. */ @@ -27,13 +50,15 @@ #define JSON_INLINE __inline #endif -/* If your compiler supports the `long long` type and the strtoll() - library function, JSON_INTEGER_IS_LONG_LONG is defined to 1, - otherwise to 0. */ -#define JSON_INTEGER_IS_LONG_LONG 1 -/* If locale.h and localeconv() are available, define to 1, - otherwise to 0. */ +#define json_int_t long long +#define json_strtoint strtoll +#define JSON_INTEGER_FORMAT "I64d" + + +/* If locale.h and localeconv() are available, define to 1, otherwise to 0. */ #define JSON_HAVE_LOCALECONV 1 + + #endif diff --git a/lib/cppmyth/project/VS2010Express/jansson/private_include/config.h b/lib/cppmyth/project/VS2010Express/jansson/private_include/jansson_private_config.h similarity index 85% rename from lib/cppmyth/project/VS2010Express/jansson/private_include/config.h rename to lib/cppmyth/project/VS2010Express/jansson/private_include/jansson_private_config.h index d1562d104..6b4aafc14 100644 --- a/lib/cppmyth/project/VS2010Express/jansson/private_include/config.h +++ b/lib/cppmyth/project/VS2010Express/jansson/private_include/jansson_private_config.h @@ -31,6 +31,16 @@ # define uint32_t uint32_t #endif +#define HAVE_UINT16_T 1 +#ifndef HAVE_UINT16_T +# define uint16_t uint16_t +#endif + +#define HAVE_UINT8_T 1 +#ifndef HAVE_UINT8_T +# define uint8_t uint8_t +#endif + /* #undef HAVE_SSIZE_T */ #ifndef HAVE_SSIZE_T