<commit_before>/*************************************************************************
 *                                                                       *
 *  I|*j^3Cl|a   "+!*%                  qt          Nd   gW              *
 *  l]{y+l?MM*  !#Wla\NNP               NW          MM   I|              *
 *        PW    ?E|    tWg              Wg  sC!     AW           ~@v~    *
 *       NC     ?M!    yN|  WW     MK   MW@K1Y%M@   RM   #Q    QP@tim    *
 *     CM|      |WQCljAE|   MD     Mg   RN     cM~  NM   WQ   MQ         *
 *    #M        aQ?         MW     M3   Mg      Q(  HQ   YR  IM|         *
 *   Dq         {Ql         MH    iMX   Mg     MM   QP   QM   Eg         *
 * !EWNaPRag2$  +M"          $WNaHaN%   MQE$%EXW    QQ   CM    %M%a$D    *
 *                                                                       *
 *               Website: https://github.com/zpublic/zpublic             *
 *                                                                       *
 ************************************************************************/
/**
 * @file
 * @brief 该文件定义命名空间zl::WinUtils下的一个类。
 */

#pragma once
#include "win_utils_header.h"

namespace zl
{
namespace WinUtils
{
	/**
	* @brief ZLShortcut类，包含三个静态成员函数。
	* 用于生成给定文件的快捷方式，由给定的快捷方式获取文件路径与文件名
	*/
    class ZLShortcut
    {

        enum
        {
            WIN_PATH_MAX_UNICODE_PATH           = 32767 + 4,    ///> max size of buffer to store path, in bytes
            WIN_PATH_UNICODE_PATH_PREFIX        = 4,            ///> length of "\\\\??\\"
            WIN_PATH_UNICODE_UNC_PATH_PREFIX    = 7,            ///> length of "\\\\??\\UNC\\"
        };

    public:
	/**
	 * @brief 对于给定的可执行文件创建快捷方式
	 * @param[in]   lpLnkFilePath 创建的快捷方式的路径与文件名
	 * @param[in]   lpDstFilePath 可执行文件路径与文件名
	 * @param[in]  pszArguments 设置快捷方式的命令行参数
	 * @param[in]  pszDesc 设置快捷方式的描述信息
	 * @param[in]  pszIcon 设置快捷方式的图标
	 * @return 如果成功，返回TRUE，如果失败返回FALSE
	 * @see _ExpandFullPathName
	 */
        static BOOL Create(
            LPCWSTR lpLnkFilePath,
            LPCWSTR lpDstFilePath,
            LPCWSTR pszArguments = NULL,
            LPCWSTR pszDesc = NULL,
            LPCWSTR pszIcon = NULL)
        {
            BOOL bReturn = FALSE;
            ::CoInitialize(NULL);

            if (!lpDstFilePath || !lpLnkFilePath)
                goto Exit0;

            {
                CComPtr<IShellLink> spiShellLink;
                CString strFullPath = lpDstFilePath;
                HRESULT hr = _ExpandFullPathName(strFullPath);
                if (FAILED(hr))
                    goto Exit0;

                hr = ::CoCreateInstance(
                    CLSID_ShellLink,
                    NULL,
                    CLSCTX_INPROC_SERVER,
                    IID_IShellLink,
                    (void**)&spiShellLink);
                if (FAILED(hr))
                    goto Exit0;

                CComPtr<IPersistFile> spiPersistFile;
                hr = spiShellLink.QueryInterface(&spiPersistFile);
                if (FAILED(hr))
                    goto Exit0;

                // Set the path to the shortcut target and add the description
                hr = spiShellLink->SetPath(strFullPath);
                if (FAILED(hr))
                    goto Exit0;

                if (pszArguments)
                {
                    hr = spiShellLink->SetArguments(pszArguments);
                    if (FAILED(hr))
                        goto Exit0;
                }

                if (pszDesc)
                {
                    hr = spiShellLink->SetDescription(pszDesc);
                    if (FAILED(hr))
                        goto Exit0;
                }

                if (pszIcon)
                {
                    hr = spiShellLink->SetIconLocation(pszIcon, 0);
                    if (FAILED(hr))
                        goto Exit0;
                }

                // Write the shortcut to disk
                hr = spiPersistFile->Save(lpLnkFilePath, TRUE);
                if (FAILED(hr))
                    goto Exit0;
            }

            bReturn = TRUE;

Exit0:
            ::CoUninitialize();
            return bReturn;
        }

	/**
	 * @brief 给定快捷方式，获取快捷方式对应的路径和文件名
	 * @param[in]   lpLnkFilePath 以空终止的字符串包含打开文件的绝对路径
	 * @param[out]  sDstPath 字符串引用，获取快捷方式的路径和文件名
	 * @return 如果成功，返回TRUE，如果失败返回FALSE
	 */
        static BOOL GetDstPath(LPCTSTR lpLnkFilePath, CString &sDstPath)
        {
            bool bReturn = FALSE;

            ::CoInitialize(NULL);

            CComPtr<IPersistFile> pPersistFile;
            HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IPersistFile, (void**)(&pPersistFile));
            if(SUCCEEDED(hr))
            {
                CComPtr<IShellLink> pShellLink;
                hr = pPersistFile->QueryInterface(IID_IShellLink, (void**)(&pShellLink));
                if(SUCCEEDED(hr))
                {
                    hr = pPersistFile->Load(lpLnkFilePath, STGM_READ);
                    if(SUCCEEDED(hr))
                    {
                        TCHAR szPath[MAX_PATH + 1] = {0};
                        hr = pShellLink->GetPath(szPath, MAX_PATH, NULL, 0);
                        if(SUCCEEDED(hr))
                        {
                            sDstPath = szPath;
                            bReturn = TRUE;
                        }
                    }
                }
            }

            CoUninitialize();
            return bReturn;
        }

    private:

	/**
	 * @brief 由指定文件名获取文件的全路径与文件名
	 * @param[in,out]   strPathName CString引用，传进文件名，返回文件全路径与文件名
	 * @return 如果成功，返回S_OK，如果失败，以HRESULT的形式返回调用线程的最近错误码或E_FAIL
	 * @see GetFullPathName
	 */
        static HRESULT _ExpandFullPathName( CString& strPathName )
        {
            DWORD dwLen = ::GetFullPathName(strPathName, 0, NULL, NULL);
            if (0 == dwLen)
                return GetLastError() ? AtlHresultFromLastError() : E_FAIL;

            assert(dwLen <= WIN_PATH_MAX_UNICODE_PATH);
            if (dwLen > WIN_PATH_MAX_UNICODE_PATH)
                return E_UNEXPECTED;

            CString strFullPathName;
            dwLen = ::GetFullPathName(strPathName, dwLen, strFullPathName.GetBuffer(dwLen), NULL);
            if (0 == dwLen)
            {
                strFullPathName.ReleaseBuffer(0);
                return GetLastError() ? AtlHresultFromLastError() : E_FAIL;
            }

            strFullPathName.ReleaseBuffer();
            strPathName = strFullPathName;
            return S_OK;
        }
    };
}
}

<commit_msg>*shortcut注释修改<commit_after>/*************************************************************************
 *                                                                       *
 *  I|*j^3Cl|a   "+!*%                  qt          Nd   gW              *
 *  l]{y+l?MM*  !#Wla\NNP               NW          MM   I|              *
 *        PW    ?E|    tWg              Wg  sC!     AW           ~@v~    *
 *       NC     ?M!    yN|  WW     MK   MW@K1Y%M@   RM   #Q    QP@tim    *
 *     CM|      |WQCljAE|   MD     Mg   RN     cM~  NM   WQ   MQ         *
 *    #M        aQ?         MW     M3   Mg      Q(  HQ   YR  IM|         *
 *   Dq         {Ql         MH    iMX   Mg     MM   QP   QM   Eg         *
 * !EWNaPRag2$  +M"          $WNaHaN%   MQE$%EXW    QQ   CM    %M%a$D    *
 *                                                                       *
 *               Website: https://github.com/zpublic/zpublic             *
 *                                                                       *
 ************************************************************************/
/**
 * @file
 * @brief 快捷方式处理
 */

#pragma once
#include "win_utils_header.h"

namespace zl
{
namespace WinUtils
{
	/**
	* @brief 快捷方式处理类
	* 用于生成给定文件的快捷方式，由给定的快捷方式获取文件路径与文件名
	*/
    class ZLShortcut
    {

        enum
        {
            WIN_PATH_MAX_UNICODE_PATH           = 32767 + 4,    ///> max size of buffer to store path, in bytes
            WIN_PATH_UNICODE_PATH_PREFIX        = 4,            ///> length of "\\\\??\\"
            WIN_PATH_UNICODE_UNC_PATH_PREFIX    = 7,            ///> length of "\\\\??\\UNC\\"
        };

    public:
		/**
		* @brief 对于给定的可执行文件创建快捷方式
		* @param[in]   lpLnkFilePath 创建的快捷方式的路径与文件名
		* @param[in]   lpDstFilePath 可执行文件路径与文件名
		* @param[in]  pszArguments 设置快捷方式的命令行参数
		* @param[in]  pszDesc 设置快捷方式的描述信息
		* @param[in]  pszIcon 设置快捷方式的图标
		* @return 如果成功，返回TRUE，如果失败返回FALSE
		* @see _ExpandFullPathName
		*/
        static BOOL Create(
            LPCWSTR lpLnkFilePath,
            LPCWSTR lpDstFilePath,
            LPCWSTR pszArguments = NULL,
            LPCWSTR pszDesc = NULL,
            LPCWSTR pszIcon = NULL)
        {
            BOOL bReturn = FALSE;
            ::CoInitialize(NULL);

            if (!lpDstFilePath || !lpLnkFilePath)
                goto Exit0;

            {
                CComPtr<IShellLink> spiShellLink;
                CString strFullPath = lpDstFilePath;
                HRESULT hr = _ExpandFullPathName(strFullPath);
                if (FAILED(hr))
                    goto Exit0;

                hr = ::CoCreateInstance(
                    CLSID_ShellLink,
                    NULL,
                    CLSCTX_INPROC_SERVER,
                    IID_IShellLink,
                    (void**)&spiShellLink);
                if (FAILED(hr))
                    goto Exit0;

                CComPtr<IPersistFile> spiPersistFile;
                hr = spiShellLink.QueryInterface(&spiPersistFile);
                if (FAILED(hr))
                    goto Exit0;

                // Set the path to the shortcut target and add the description
                hr = spiShellLink->SetPath(strFullPath);
                if (FAILED(hr))
                    goto Exit0;

                if (pszArguments)
                {
                    hr = spiShellLink->SetArguments(pszArguments);
                    if (FAILED(hr))
                        goto Exit0;
                }

                if (pszDesc)
                {
                    hr = spiShellLink->SetDescription(pszDesc);
                    if (FAILED(hr))
                        goto Exit0;
                }

                if (pszIcon)
                {
                    hr = spiShellLink->SetIconLocation(pszIcon, 0);
                    if (FAILED(hr))
                        goto Exit0;
                }

                // Write the shortcut to disk
                hr = spiPersistFile->Save(lpLnkFilePath, TRUE);
                if (FAILED(hr))
                    goto Exit0;
            }

            bReturn = TRUE;

Exit0:
            ::CoUninitialize();
            return bReturn;
        }

		/**
		* @brief 给定快捷方式，获取快捷方式对应的路径和文件名
		* @param[in]   lpLnkFilePath 以空终止的字符串包含打开文件的绝对路径
		* @param[out]  sDstPath 字符串引用，获取快捷方式的路径和文件名
		* @return 如果成功，返回TRUE，如果失败返回FALSE
		*/
        static BOOL GetDstPath(LPCTSTR lpLnkFilePath, CString &sDstPath)
        {
            bool bReturn = FALSE;

            ::CoInitialize(NULL);

            CComPtr<IPersistFile> pPersistFile;
            HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IPersistFile, (void**)(&pPersistFile));
            if(SUCCEEDED(hr))
            {
                CComPtr<IShellLink> pShellLink;
                hr = pPersistFile->QueryInterface(IID_IShellLink, (void**)(&pShellLink));
                if(SUCCEEDED(hr))
                {
                    hr = pPersistFile->Load(lpLnkFilePath, STGM_READ);
                    if(SUCCEEDED(hr))
                    {
                        TCHAR szPath[MAX_PATH + 1] = {0};
                        hr = pShellLink->GetPath(szPath, MAX_PATH, NULL, 0);
                        if(SUCCEEDED(hr))
                        {
                            sDstPath = szPath;
                            bReturn = TRUE;
                        }
                    }
                }
            }

            CoUninitialize();
            return bReturn;
        }

    private:

		/**
		* @brief 由指定文件名获取文件的全路径与文件名
		* @param[in,out]   strPathName CString引用，传进文件名，返回文件全路径与文件名
		* @return 如果成功，返回S_OK，如果失败，以HRESULT的形式返回调用线程的最近错误码或E_FAIL
		* @see GetFullPathName
		*/
        static HRESULT _ExpandFullPathName( CString& strPathName )
        {
            DWORD dwLen = ::GetFullPathName(strPathName, 0, NULL, NULL);
            if (0 == dwLen)
                return GetLastError() ? AtlHresultFromLastError() : E_FAIL;

            assert(dwLen <= WIN_PATH_MAX_UNICODE_PATH);
            if (dwLen > WIN_PATH_MAX_UNICODE_PATH)
                return E_UNEXPECTED;

            CString strFullPathName;
            dwLen = ::GetFullPathName(strPathName, dwLen, strFullPathName.GetBuffer(dwLen), NULL);
            if (0 == dwLen)
            {
                strFullPathName.ReleaseBuffer(0);
                return GetLastError() ? AtlHresultFromLastError() : E_FAIL;
            }

            strFullPathName.ReleaseBuffer();
            strPathName = strFullPathName;
            return S_OK;
        }
    };
}
}

<|endoftext|>


<commit_before>/*
 * SaveHandler.hpp
 *
 *  Created on: 29.05.2017
 *      Author: Alexander
 */

#ifndef PERSISTENCE_BASE_SAVEHANDLER_HPP
#define PERSISTENCE_BASE_SAVEHANDLER_HPP

#include "persistence/interface/XSaveHandler.hpp"

#include <string>
#include "abstractDataTypes/Bag.hpp"

namespace ecore
{
	class EObject;
}

namespace persistence
{
	namespace base
	{
		class SaveHandler: public persistence::interface::XSaveHandler
		{
			public:
				SaveHandler();
				virtual ~SaveHandler();

				std::string getPrefix();
				void setRootObject(std::shared_ptr<ecore::EObject> object);

				std::string extractType(std::shared_ptr<ecore::EObject> obj) const;

				virtual bool createRootNode(const std::string& name, const std::string& ns_uri) = 0;
				virtual bool createRootNode(const std::string& prefix, const std::string& name, const std::string& ns_uri) = 0;

				virtual bool createAndAddElement(const std::string& name) = 0;

				void addAttribute(const std::string &name, bool value);
				virtual void addAttribute(const std::string &name, const std::string& value) = 0;

				void addReference(const std::string &name, std::shared_ptr<ecore::EObject> object);
				virtual void addReferences(const std::string &name, std::shared_ptr<ecore::EObject> object) = 0;
				virtual void addReference(const std::shared_ptr<ecore::EObject> object, const std::string &tagName, const bool typeRequired);
				virtual void release() = 0;
				virtual void setThisPtr(std::shared_ptr<SaveHandler> thisPtr);
				virtual void setIsXSIMode(bool value);
				virtual void setTypesMap(std::map<std::string, std::shared_ptr<ecore::EObject>> typesMap);
				virtual void addTypeReference(const std::string& href, const std::string& xmitype) = 0;

			protected:
				std::shared_ptr<ecore::EObject> m_rootObject;
				std::string m_rootPrefix;

			private:
				std::shared_ptr<SaveHandler> m_thisPtr;
				bool m_isXSIMode;
				std::shared_ptr<Bag<ecore::EObject>> m_savedObjects;
				std::map<std::shared_ptr<ecore::EObject>, std::string> m_refToObject_map;
		};
	} /* namespace base */
} /* namespace persistence */

#endif /* SaveHandler_HPP_ */
<commit_msg>[persistence] map for references should be protected<commit_after>/*
 * SaveHandler.hpp
 *
 *  Created on: 29.05.2017
 *      Author: Alexander
 */

#ifndef PERSISTENCE_BASE_SAVEHANDLER_HPP
#define PERSISTENCE_BASE_SAVEHANDLER_HPP

#include "persistence/interface/XSaveHandler.hpp"

#include <string>
#include "abstractDataTypes/Bag.hpp"

namespace ecore
{
	class EObject;
}

namespace persistence
{
	namespace base
	{
		class SaveHandler: public persistence::interface::XSaveHandler
		{
			public:
				SaveHandler();
				virtual ~SaveHandler();

				std::string getPrefix();
				void setRootObject(std::shared_ptr<ecore::EObject> object);

				std::string extractType(std::shared_ptr<ecore::EObject> obj) const;

				virtual bool createRootNode(const std::string& name, const std::string& ns_uri) = 0;
				virtual bool createRootNode(const std::string& prefix, const std::string& name, const std::string& ns_uri) = 0;

				virtual bool createAndAddElement(const std::string& name) = 0;

				void addAttribute(const std::string &name, bool value);
				virtual void addAttribute(const std::string &name, const std::string& value) = 0;

				void addReference(const std::string &name, std::shared_ptr<ecore::EObject> object);
				virtual void addReferences(const std::string &name, std::shared_ptr<ecore::EObject> object) = 0;
				virtual void addReference(const std::shared_ptr<ecore::EObject> object, const std::string &tagName, const bool typeRequired);
				virtual void release() = 0;
				virtual void setThisPtr(std::shared_ptr<SaveHandler> thisPtr);
				virtual void setIsXSIMode(bool value);
				virtual void setTypesMap(std::map<std::string, std::shared_ptr<ecore::EObject>> typesMap);
				virtual void addTypeReference(const std::string& href, const std::string& xmitype) = 0;

			protected:
				std::shared_ptr<ecore::EObject> m_rootObject;
				std::string m_rootPrefix;
				std::map<std::shared_ptr<ecore::EObject>, std::string> m_refToObject_map;

			private:
				std::shared_ptr<SaveHandler> m_thisPtr;
				bool m_isXSIMode;
				std::shared_ptr<Bag<ecore::EObject>> m_savedObjects;
		};
	} /* namespace base */
} /* namespace persistence */

#endif /* SaveHandler_HPP_ */
<|endoftext|>


<commit_before>#include <sys/time.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>

#include <iostream>
#include <fstream>
#include <map>

#include <CoreFoundation/CoreFoundation.h>

namespace {
  CFStringRef applicationID = CFSTR("org.pqrs.KeyRemap4MacBook");

  // ============================================================
  // SAVE & LOAD
  CFMutableDictionaryRef dict_sysctl = NULL;
  std::map<std::string, int> map_reset;

  void
  save(const char *name)
  {
    if (! dict_sysctl) return;

    char entry[512];
    snprintf(entry, sizeof(entry), "keyremap4macbook.%s", name);

    int value;
    size_t len = sizeof(value);
    if (sysctlbyname(entry, &value, &len, NULL, 0) == -1) return;

    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &value);

    typeof(map_reset.end()) it = map_reset.find(name);
    if (it == map_reset.end()) return;
    CFNumberRef defaultval = CFNumberCreate(NULL, kCFNumberIntType, &(it->second));

    if (CFNumberCompare(val, defaultval, NULL) != 0) {
      CFDictionarySetValue(dict_sysctl, key, val);
    }
  }

  void
  load(const char *name)
  {
    if (! dict_sysctl) return;
    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);

    CFNumberRef val = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue(dict_sysctl, key));
    if (! val) return;

    int value;
    if (! CFNumberGetValue(val, kCFNumberIntType, &value)) return;

    char cmd[512];
    snprintf(cmd, sizeof(cmd), "/Library/org.pqrs/KeyRemap4MacBook/bin/KeyRemap4MacBook_sysctl_set %s %d", name, value);
    system(cmd);
  }

  void
  scanLines(const char *filename, void (*func)(const char *))
  {
    std::ifstream ifs(filename);
    if (! ifs) return;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      const char *sysctl_begin = "<sysctl>";
      const char *sysctl_end = "</sysctl>";

      char *begin = strstr(line, "<sysctl>");
      if (! begin) continue;
      char *end = strstr(line, sysctl_end);
      if (! end) continue;

      begin += strlen(sysctl_begin);
      *end = '\0';

      func(begin);
    }
  }

  bool
  makeMapReset(void)
  {
    std::ifstream ifs("/Library/org.pqrs/KeyRemap4MacBook/share/reset");
    if (! ifs) return false;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      char *p = strchr(line, ' ');
      if (! p) continue;
      *p = '\0';

      int value = atoi(p + 1);

      map_reset[line] = value;
    }

    return true;
  }

  bool
  saveToFile(const char **targetFiles, CFStringRef identify)
  {
    if (! makeMapReset()) return false;

    dict_sysctl = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
    if (! dict_sysctl) return false;

    for (int i = 0; ; ++i) {
      const char *filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, save);
    }
    CFPreferencesSetAppValue(identify, dict_sysctl, applicationID);

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }

  bool
  loadFromFile(const char **targetFiles, CFStringRef identify)
  {
    dict_sysctl = reinterpret_cast<CFMutableDictionaryRef>(const_cast<void *>(CFPreferencesCopyAppValue(identify, applicationID)));
    if (! dict_sysctl) return false;

    for (int i = 0; ; ++i) {
      const char *filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, load);
    }

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }

  // ============================================================
  // ADD & DELETE & SELECT
  void
  setConfigList(CFArrayRef list)
  {
    CFPreferencesSetAppValue(CFSTR("configList"), list, applicationID);
  }

  CFArrayRef
  getConfigList(void)
  {
    CFArrayRef list = reinterpret_cast<CFArrayRef>(CFPreferencesCopyAppValue(CFSTR("configList"), applicationID));

    if (! list || CFArrayGetCount(list) == 0) {
      if (list) CFRelease(list);

      CFMutableDictionaryRef dict[1];
      dict[0] = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
      CFDictionarySetValue(dict[0], CFSTR("name"), CFSTR("Default"));
      CFDictionarySetValue(dict[0], CFSTR("identify"), CFSTR("config_default"));

      list = CFArrayCreate(NULL, const_cast<const void **>(reinterpret_cast<void **>(dict)), 1, NULL);
      setConfigList(list);
    }

    return list;
  }

  CFDictionaryRef
  getConfigDictionary(CFIndex index)
  {
    CFArrayRef list = getConfigList();
    if (! list) return NULL;

    if (index < 0) return NULL;
    if (index >= CFArrayGetCount(list)) return NULL;

    return reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(list, index));
  }

  CFStringRef
  getIdentify(CFIndex index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return NULL;

    return reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("identify")));
  }

  CFStringRef
  getConfigName(int index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return NULL;

    return reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("name")));
  }

  bool
  appendConfig(void)
  {
    CFArrayRef list = getConfigList();
    if (! list) return false;

    struct timeval tm;
    gettimeofday(&tm, NULL);
    CFStringRef identify = CFStringCreateWithFormat(NULL, NULL, CFSTR("config_%d_%d"), tm.tv_sec, tm.tv_usec);

    CFMutableDictionaryRef dict;
    dict = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
    CFDictionarySetValue(dict, CFSTR("name"), CFSTR("NewItem"));
    CFDictionarySetValue(dict, CFSTR("identify"), identify);

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArrayAppendValue(newlist, dict);

    setConfigList(newlist);
    return true;
  }

  bool
  removeConfig(int index)
  {
    CFStringRef identify = getIdentify(index);
    if (! identify) return false;

    CFPreferencesSetAppValue(identify, NULL, applicationID);

    CFArrayRef list = getConfigList();
    if (! list) return false;

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArrayRemoveValueAtIndex(newlist, index);

    setConfigList(newlist);
    return true;
  }

  bool
  renameConfig(int index, const char *newname)
  {
    CFArrayRef list = getConfigList();
    if (! list) return false;

    CFDictionaryRef olddict = getConfigDictionary(index);
    if (! olddict) return false;

    CFMutableDictionaryRef newdict = CFDictionaryCreateMutableCopy(NULL, 0, olddict);
    CFDictionarySetValue(newdict, CFSTR("name"), CFStringCreateWithCString(NULL, newname, kCFStringEncodingUTF8));

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArraySetValueAtIndex(newlist, index, newdict);

    setConfigList(newlist);
    return true;
  }

  CFIndex
  getConfigCount(void)
  {
    CFArrayRef list = getConfigList();
    if (! list) return 0;

    return CFArrayGetCount(list);
  }

  // ----------------------------------------
  bool
  setSelectedIndex(CFIndex index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return false;

    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &index);
    CFPreferencesSetAppValue(CFSTR("selectedIndex"), val, applicationID);

    return true;
  }

  CFIndex
  getSelectedIndex(void)
  {
    Boolean isOK;
    CFIndex value = CFPreferencesGetAppIntegerValue(CFSTR("selectedIndex"), applicationID, &isOK);
    if (! isOK || value < 0) {
      value = 0;
      setSelectedIndex(value);
    }
    return value;
  }

  // ----------------------------------------
  bool
  setStatusbarEnable(CFIndex enable)
  {
    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &enable);
    CFPreferencesSetAppValue(CFSTR("isStatusbarEnable"), val, applicationID);
    return true;
  }

  CFIndex
  isStatusbarEnable(void)
  {
    Boolean isOK;
    CFIndex value = CFPreferencesGetAppIntegerValue(CFSTR("isStatusbarEnable"), applicationID, &isOK);
    if (! isOK) {
      value = 1;
      setStatusbarEnable(value);
    }
    return value;
  }

  void
  stripString(char *buf, size_t buflen)
  {
    char *p = buf;
    for (;;) {
      if (! isspace(*p)) break;
      ++p;
    }
    char *q = p;
    for (;;) {
      if (*q == '\0' || *q == '\r' || *q == '\n') break;
      ++q;
    }
    *q = '\0';
    snprintf(buf, buflen, "%s", p);
  }
}

int
main(int argc, char **argv)
{
  if (argc == 1) {
    fprintf(stderr, "Usage: %s (save|load|add|delete|rename|getname|select|count|current|statusbar|toggle_statusbar) [params]\n", argv[0]);
    return 1;
  }

  bool isSuccess = false;

  if (strcmp(argv[1], "select") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s select index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    isSuccess = setSelectedIndex(index);

  } else if (strcmp(argv[1], "add") == 0) {
    isSuccess = appendConfig();

  } else if (strcmp(argv[1], "delete") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s delete index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    isSuccess = removeConfig(index);

  } else if (strcmp(argv[1], "rename") == 0) {
    // sysctl_ctl rename "index" "newname"
    if (argc < 4) {
      fprintf(stderr, "Usage: %s rename index newname\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    char buf[512];
    snprintf(buf, sizeof(buf), "%s", argv[3]);
    stripString(buf, sizeof(buf));
    if (buf[0] == '\0') {
      snprintf(buf, sizeof(buf), "(null)");
    }
    isSuccess = renameConfig(index, buf);

  } else if (strcmp(argv[1], "count") == 0) {
    printf("%ld\n", getConfigCount());
    return 0;

  } else if (strcmp(argv[1], "current") == 0) {
    printf("%ld\n", getSelectedIndex());
    return 0;

  } else if (strcmp(argv[1], "statusbar") == 0) {
    printf("%ld\n", isStatusbarEnable());
    return 0;

  } else if (strcmp(argv[1], "toggle_statusbar") == 0) {
    CFIndex value = isStatusbarEnable();
    isSuccess = setStatusbarEnable(! value);

  } else if (strcmp(argv[1], "getname") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s getname index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    CFStringRef name = getConfigName(index);
    if (name) {
      char buf[512];
      if (CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8)) {
        stripString(buf, sizeof(buf));
        printf("%s\n", buf);
      } else {
        printf("(null)\n", buf);
      }
    }
    return 0;

  } else if ((strcmp(argv[1], "save") == 0) || (strcmp(argv[1], "load") == 0)) {
    CFIndex value = getSelectedIndex();
    CFStringRef identify = getIdentify(value);

    const char *targetFiles[] = {
      "/Library/org.pqrs/KeyRemap4MacBook/prefpane/checkbox.xml",
      "/Library/org.pqrs/KeyRemap4MacBook/prefpane/number.xml",
      NULL,
    };
    if (strcmp(argv[1], "save") == 0) {
      isSuccess = saveToFile(targetFiles, identify);
    }
    if (strcmp(argv[1], "load") == 0) {
      system("/Library/org.pqrs/KeyRemap4MacBook/bin/KeyRemap4MacBook_sysctl_reset");
      isSuccess = loadFromFile(targetFiles, identify);
    }
  }

  CFPreferencesAppSynchronize(applicationID);

finish:
  if (isSuccess) {
    fprintf(stderr, "[DONE]\n");
  } else {
    fprintf(stderr, "[ERROR]\n");
  }

  return 0;
}
<commit_msg>apply uncrustify<commit_after>#include <sys/time.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>

#include <iostream>
#include <fstream>
#include <map>

#include <CoreFoundation/CoreFoundation.h>

namespace {
  CFStringRef applicationID = CFSTR("org.pqrs.KeyRemap4MacBook");

  // ============================================================
  // SAVE & LOAD
  CFMutableDictionaryRef dict_sysctl = NULL;
  std::map<std::string, int> map_reset;

  void
  save(const char* name)
  {
    if (! dict_sysctl) return;

    char entry[512];
    snprintf(entry, sizeof(entry), "keyremap4macbook.%s", name);

    int value;
    size_t len = sizeof(value);
    if (sysctlbyname(entry, &value, &len, NULL, 0) == -1) return;

    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &value);

    std::map<std::string, int>::iterator it = map_reset.find(name);
    if (it == map_reset.end()) return;
    CFNumberRef defaultval = CFNumberCreate(NULL, kCFNumberIntType, &(it->second));

    if (CFNumberCompare(val, defaultval, NULL) != 0) {
      CFDictionarySetValue(dict_sysctl, key, val);
    }
  }

  void
  load(const char* name)
  {
    if (! dict_sysctl) return;
    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);

    CFNumberRef val = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue(dict_sysctl, key));
    if (! val) return;

    int value;
    if (! CFNumberGetValue(val, kCFNumberIntType, &value)) return;

    char cmd[512];
    snprintf(cmd, sizeof(cmd), "/Library/org.pqrs/KeyRemap4MacBook/bin/KeyRemap4MacBook_sysctl_set %s %d", name, value);
    system(cmd);
  }

  void
  scanLines(const char* filename, void (* func)(const char*))
  {
    std::ifstream ifs(filename);
    if (! ifs) return;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      const char* sysctl_begin = "<sysctl>";
      const char* sysctl_end = "</sysctl>";

      char* begin = strstr(line, "<sysctl>");
      if (! begin) continue;
      char* end = strstr(line, sysctl_end);
      if (! end) continue;

      begin += strlen(sysctl_begin);
      *end = '\0';

      func(begin);
    }
  }

  bool
  makeMapReset(void)
  {
    std::ifstream ifs("/Library/org.pqrs/KeyRemap4MacBook/share/reset");
    if (! ifs) return false;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      char* p = strchr(line, ' ');
      if (! p) continue;
      *p = '\0';

      int value = atoi(p + 1);

      map_reset[line] = value;
    }

    return true;
  }

  bool
  saveToFile(const char** targetFiles, CFStringRef identify)
  {
    if (! makeMapReset()) return false;

    dict_sysctl = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
    if (! dict_sysctl) return false;

    for (int i = 0;; ++i) {
      const char* filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, save);
    }
    CFPreferencesSetAppValue(identify, dict_sysctl, applicationID);

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }

  bool
  loadFromFile(const char** targetFiles, CFStringRef identify)
  {
    dict_sysctl = reinterpret_cast<CFMutableDictionaryRef>(const_cast<void*>(CFPreferencesCopyAppValue(identify, applicationID)));
    if (! dict_sysctl) return false;

    for (int i = 0;; ++i) {
      const char* filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, load);
    }

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }

  // ============================================================
  // ADD & DELETE & SELECT
  void
  setConfigList(CFArrayRef list)
  {
    CFPreferencesSetAppValue(CFSTR("configList"), list, applicationID);
  }

  CFArrayRef
  getConfigList(void)
  {
    CFArrayRef list = reinterpret_cast<CFArrayRef>(CFPreferencesCopyAppValue(CFSTR("configList"), applicationID));

    if (! list || CFArrayGetCount(list) == 0) {
      if (list) CFRelease(list);

      CFMutableDictionaryRef dict[1];
      dict[0] = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
      CFDictionarySetValue(dict[0], CFSTR("name"), CFSTR("Default"));
      CFDictionarySetValue(dict[0], CFSTR("identify"), CFSTR("config_default"));

      list = CFArrayCreate(NULL, const_cast<const void**>(reinterpret_cast<void**>(dict)), 1, NULL);
      setConfigList(list);
    }

    return list;
  }

  CFDictionaryRef
  getConfigDictionary(CFIndex index)
  {
    CFArrayRef list = getConfigList();
    if (! list) return NULL;

    if (index < 0) return NULL;
    if (index >= CFArrayGetCount(list)) return NULL;

    return reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(list, index));
  }

  CFStringRef
  getIdentify(CFIndex index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return NULL;

    return reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("identify")));
  }

  CFStringRef
  getConfigName(int index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return NULL;

    return reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("name")));
  }

  bool
  appendConfig(void)
  {
    CFArrayRef list = getConfigList();
    if (! list) return false;

    struct timeval tm;
    gettimeofday(&tm, NULL);
    CFStringRef identify = CFStringCreateWithFormat(NULL, NULL, CFSTR("config_%d_%d"), tm.tv_sec, tm.tv_usec);

    CFMutableDictionaryRef dict;
    dict = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
    CFDictionarySetValue(dict, CFSTR("name"), CFSTR("NewItem"));
    CFDictionarySetValue(dict, CFSTR("identify"), identify);

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArrayAppendValue(newlist, dict);

    setConfigList(newlist);
    return true;
  }

  bool
  removeConfig(int index)
  {
    CFStringRef identify = getIdentify(index);
    if (! identify) return false;

    CFPreferencesSetAppValue(identify, NULL, applicationID);

    CFArrayRef list = getConfigList();
    if (! list) return false;

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArrayRemoveValueAtIndex(newlist, index);

    setConfigList(newlist);
    return true;
  }

  bool
  renameConfig(int index, const char* newname)
  {
    CFArrayRef list = getConfigList();
    if (! list) return false;

    CFDictionaryRef olddict = getConfigDictionary(index);
    if (! olddict) return false;

    CFMutableDictionaryRef newdict = CFDictionaryCreateMutableCopy(NULL, 0, olddict);
    CFDictionarySetValue(newdict, CFSTR("name"), CFStringCreateWithCString(NULL, newname, kCFStringEncodingUTF8));

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArraySetValueAtIndex(newlist, index, newdict);

    setConfigList(newlist);
    return true;
  }

  CFIndex
  getConfigCount(void)
  {
    CFArrayRef list = getConfigList();
    if (! list) return 0;

    return CFArrayGetCount(list);
  }

  // ----------------------------------------
  bool
  setSelectedIndex(CFIndex index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return false;

    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &index);
    CFPreferencesSetAppValue(CFSTR("selectedIndex"), val, applicationID);

    return true;
  }

  CFIndex
  getSelectedIndex(void)
  {
    Boolean isOK;
    CFIndex value = CFPreferencesGetAppIntegerValue(CFSTR("selectedIndex"), applicationID, &isOK);
    if (! isOK || value < 0) {
      value = 0;
      setSelectedIndex(value);
    }
    return value;
  }

  // ----------------------------------------
  bool
  setStatusbarEnable(CFIndex enable)
  {
    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &enable);
    CFPreferencesSetAppValue(CFSTR("isStatusbarEnable"), val, applicationID);
    return true;
  }

  CFIndex
  isStatusbarEnable(void)
  {
    Boolean isOK;
    CFIndex value = CFPreferencesGetAppIntegerValue(CFSTR("isStatusbarEnable"), applicationID, &isOK);
    if (! isOK) {
      value = 1;
      setStatusbarEnable(value);
    }
    return value;
  }

  void
  stripString(char* buf, size_t buflen)
  {
    char* p = buf;
    for (;;) {
      if (! isspace(*p)) break;
      ++p;
    }
    char* q = p;
    for (;;) {
      if (*q == '\0' || *q == '\r' || *q == '\n') break;
      ++q;
    }
    *q = '\0';
    snprintf(buf, buflen, "%s", p);
  }
}

int
main(int argc, char** argv)
{
  if (argc == 1) {
    fprintf(stderr, "Usage: %s (save|load|add|delete|rename|getname|select|count|current|statusbar|toggle_statusbar) [params]\n", argv[0]);
    return 1;
  }

  bool isSuccess = false;

  if (strcmp(argv[1], "select") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s select index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    isSuccess = setSelectedIndex(index);

  } else if (strcmp(argv[1], "add") == 0) {
    isSuccess = appendConfig();

  } else if (strcmp(argv[1], "delete") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s delete index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    isSuccess = removeConfig(index);

  } else if (strcmp(argv[1], "rename") == 0) {
    // sysctl_ctl rename "index" "newname"
    if (argc < 4) {
      fprintf(stderr, "Usage: %s rename index newname\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    char buf[512];
    snprintf(buf, sizeof(buf), "%s", argv[3]);
    stripString(buf, sizeof(buf));
    if (buf[0] == '\0') {
      snprintf(buf, sizeof(buf), "(null)");
    }
    isSuccess = renameConfig(index, buf);

  } else if (strcmp(argv[1], "count") == 0) {
    printf("%ld\n", getConfigCount());
    return 0;

  } else if (strcmp(argv[1], "current") == 0) {
    printf("%ld\n", getSelectedIndex());
    return 0;

  } else if (strcmp(argv[1], "statusbar") == 0) {
    printf("%ld\n", isStatusbarEnable());
    return 0;

  } else if (strcmp(argv[1], "toggle_statusbar") == 0) {
    CFIndex value = isStatusbarEnable();
    isSuccess = setStatusbarEnable(! value);

  } else if (strcmp(argv[1], "getname") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s getname index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    CFStringRef name = getConfigName(index);
    if (name) {
      char buf[512];
      if (CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8)) {
        stripString(buf, sizeof(buf));
        printf("%s\n", buf);
      } else {
        printf("(null)\n", buf);
      }
    }
    return 0;

  } else if ((strcmp(argv[1], "save") == 0) || (strcmp(argv[1], "load") == 0)) {
    CFIndex value = getSelectedIndex();
    CFStringRef identify = getIdentify(value);

    const char* targetFiles[] = {
      "/Library/org.pqrs/KeyRemap4MacBook/prefpane/checkbox.xml",
      "/Library/org.pqrs/KeyRemap4MacBook/prefpane/number.xml",
      NULL,
    };
    if (strcmp(argv[1], "save") == 0) {
      isSuccess = saveToFile(targetFiles, identify);
    }
    if (strcmp(argv[1], "load") == 0) {
      system("/Library/org.pqrs/KeyRemap4MacBook/bin/KeyRemap4MacBook_sysctl_reset");
      isSuccess = loadFromFile(targetFiles, identify);
    }
  }

  CFPreferencesAppSynchronize(applicationID);

finish:
  if (isSuccess) {
    fprintf(stderr, "[DONE]\n");
  } else {
    fprintf(stderr, "[ERROR]\n");
  }

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>App: fix Python object leak in ObjectIdentifier<commit_after><|endoftext|>


<commit_before>/*
 *
 * Copyright (C) 2009, Joacim Jacobsson ( j dot jacobsson at gmail dot com )
 * All rights reserved.
 *
 * See LICENSE file for details
 *
 */

#include "BehaviorTreeNode.h"
#include "../NodeToNodeArrow.h"
#include <btree/btree.h>

#include <QtGui/QtGui>
#include <QtSvg/QSvgRenderer>

const char* const g_NodeResourcePaths[_E_MAX_GRIST_TYPES_] = {
	":/nodes/unknown.svg",
	":/nodes/sequence.svg",
	":/nodes/selector.svg",
	":/nodes/parallel.svg",
	":/nodes/dyn_selector.svg",
	":/nodes/decorator.svg",
	":/nodes/action.svg"
};

BehaviorTreeNode::BehaviorTreeNode( Node* n, BehaviorTreeNode* parent )
	: QGraphicsSvgItem( g_NodeResourcePaths[n->m_Grist.m_Type] )
	, m_Node( n )
	, m_MouseState( E_MS_NONE )
	, m_DraggingArrow( 0x0 )
{
	setFlag( QGraphicsItem::ItemIsMovable, true );
	setFlag( QGraphicsItem::ItemIsSelectable, true );
	setFlag( QGraphicsItem::ItemStacksBehindParent, false );

	if( parent )
		setParentItem( parent );
	setZValue( 0.0 );
}

void BehaviorTreeNode::removeArrow(NodeToNodeArrow *arrow)
{
	int index = m_Arrows.indexOf(arrow);

	if (index != -1)
		m_Arrows.removeAt(index);
}

void BehaviorTreeNode::removeArrows()
{
	foreach( NodeToNodeArrow *arrow, m_Arrows )
	{
		arrow->startItem()->removeArrow(arrow);
		arrow->endItem()->removeArrow(arrow);
		scene()->removeItem(arrow);
		delete arrow;
	}
}

void BehaviorTreeNode::addArrow(NodeToNodeArrow *arrow)
{
	m_Arrows.append(arrow);
}

NodeToNodeArrow* BehaviorTreeNode::findArrowTo( BehaviorTreeNode* other )
{
	foreach( NodeToNodeArrow *arrow, m_Arrows )
	{
		if( arrow->startItem() == this && arrow->endItem() == other )
			return arrow;
		if( arrow->startItem() == other && arrow->endItem() == this )
			return arrow;
	}
	return 0x0;
}

QVariant BehaviorTreeNode::itemChange( GraphicsItemChange change, const QVariant &value )
{
	switch( change )
	{
	case ItemSelectedChange:
		update();
		break;
	case ItemPositionChange:
		break;
	}
	return QGraphicsSvgItem::itemChange( change, value );
}

void BehaviorTreeNode::mousePressEvent( QGraphicsSceneMouseEvent* event )
{
	if( event->button() == Qt::LeftButton )
	{
		m_MouseState = E_MS_LB_DOWN;
		m_StartPos = event->screenPos();
	}
	QGraphicsSvgItem::mousePressEvent( event );
}

void BehaviorTreeNode::mouseReleaseEvent( QGraphicsSceneMouseEvent* event )
{
	if( event->button() == Qt::LeftButton )
	{
		if( m_MouseState == E_MS_DRAGGING )
			draggingEnded();

		m_MouseState = E_MS_NONE;
	}
	QGraphicsSvgItem::mouseReleaseEvent( event );
}

void BehaviorTreeNode::mouseMoveEvent( QGraphicsSceneMouseEvent* event )
{
	if( m_MouseState == E_MS_LB_DOWN )
	{
		if( m_StartPos != event->screenPos() )
		{
			draggingStarted();
			m_MouseState = E_MS_DRAGGING;
		}
	}
	if( m_MouseState == E_MS_DRAGGING )
		lookForRelinkTarget();

	QGraphicsSvgItem::mouseMoveEvent( event );
}

void BehaviorTreeNode::draggingStarted()
{
	if( parentItem() )
	{
		BehaviorTreeNode* p = (BehaviorTreeNode*)parentItem();
		m_DraggingArrow = findArrowTo( p );
		p->removeArrow( m_DraggingArrow );
		m_DraggingArrow->setDashed( true );
		m_DraggingArrow->setStartAndEnd( this, p );

		QPointF position( scenePos() );
		setParentItem( 0x0 );
		setPos( position );
	}
	else
	{
		m_DraggingArrow = new NodeToNodeArrow( this, 0x0, scene() );
		m_DraggingArrow->setDashed( true );
		addArrow( m_DraggingArrow );
	}

	setupRelinkage();

	setZValue( 1.0 );
}

void BehaviorTreeNode::draggingEnded()
{
	if( m_Relinkage.m_Parent )
	{
		BehaviorTreeNode* p = (BehaviorTreeNode*)m_Relinkage.m_Parent->m_UserData;
		setPos( p->mapFromScene( scenePos() ) );
		setParentItem( p );

		p->addArrow( m_DraggingArrow );
		m_DraggingArrow->setStartAndEnd( p, this );
		m_DraggingArrow->setDashed( false );
		m_DraggingArrow = 0x0;
	}
	else
	{
		removeArrow( m_DraggingArrow );
		delete m_DraggingArrow;
		m_DraggingArrow = 0x0;
	}

	executeRelinkage();

	setZValue( 0.0 );

	emit nodeDragged();
}

void BehaviorTreeNode::setupRelinkage()
{
	m_Relinkage.m_Parent = m_Node->m_Pare;
	if( m_Node->m_Prev )
	{
		m_Relinkage.m_Sibling		= m_Node->m_Prev;
		m_Relinkage.m_BeforeSibling	= false;
	}
	else if( m_Node->m_Next )
	{
		m_Relinkage.m_Sibling		= m_Node->m_Next;
		m_Relinkage.m_BeforeSibling	= true;
	}
	else
	{
		m_Relinkage.m_Sibling		= 0x0;
		m_Relinkage.m_BeforeSibling = false;
	}
	UnlinkNodeFromParentAndSiblings( m_Node );
}

void BehaviorTreeNode::executeRelinkage()
{
	if( m_Relinkage.m_Parent )
		m_Node->m_Pare = m_Relinkage.m_Parent;

	if( m_Relinkage.m_Sibling )
	{
		if( m_Relinkage.m_BeforeSibling )
		{
			if( m_Relinkage.m_Sibling->m_Prev )
				m_Relinkage.m_Sibling->m_Prev->m_Next = m_Node;
			else
				SetFirstChild( m_Node->m_Pare, m_Node );

			m_Node->m_Prev = m_Relinkage.m_Sibling->m_Prev;

			m_Relinkage.m_Sibling->m_Prev = m_Node;
			m_Node->m_Next = m_Relinkage.m_Sibling;
		}
		else
		{
			if( m_Relinkage.m_Sibling->m_Next )
				m_Relinkage.m_Sibling->m_Next->m_Prev = m_Node;
			m_Node->m_Next = m_Relinkage.m_Sibling->m_Next;
			m_Relinkage.m_Sibling->m_Next = m_Node;
			m_Node->m_Prev = m_Relinkage.m_Sibling;
		}
	}
	else
	{
		m_Node->m_Next = 0x0;
		m_Node->m_Prev = 0x0;
		SetFirstChild( m_Node->m_Pare, m_Node );
	}
}

void BehaviorTreeNode::lookForRelinkTarget()
{
	QList<QGraphicsItem*> coll( collidingItems() );
	foreach( QGraphicsItem* uknown_item, coll )
	{
		if( uknown_item->type() != Type )
			continue;

		BehaviorTreeNode* item = (BehaviorTreeNode*)uknown_item;
		Node* p = item->m_Node;

		if( !AcceptsMoreChildren( p ) && !AcceptsMoreChildren( p = p->m_Pare ) )
			continue;

		// Current parent does not need evaluation.
		if( p == m_Relinkage.m_Parent )
			continue;

		Relinkage t;

		t.m_Parent  		= p;
		t.m_Sibling			= GetFirstChild( p );
		t.m_BeforeSibling 	= true;

		m_DraggingArrow->setStartAndEnd( this, (BehaviorTreeNode*)p->m_UserData );
		m_Relinkage = t;
	}
/*
	BehaviorTreeNode* p = (BehaviorTreeNode*)m_Relinkage.m_Parent->m_UserData;

	QPointF p1(p->scenePos());
	QPointF p2(scenePos());
	QRectF r1( p->boundingRect() );
	QRectF r2( boundingRect() );
	p1.rx() += r1.width() / 2.0f;
	p2.rx() += r2.width() / 2.0f;

	if( p1.x() > p2.x() )
		p2.rx() = p1.x() + (p1.x()-p2.x());

	QLineF line( p1, p2 );
	qreal a		= line.angle();
	qreal best	= 0;

	QList<QGraphicsItem*> childlist( p->childItems() );
	foreach( QGraphicsItem* uknown_item, coll )
	{
		if( uknown_item->type() != Type )
			continue;

		BehaviorTreeNode* item = (BehaviorTreeNode*)uknown_item;
		p2 = item->scenePos();
		r2 = item->boundingRect();
		p2.rx() += r2.width() / 2.0f;
		line.setP2( p2 );
		qreal ta = line.angle();

		if( m_Relinkage.m_Sibling == 0x0 )
		{
			m_Relinkage.m_Sibling = item->m_Node;
			best = ta;
			m_Relinkage.m_BeforeSibling = ta < a;
		}
		else if( qAbs( a - best ) > qAbs( ta - best ) )
		{
			m_Relinkage.m_Sibling = item->m_Node;
			best = ta;
			m_Relinkage.m_BeforeSibling = ta < a;
		}
	}
*/
}

<commit_msg>Let's get rid of that since it's full of fail.<commit_after>/*
 *
 * Copyright (C) 2009, Joacim Jacobsson ( j dot jacobsson at gmail dot com )
 * All rights reserved.
 *
 * See LICENSE file for details
 *
 */

#include "BehaviorTreeNode.h"
#include "../NodeToNodeArrow.h"
#include <btree/btree.h>

#include <QtGui/QtGui>
#include <QtSvg/QSvgRenderer>

const char* const g_NodeResourcePaths[_E_MAX_GRIST_TYPES_] = {
	":/nodes/unknown.svg",
	":/nodes/sequence.svg",
	":/nodes/selector.svg",
	":/nodes/parallel.svg",
	":/nodes/dyn_selector.svg",
	":/nodes/decorator.svg",
	":/nodes/action.svg"
};

BehaviorTreeNode::BehaviorTreeNode( Node* n, BehaviorTreeNode* parent )
	: QGraphicsSvgItem( g_NodeResourcePaths[n->m_Grist.m_Type] )
	, m_Node( n )
	, m_MouseState( E_MS_NONE )
	, m_DraggingArrow( 0x0 )
{
	setFlag( QGraphicsItem::ItemIsMovable, true );
	setFlag( QGraphicsItem::ItemIsSelectable, true );
	setFlag( QGraphicsItem::ItemStacksBehindParent, false );

	if( parent )
		setParentItem( parent );
	setZValue( 0.0 );
}

void BehaviorTreeNode::removeArrow(NodeToNodeArrow *arrow)
{
	int index = m_Arrows.indexOf(arrow);

	if (index != -1)
		m_Arrows.removeAt(index);
}

void BehaviorTreeNode::removeArrows()
{
	foreach( NodeToNodeArrow *arrow, m_Arrows )
	{
		arrow->startItem()->removeArrow(arrow);
		arrow->endItem()->removeArrow(arrow);
		scene()->removeItem(arrow);
		delete arrow;
	}
}

void BehaviorTreeNode::addArrow(NodeToNodeArrow *arrow)
{
	m_Arrows.append(arrow);
}

NodeToNodeArrow* BehaviorTreeNode::findArrowTo( BehaviorTreeNode* other )
{
	foreach( NodeToNodeArrow *arrow, m_Arrows )
	{
		if( arrow->startItem() == this && arrow->endItem() == other )
			return arrow;
		if( arrow->startItem() == other && arrow->endItem() == this )
			return arrow;
	}
	return 0x0;
}

QVariant BehaviorTreeNode::itemChange( GraphicsItemChange change, const QVariant &value )
{
	switch( change )
	{
	case ItemSelectedChange:
		update();
		break;
	case ItemPositionChange:
		break;
	}
	return QGraphicsSvgItem::itemChange( change, value );
}

void BehaviorTreeNode::mousePressEvent( QGraphicsSceneMouseEvent* event )
{
	if( event->button() == Qt::LeftButton )
	{
		m_MouseState = E_MS_LB_DOWN;
		m_StartPos = event->screenPos();
	}
	QGraphicsSvgItem::mousePressEvent( event );
}

void BehaviorTreeNode::mouseReleaseEvent( QGraphicsSceneMouseEvent* event )
{
	if( event->button() == Qt::LeftButton )
	{
		if( m_MouseState == E_MS_DRAGGING )
			draggingEnded();

		m_MouseState = E_MS_NONE;
	}
	QGraphicsSvgItem::mouseReleaseEvent( event );
}

void BehaviorTreeNode::mouseMoveEvent( QGraphicsSceneMouseEvent* event )
{
	if( m_MouseState == E_MS_LB_DOWN )
	{
		if( m_StartPos != event->screenPos() )
		{
			draggingStarted();
			m_MouseState = E_MS_DRAGGING;
		}
	}
	if( m_MouseState == E_MS_DRAGGING )
		lookForRelinkTarget();

	QGraphicsSvgItem::mouseMoveEvent( event );
}

void BehaviorTreeNode::draggingStarted()
{
	if( parentItem() )
	{
		BehaviorTreeNode* p = (BehaviorTreeNode*)parentItem();
		m_DraggingArrow = findArrowTo( p );
		p->removeArrow( m_DraggingArrow );
		m_DraggingArrow->setDashed( true );
		m_DraggingArrow->setStartAndEnd( this, p );

		QPointF position( scenePos() );
		setParentItem( 0x0 );
		setPos( position );
	}
	else
	{
		m_DraggingArrow = new NodeToNodeArrow( this, 0x0, scene() );
		m_DraggingArrow->setDashed( true );
		addArrow( m_DraggingArrow );
	}

	setupRelinkage();

	setZValue( 1.0 );
}

void BehaviorTreeNode::draggingEnded()
{
	if( m_Relinkage.m_Parent )
	{
		BehaviorTreeNode* p = (BehaviorTreeNode*)m_Relinkage.m_Parent->m_UserData;
		setPos( p->mapFromScene( scenePos() ) );
		setParentItem( p );

		p->addArrow( m_DraggingArrow );
		m_DraggingArrow->setStartAndEnd( p, this );
		m_DraggingArrow->setDashed( false );
		m_DraggingArrow = 0x0;
	}
	else
	{
		removeArrow( m_DraggingArrow );
		delete m_DraggingArrow;
		m_DraggingArrow = 0x0;
	}

	executeRelinkage();

	setZValue( 0.0 );

	emit nodeDragged();
}

void BehaviorTreeNode::setupRelinkage()
{
	m_Relinkage.m_Parent = m_Node->m_Pare;
	if( m_Node->m_Prev )
	{
		m_Relinkage.m_Sibling		= m_Node->m_Prev;
		m_Relinkage.m_BeforeSibling	= false;
	}
	else if( m_Node->m_Next )
	{
		m_Relinkage.m_Sibling		= m_Node->m_Next;
		m_Relinkage.m_BeforeSibling	= true;
	}
	else
	{
		m_Relinkage.m_Sibling		= 0x0;
		m_Relinkage.m_BeforeSibling = false;
	}
	UnlinkNodeFromParentAndSiblings( m_Node );
}

void BehaviorTreeNode::executeRelinkage()
{
	if( m_Relinkage.m_Parent )
		m_Node->m_Pare = m_Relinkage.m_Parent;

	if( m_Relinkage.m_Sibling )
	{
		if( m_Relinkage.m_BeforeSibling )
		{
			if( m_Relinkage.m_Sibling->m_Prev )
				m_Relinkage.m_Sibling->m_Prev->m_Next = m_Node;
			else
				SetFirstChild( m_Node->m_Pare, m_Node );

			m_Node->m_Prev = m_Relinkage.m_Sibling->m_Prev;

			m_Relinkage.m_Sibling->m_Prev = m_Node;
			m_Node->m_Next = m_Relinkage.m_Sibling;
		}
		else
		{
			if( m_Relinkage.m_Sibling->m_Next )
				m_Relinkage.m_Sibling->m_Next->m_Prev = m_Node;
			m_Node->m_Next = m_Relinkage.m_Sibling->m_Next;
			m_Relinkage.m_Sibling->m_Next = m_Node;
			m_Node->m_Prev = m_Relinkage.m_Sibling;
		}
	}
	else
	{
		m_Node->m_Next = 0x0;
		m_Node->m_Prev = 0x0;
		SetFirstChild( m_Node->m_Pare, m_Node );
	}
}

void BehaviorTreeNode::lookForRelinkTarget()
{
	QList<QGraphicsItem*> coll( collidingItems() );
	foreach( QGraphicsItem* uknown_item, coll )
	{
		if( uknown_item->type() != Type )
			continue;

		BehaviorTreeNode* item = (BehaviorTreeNode*)uknown_item;
		Node* p = item->m_Node;

		if( !AcceptsMoreChildren( p ) && !AcceptsMoreChildren( p = p->m_Pare ) )
			continue;

		// Current parent does not need evaluation.
		if( p == m_Relinkage.m_Parent )
			continue;

		Relinkage t;

		t.m_Parent  		= p;
		t.m_Sibling			= GetFirstChild( p );
		t.m_BeforeSibling 	= true;

		m_DraggingArrow->setStartAndEnd( this, (BehaviorTreeNode*)p->m_UserData );
		m_Relinkage = t;
	}
}

<|endoftext|>


<commit_before>#include <string>

#include "caffe/layer.hpp"
#include "caffe/layer_factory.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/vision_layers.hpp"

namespace caffe {

// GetLayer() defines the overall layer factory. The Get*Layer() functions
// define factories for layers with multiple computational engines.

// Get convolution layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetConvolutionLayer(
    const LayerParameter& param) {
  ConvolutionParameter_Engine engine = param.convolution_param().engine();
  if (engine == ConvolutionParameter_Engine_DEFAULT) {
    engine = ConvolutionParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = ConvolutionParameter_Engine_CUDNN;
#endif
  }
  if (engine == ConvolutionParameter_Engine_CAFFE) {
    return new ConvolutionLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == ConvolutionParameter_Engine_CUDNN) {
    return new CuDNNConvolutionLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get pooling layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetPoolingLayer(const LayerParameter& param) {
  PoolingParameter_Engine engine = param.pooling_param().engine();
  if (engine == PoolingParameter_Engine_DEFAULT) {
    engine = PoolingParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = PoolingParameter_Engine_CUDNN;
#endif
  }
  if (engine == PoolingParameter_Engine_CAFFE) {
    return new PoolingLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == PoolingParameter_Engine_CUDNN) {
    if (p_param.pad_h() || p_param.pad_w() || param.top_size() > 1) {
      LOG(INFO) << "CUDNN does not support padding or multiple tops. "
                << "Using Caffe's own pooling layer.";
      return new PoolingLayer<DType>(param);
    }
    return new CuDNNPoolingLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get relu layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetReLULayer(const LayerParameter& param) {
  ReLUParameter_Engine engine = param.relu_param().engine();
  if (engine == ReLUParameter_Engine_DEFAULT) {
    engine = ReLUParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = ReLUParameter_Engine_CUDNN;
#endif
  }
  if (engine == ReLUParameter_Engine_CAFFE) {
    return new ReLULayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == ReLUParameter_Engine_CUDNN) {
    return new CuDNNReLULayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get sigmoid layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetSigmoidLayer(const LayerParameter& param) {
  SigmoidParameter_Engine engine = param.sigmoid_param().engine();
  if (engine == SigmoidParameter_Engine_DEFAULT) {
    engine = SigmoidParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = SigmoidParameter_Engine_CUDNN;
#endif
  }
  if (engine == SigmoidParameter_Engine_CAFFE) {
    return new SigmoidLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == SigmoidParameter_Engine_CUDNN) {
    return new CuDNNSigmoidLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get tanh layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetTanHLayer(const LayerParameter& param) {
  TanHParameter_Engine engine = param.tanh_param().engine();
  if (engine == TanHParameter_Engine_DEFAULT) {
    engine = TanHParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = TanHParameter_Engine_CUDNN;
#endif
  }
  if (engine == TanHParameter_Engine_CAFFE) {
    return new TanHLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == TanHParameter_Engine_CUDNN) {
    return new CuDNNTanHLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get softmax layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetSoftmaxLayer(const LayerParameter& param) {
  SoftmaxParameter_Engine engine = param.softmax_param().engine();
  if (engine == SoftmaxParameter_Engine_DEFAULT) {
    engine = SoftmaxParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = SoftmaxParameter_Engine_CUDNN;
#endif
  }
  if (engine == SoftmaxParameter_Engine_CAFFE) {
    return new SoftmaxLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == SoftmaxParameter_Engine_CUDNN) {
    return new CuDNNSoftmaxLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Layers that have a specific creator function.
REGISTER_LAYER_CREATOR(CONVOLUTION, GetConvolutionLayer);
REGISTER_LAYER_CREATOR(POOLING, GetPoolingLayer);
REGISTER_LAYER_CREATOR(RELU, GetReLULayer);
REGISTER_LAYER_CREATOR(SIGMOID, GetSigmoidLayer);
REGISTER_LAYER_CREATOR(SOFTMAX, GetSoftmaxLayer);
REGISTER_LAYER_CREATOR(TANH, GetTanHLayer);

// Layers that use their constructor as their default creator.
REGISTER_LAYER_CLASS(ACCURACY, AccuracyLayer);
REGISTER_LAYER_CLASS(ABSVAL, AbsValLayer);
REGISTER_LAYER_CLASS(ARGMAX, ArgMaxLayer);
REGISTER_LAYER_CLASS(BNLL, BNLLLayer);
REGISTER_LAYER_CLASS(CONCAT, ConcatLayer);
REGISTER_LAYER_CLASS(CONTRASTIVE_LOSS, ContrastiveLossLayer);
REGISTER_LAYER_CLASS(DATA, DataLayer);
REGISTER_LAYER_CLASS(DROPOUT, DropoutLayer);
REGISTER_LAYER_CLASS(DUMMY_DATA, DummyDataLayer);
REGISTER_LAYER_CLASS(EUCLIDEAN_LOSS, EuclideanLossLayer);
REGISTER_LAYER_CLASS(ELTWISE, EltwiseLayer);
REGISTER_LAYER_CLASS(FLATTEN, FlattenLayer);
REGISTER_LAYER_CLASS(HDF5_DATA, HDF5DataLayer);
REGISTER_LAYER_CLASS(HDF5_OUTPUT, HDF5OutputLayer);
REGISTER_LAYER_CLASS(HINGE_LOSS, HingeLossLayer);
REGISTER_LAYER_CLASS(IMAGE_DATA, ImageDataLayer);
REGISTER_LAYER_CLASS(IM2COL, Im2colLayer);
REGISTER_LAYER_CLASS(INFOGAIN_LOSS, InfogainLossLayer);
REGISTER_LAYER_CLASS(INNER_PRODUCT, InnerProductLayer);
REGISTER_LAYER_CLASS(LRN, LRNLayer);
REGISTER_LAYER_CLASS(MEMORY_DATA, MemoryDataLayer);
REGISTER_LAYER_CLASS(MVN, MVNLayer);
REGISTER_LAYER_CLASS(MULTINOMIAL_LOGISTIC_LOSS, MultinomialLogisticLossLayer);
REGISTER_LAYER_CLASS(POWER, PowerLayer);
REGISTER_LAYER_CLASS(SILENCE, SilenceLayer);
REGISTER_LAYER_CLASS(SIGMOID_CROSS_ENTROPY_LOSS, SigmoidCrossEntropyLossLayer);
REGISTER_LAYER_CLASS(SLICE, SliceLayer);
REGISTER_LAYER_CLASS(SOFTMAX_LOSS, SoftmaxWithLossLayer);
REGISTER_LAYER_CLASS(SPLIT, SplitLayer);
REGISTER_LAYER_CLASS(WINDOW_DATA, WindowDataLayer);

}  // namespace caffe
<commit_msg>add long-ignored threshold layer<commit_after>#include <string>

#include "caffe/layer.hpp"
#include "caffe/layer_factory.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/vision_layers.hpp"

namespace caffe {

// GetLayer() defines the overall layer factory. The Get*Layer() functions
// define factories for layers with multiple computational engines.

// Get convolution layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetConvolutionLayer(
    const LayerParameter& param) {
  ConvolutionParameter_Engine engine = param.convolution_param().engine();
  if (engine == ConvolutionParameter_Engine_DEFAULT) {
    engine = ConvolutionParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = ConvolutionParameter_Engine_CUDNN;
#endif
  }
  if (engine == ConvolutionParameter_Engine_CAFFE) {
    return new ConvolutionLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == ConvolutionParameter_Engine_CUDNN) {
    return new CuDNNConvolutionLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get pooling layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetPoolingLayer(const LayerParameter& param) {
  PoolingParameter_Engine engine = param.pooling_param().engine();
  if (engine == PoolingParameter_Engine_DEFAULT) {
    engine = PoolingParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = PoolingParameter_Engine_CUDNN;
#endif
  }
  if (engine == PoolingParameter_Engine_CAFFE) {
    return new PoolingLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == PoolingParameter_Engine_CUDNN) {
    if (p_param.pad_h() || p_param.pad_w() || param.top_size() > 1) {
      LOG(INFO) << "CUDNN does not support padding or multiple tops. "
                << "Using Caffe's own pooling layer.";
      return new PoolingLayer<DType>(param);
    }
    return new CuDNNPoolingLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get relu layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetReLULayer(const LayerParameter& param) {
  ReLUParameter_Engine engine = param.relu_param().engine();
  if (engine == ReLUParameter_Engine_DEFAULT) {
    engine = ReLUParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = ReLUParameter_Engine_CUDNN;
#endif
  }
  if (engine == ReLUParameter_Engine_CAFFE) {
    return new ReLULayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == ReLUParameter_Engine_CUDNN) {
    return new CuDNNReLULayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get sigmoid layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetSigmoidLayer(const LayerParameter& param) {
  SigmoidParameter_Engine engine = param.sigmoid_param().engine();
  if (engine == SigmoidParameter_Engine_DEFAULT) {
    engine = SigmoidParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = SigmoidParameter_Engine_CUDNN;
#endif
  }
  if (engine == SigmoidParameter_Engine_CAFFE) {
    return new SigmoidLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == SigmoidParameter_Engine_CUDNN) {
    return new CuDNNSigmoidLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get tanh layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetTanHLayer(const LayerParameter& param) {
  TanHParameter_Engine engine = param.tanh_param().engine();
  if (engine == TanHParameter_Engine_DEFAULT) {
    engine = TanHParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = TanHParameter_Engine_CUDNN;
#endif
  }
  if (engine == TanHParameter_Engine_CAFFE) {
    return new TanHLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == TanHParameter_Engine_CUDNN) {
    return new CuDNNTanHLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get softmax layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetSoftmaxLayer(const LayerParameter& param) {
  SoftmaxParameter_Engine engine = param.softmax_param().engine();
  if (engine == SoftmaxParameter_Engine_DEFAULT) {
    engine = SoftmaxParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = SoftmaxParameter_Engine_CUDNN;
#endif
  }
  if (engine == SoftmaxParameter_Engine_CAFFE) {
    return new SoftmaxLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == SoftmaxParameter_Engine_CUDNN) {
    return new CuDNNSoftmaxLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Layers that have a specific creator function.
REGISTER_LAYER_CREATOR(CONVOLUTION, GetConvolutionLayer);
REGISTER_LAYER_CREATOR(POOLING, GetPoolingLayer);
REGISTER_LAYER_CREATOR(RELU, GetReLULayer);
REGISTER_LAYER_CREATOR(SIGMOID, GetSigmoidLayer);
REGISTER_LAYER_CREATOR(SOFTMAX, GetSoftmaxLayer);
REGISTER_LAYER_CREATOR(TANH, GetTanHLayer);

// Layers that use their constructor as their default creator.
REGISTER_LAYER_CLASS(ACCURACY, AccuracyLayer);
REGISTER_LAYER_CLASS(ABSVAL, AbsValLayer);
REGISTER_LAYER_CLASS(ARGMAX, ArgMaxLayer);
REGISTER_LAYER_CLASS(BNLL, BNLLLayer);
REGISTER_LAYER_CLASS(CONCAT, ConcatLayer);
REGISTER_LAYER_CLASS(CONTRASTIVE_LOSS, ContrastiveLossLayer);
REGISTER_LAYER_CLASS(DATA, DataLayer);
REGISTER_LAYER_CLASS(DROPOUT, DropoutLayer);
REGISTER_LAYER_CLASS(DUMMY_DATA, DummyDataLayer);
REGISTER_LAYER_CLASS(EUCLIDEAN_LOSS, EuclideanLossLayer);
REGISTER_LAYER_CLASS(ELTWISE, EltwiseLayer);
REGISTER_LAYER_CLASS(FLATTEN, FlattenLayer);
REGISTER_LAYER_CLASS(HDF5_DATA, HDF5DataLayer);
REGISTER_LAYER_CLASS(HDF5_OUTPUT, HDF5OutputLayer);
REGISTER_LAYER_CLASS(HINGE_LOSS, HingeLossLayer);
REGISTER_LAYER_CLASS(IMAGE_DATA, ImageDataLayer);
REGISTER_LAYER_CLASS(IM2COL, Im2colLayer);
REGISTER_LAYER_CLASS(INFOGAIN_LOSS, InfogainLossLayer);
REGISTER_LAYER_CLASS(INNER_PRODUCT, InnerProductLayer);
REGISTER_LAYER_CLASS(LRN, LRNLayer);
REGISTER_LAYER_CLASS(MEMORY_DATA, MemoryDataLayer);
REGISTER_LAYER_CLASS(MVN, MVNLayer);
REGISTER_LAYER_CLASS(MULTINOMIAL_LOGISTIC_LOSS, MultinomialLogisticLossLayer);
REGISTER_LAYER_CLASS(POWER, PowerLayer);
REGISTER_LAYER_CLASS(SILENCE, SilenceLayer);
REGISTER_LAYER_CLASS(SIGMOID_CROSS_ENTROPY_LOSS, SigmoidCrossEntropyLossLayer);
REGISTER_LAYER_CLASS(SLICE, SliceLayer);
REGISTER_LAYER_CLASS(SOFTMAX_LOSS, SoftmaxWithLossLayer);
REGISTER_LAYER_CLASS(SPLIT, SplitLayer);
REGISTER_LAYER_CLASS(THRESHOLD, ThresholdLayer);
REGISTER_LAYER_CLASS(WINDOW_DATA, WindowDataLayer);

}  // namespace caffe
<|endoftext|>


<commit_before>#pragma once

#include <iterator>

#include <cstdlib> //malloc, realloc
#include <cstring> //memcpy
#include <exception> //bad_alloc

namespace tyti {
template<typename T>
class any_iterator : std::iterator<std::bidirectional_iterator_tag, T>
{
    //functionpointer save structure
    struct TypeInfos
    {
        void(*inc_fn)(void*);
        void(*dec_fn)(void*);
        const bool(*equal_fn)(const void*,const void*);
        const T*(*deref_fn)(const void*);
        size_t size;
    };

    template<typename IterType>
    TypeInfos* getFunctionInfos()
    {
        static TypeInfos ti =
        {
            any_iterator::inc<IterType>,
            any_iterator::dec<IterType>,
            any_iterator::equal<IterType>,
            any_iterator::deref<IterType>,
            sizeof(IterType)
        };
        return &ti;
    }

    //access functions
    template<typename Iter>
    static void inc(void* _ptr)
    {
        ++(*reinterpret_cast<Iter*>(_ptr));
    }

    template<typename Iter>
    static void dec(void* _ptr)
    {
        --(*reinterpret_cast<Iter*>(_ptr));
    }

    template<typename Iter>
    static const T* deref(const void* _ptr)
    {
        return &(*(*reinterpret_cast<const Iter*>(_ptr)));
    }

    template<typename Iter>
    static const bool equal(const void* _lhs, const void* _rhs)
    {
        return *reinterpret_cast<const Iter*>(_lhs) == *reinterpret_cast<const Iter*>(_rhs);
    }

    // helper functions
    static void assign(void* dst_, size_t dst_size_, const void* src_, size_t src_size_)
    {
        if (dst_size_ < src_size_)
        {
            dst_ = std::realloc(dst_, src_size_);
            if (!dst_)
                throw std::bad_alloc();
        }
        std::memcpy(dst_, src_, src_size_);
    }

    // member variables
    void* ptr_;
    TypeInfos* ti_;

    /// Interface
public:
    template <typename IterType>
    explicit any_iterator(const IterType& _iter)
        : ptr_(std::malloc(sizeof(IterType))), ti_(getFunctionInfos<IterType>())
    {
        if (!ptr_)
            throw std::bad_alloc();
        std::memcpy(ptr_, &_iter, sizeof(IterType));
    }

    any_iterator(const any_iterator& _iter)
        : ptr_(std::malloc(_iter.ti_->size)), ti_(_iter.ti_)
    {
        if (!ptr_)
            throw std::bad_alloc();
        std::memcpy(ptr_, _iter.ptr_, ti_->size);
    }

    template <typename IterType>
    any_iterator operator=(const IterType& _iter)
    {
        const size_t old_size = ti_->size;
        const size_t new_size = sizeof(IterType);
        assign(ptr_, old_size, &_iter, new_size);
        ti_ = getFunctionInfos<IterType>();
        return *this;
    }

    any_iterator operator=(const any_iterator& _iter)
    {
        const size_t old_size = ti_->size;
        const size_t new_size = _iter.ti_->size;
        assign(ptr_, old_size, _iter.ptr_, new_size);
        ti_ = _iter.ti_;
        return *this;
    }

    ~any_iterator()
    {
        std::free(ptr_);
    }

    bool operator==(const any_iterator& _rhs) const
    {
        if (ti_ != _rhs.ti_) //different types
            return false;
        return ti_->equal_fn(ptr_, _rhs.ptr_);
    }

    template <typename IterType>
    bool operator==(const IterType& _rhs) const {
        return ti_->equal_fn(ptr_, reinterpret_cast<const void*>(&_rhs));
    }

    template <typename IterType>
    bool operator!=(const IterType& _rhs) const{
        return !operator==(_rhs);
    }

    /// Standard pre-increment operator
    any_iterator& operator++() {
        ti_->inc_fn(ptr_);
        return *this;
    }

    /// Standard post-increment operator
    any_iterator operator++(int) {
        any_iterator cpy(*this);
        ti_->inc_fn(ptr_);
        return cpy;
    }

    /// Standard pre-decrement operator
    any_iterator& operator--() {
        ti_->dec_fn(ptr_);
        return *this;
    }

    /// Standard post-decrement operator
    any_iterator operator--(int) {
        any_iterator cpy(*this);
        ti_->dec_fn(ptr_);
        return cpy;
    }

    const T& operator*() const {
        return *(ti_->deref_fn(ptr_));
    }

    /// Standard pointer operator.
    const T* operator->() const {
        return ti_->deref_fn(ptr_);
    }
};

// C++17 todo:
//if msvc >= 2017 or gcc with c++17 support
//#include <any>
//using AnyIterator = AnyIteratorT<std::any>;
//endif

} // end namespace tyti

template<typename IterT, typename T>
bool operator==(const IterT& _lhs, const tyti::any_iterator<T>& _rhs)
{
    return _rhs == _lhs;
}

template<typename IterT, typename T>
bool operator!=(const IterT& _lhs, const tyti::any_iterator<T>& _rhs)
{
    return _rhs != _lhs;
}<commit_msg>Update any_iterator.hpp (#3)<commit_after>#pragma once

#include <iterator>

#include <cstdlib> //malloc, realloc
#include <cstring> //memcpy
#include <exception> //bad_alloc

namespace tyti {
template<typename T>
class any_iterator : std::iterator<std::bidirectional_iterator_tag, T>
{
    //functionpointer save structure
    struct TypeInfos
    {
        void(*inc_fn)(void*);
        void(*dec_fn)(void*);
        const bool(*equal_fn)(const void*,const void*);
        const T*(*deref_fn)(const void*);
        size_t size;
    };

    template<typename IterType>
    TypeInfos* getFunctionInfos()
    {
        static TypeInfos ti =
        {
            any_iterator::inc<IterType>,
            any_iterator::dec<IterType>,
            any_iterator::equal<IterType>,
            any_iterator::deref<IterType>,
            sizeof(IterType)
        };
        return &ti;
    }

    //access functions
    template<typename Iter>
    static void inc(void* _ptr)
    {
        ++(*reinterpret_cast<Iter*>(_ptr));
    }

    template<typename Iter>
    static void dec(void* _ptr)
    {
        --(*reinterpret_cast<Iter*>(_ptr));
    }

    template<typename Iter>
    static const T* deref(const void* _ptr)
    {
        return &(*(*reinterpret_cast<const Iter*>(_ptr)));
    }

    template<typename Iter>
    static const bool equal(const void* _lhs, const void* _rhs)
    {
        return *reinterpret_cast<const Iter*>(_lhs) == *reinterpret_cast<const Iter*>(_rhs);
    }

    // helper functions
    static void assign(void** dst_, size_t dst_size_, const void* src_, size_t src_size_)
    {
        if (dst_size_ < src_size_)
        {
            *dst_ = std::realloc(*dst_, src_size_);
            if (!*dst_)
                throw std::bad_alloc();
        }
        std::memcpy(*dst_, src_, src_size_);
    }

    // member variables
    void* ptr_;
    TypeInfos* ti_;

    /// Interface
public:
    template <typename IterType>
    explicit any_iterator(const IterType& _iter)
        : ptr_(std::malloc(sizeof(IterType))), ti_(getFunctionInfos<IterType>())
    {
        if (!ptr_)
            throw std::bad_alloc();
        std::memcpy(ptr_, &_iter, sizeof(IterType));
    }

    any_iterator(const any_iterator& _iter)
        : ptr_(std::malloc(_iter.ti_->size)), ti_(_iter.ti_)
    {
        if (!ptr_)
            throw std::bad_alloc();
        std::memcpy(ptr_, _iter.ptr_, ti_->size);
    }

    template <typename IterType>
    any_iterator operator=(const IterType& _iter)
    {
        const size_t old_size = ti_->size;
        const size_t new_size = sizeof(IterType);
        assign(&ptr_, old_size, &_iter, new_size);
        ti_ = getFunctionInfos<IterType>();
        return *this;
    }

    any_iterator operator=(const any_iterator& _iter)
    {
        const size_t old_size = ti_->size;
        const size_t new_size = _iter.ti_->size;
        assign(&ptr_, old_size, _iter.ptr_, new_size);
        ti_ = _iter.ti_;
        return *this;
    }

    ~any_iterator()
    {
        std::free(ptr_);
    }

    bool operator==(const any_iterator& _rhs) const
    {
        if (ti_ != _rhs.ti_) //different types
            return false;
        return ti_->equal_fn(ptr_, _rhs.ptr_);
    }

    template <typename IterType>
    bool operator==(const IterType& _rhs) const {
        return ti_->equal_fn(ptr_, reinterpret_cast<const void*>(&_rhs));
    }

    template <typename IterType>
    bool operator!=(const IterType& _rhs) const{
        return !operator==(_rhs);
    }

    /// Standard pre-increment operator
    any_iterator& operator++() {
        ti_->inc_fn(ptr_);
        return *this;
    }

    /// Standard post-increment operator
    any_iterator operator++(int) {
        any_iterator cpy(*this);
        ti_->inc_fn(ptr_);
        return cpy;
    }

    /// Standard pre-decrement operator
    any_iterator& operator--() {
        ti_->dec_fn(ptr_);
        return *this;
    }

    /// Standard post-decrement operator
    any_iterator operator--(int) {
        any_iterator cpy(*this);
        ti_->dec_fn(ptr_);
        return cpy;
    }

    const T& operator*() const {
        return *(ti_->deref_fn(ptr_));
    }

    /// Standard pointer operator.
    const T* operator->() const {
        return ti_->deref_fn(ptr_);
    }
};

// C++17 todo:
//if msvc >= 2017 or gcc with c++17 support
//#include <any>
//using AnyIterator = AnyIteratorT<std::any>;
//endif

} // end namespace tyti

template<typename IterT, typename T>
bool operator==(const IterT& _lhs, const tyti::any_iterator<T>& _rhs)
{
    return _rhs == _lhs;
}

template<typename IterT, typename T>
bool operator!=(const IterT& _lhs, const tyti::any_iterator<T>& _rhs)
{
    return _rhs != _lhs;
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "m2ts/vpxpes2ts.h"

#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <vector>

namespace libwebm {
// TODO(tomfinegan): Dedupe this and PesHeaderField.
// Stores a value and its size in bits for writing into a MPEG2 TS Header.
// Maximum size is 64 bits. Users may call the Check() method to perform minimal
// validation (size > 0 and <= 64).
struct TsHeaderField {
  TsHeaderField(std::uint64_t value, std::uint32_t size_in_bits,
                std::uint8_t byte_index, std::uint8_t bits_to_shift)
      : bits(value),
        num_bits(size_in_bits),
        index(byte_index),
        shift(bits_to_shift) {}
  TsHeaderField() = delete;
  TsHeaderField(const TsHeaderField&) = default;
  TsHeaderField(TsHeaderField&&) = default;
  ~TsHeaderField() = default;
  bool Check() const {
    return num_bits > 0 && num_bits <= 64 && shift >= 0 && shift < 64;
  }

  // Value to be stored in the field.
  std::uint64_t bits;

  // Number of bits in the value.
  const int num_bits;

  // Index into the header for the byte in which |bits| will be written.
  const std::uint8_t index;

  // Number of bits to left shift value before or'ing. Ignored for whole bytes.
  const int shift;
};

// Data storage for MPEG2 Transport Stream headers.
// https://en.wikipedia.org/wiki/MPEG_transport_stream#Packet
struct TsHeader {
  TsHeader(bool payload_start, bool adaptation_flag, std::uint8_t counter)
      : is_payload_start(payload_start),
        has_adaptation(adaptation_flag),
        counter_value(counter) {}
  TsHeader() = delete;
  TsHeader(const TsHeader&) = default;
  TsHeader(TsHeader&&) = default;
  ~TsHeader() = default;

  void Write(PacketDataBuffer* buffer) const;

  // Indicates the packet is the beginning of a new fragmented payload.
  const bool is_payload_start;

  // Indicates the packet contains an adaptation field.
  const bool has_adaptation;

  // The sync byte is the bit pattern of 0x47 (ASCII char 'G').
  const std::uint8_t kTsHeaderSyncByte = 0x47;
  const std::uint8_t sync_byte = kTsHeaderSyncByte;

  // Value for |continuity_counter|. Used to detect gaps when demuxing.
  const std::uint8_t counter_value;

  // Set when FEC is impossible. Always 0.
  const TsHeaderField transport_error_indicator = TsHeaderField(0, 1, 1, 7);

  // This MPEG2 TS header is the start of a new payload (aka PES packet).
  const TsHeaderField payload_unit_start_indicator =
      TsHeaderField(is_payload_start ? 1 : 0, 1, 1, 6);

  // Set when the current packet has a higher priority than other packets with
  // the same PID. Always 0 for VPX.
  const TsHeaderField transport_priority = TsHeaderField(0, 1, 1, 5);

  // https://en.wikipedia.org/wiki/MPEG_transport_stream#Packet_Identifier_.28PID.29
  // 0x0020-0x1FFA May be assigned as needed to Program Map Tables, elementary
  // streams and other data tables.
  // Note: Though we hard code to 0x20, this value is actually 13 bits-- the
  // buffer for the header is always set to 0, so it doesn't matter in practice.
  const TsHeaderField pid = TsHeaderField(0x20, 8, 2, 0);

  // Indicates scrambling key. Unused; always 0.
  const TsHeaderField scrambling_control = TsHeaderField(0, 2, 3, 6);

  // Adaptation field flag. Unused; always 0.
  // TODO(tomfinegan): Not sure this is OK. Might need to add support for
  // writing the Adaptation Field.
  const TsHeaderField adaptation_field_flag =
      TsHeaderField(has_adaptation ? 1 : 0, 1, 3, 5);

  // Payload flag. All output packets created here have payloads. Always 1.
  const TsHeaderField payload_flag = TsHeaderField(1, 1, 3, 4);

  // Continuity counter. Two bit field that is incremented for every packet.
  const TsHeaderField continuity_counter =
      TsHeaderField(counter_value, 4, 3, 3);
};

void TsHeader::Write(PacketDataBuffer* buffer) const {
  std::uint8_t* byte = &(*buffer)[0];
  *byte = sync_byte;

  *++byte = 0;
  *byte |= transport_error_indicator.bits << transport_error_indicator.shift;
  *byte |= payload_unit_start_indicator.bits
           << payload_unit_start_indicator.shift;
  *byte |= transport_priority.bits << transport_priority.shift;

  *++byte = pid.bits;

  *++byte = 0;
  *byte |= scrambling_control.bits << scrambling_control.shift;
  *byte |= adaptation_field_flag.bits << adaptation_field_flag.shift;
  *byte |= payload_flag.bits << payload_flag.shift;
  *byte |= continuity_counter.bits;  // last 4 bits.
}

bool VpxPes2Ts::ConvertToFile() {
  output_file_ = FilePtr(fopen(output_file_name_.c_str(), "wb"), FILEDeleter());
  if (output_file_ == nullptr) {
    std::fprintf(stderr, "VpxPes2Ts: Cannot open %s for output.\n",
                 output_file_name_.c_str());
    return false;
  }
  pes_converter_.reset(new Webm2Pes(input_file_name_, this));
  if (pes_converter_ == nullptr) {
    std::fprintf(stderr, "VpxPes2Ts: Out of memory.\n");
    return false;
  }
  return pes_converter_->ConvertToPacketReceiver();
}

bool VpxPes2Ts::ReceivePacket(const PacketDataBuffer& packet_data) {
  const int kTsHeaderSize = 4;
  const int kTsPayloadSize = 184;
  const int kTsPacketSize = kTsHeaderSize + kTsPayloadSize;
  int bytes_to_packetize = packet_data.size();
  std::uint8_t continuity_counter = 0;
  std::size_t read_pos = 0;

  ts_buffer_.reserve(kTsPacketSize);

  while (bytes_to_packetize > 0) {
    if (continuity_counter > 0xf)
      continuity_counter = 0;

    // Calculate payload size (need to know if we'll have to pad with an empty
    // adaptation field).
    int payload_size = std::min(bytes_to_packetize, kTsPayloadSize);

    // Write the TS header.
    const TsHeader header(
        bytes_to_packetize == static_cast<int>(packet_data.size()),
        payload_size != kTsPayloadSize, continuity_counter);
    header.Write(&ts_buffer_);
    int write_pos = kTsHeaderSize;

    // (pre)Pad payload with an empty adaptation field. All packets must be
    // |kTsPacketSize| (188).
    if (payload_size < kTsPayloadSize) {
      // We need at least 2 bytes to write an empty adaptation field.
      if (payload_size == (kTsPayloadSize - 1)) {
        payload_size--;
      }

      // Padding adaptation field:
      //   8 bits: number of adaptation field bytes following this byte.
      //   8 bits: unused (in this program) flags.
      // This is followed by a run of 0xff to reach |kTsPayloadSize| (184)
      // bytes.
      const int pad_size = kTsPayloadSize - payload_size - 1 - 1;
      ts_buffer_[write_pos++] = pad_size + 1;
      ts_buffer_[write_pos++] = 0;

      const std::uint8_t kStuffingByte = 0xff;
      for (int i = 0; i < pad_size; ++i) {
        ts_buffer_[write_pos++] = kStuffingByte;
      }
    }

    for (int i = 0; i < payload_size; ++i) {
      ts_buffer_[write_pos++] = packet_data[read_pos++];
    }

    bytes_to_packetize -= payload_size;
    continuity_counter++;

    if (write_pos != kTsPacketSize) {
      fprintf(stderr, "VpxPes2Ts: Invalid packet length.\n");
      return false;
    }

    // Write contents of |ts_buffer_| to |output_file_|.
    // TODO(tomfinegan): Writing 188 bytes at a time isn't exactly efficient...
    // Fix me.
    if (static_cast<int>(std::fwrite(&ts_buffer_[0], 1, kTsPacketSize,
                                     output_file_.get())) != kTsPacketSize) {
      std::fprintf(stderr, "VpxPes2Ts: TS packet write failed.\n");
      return false;
    }
  }

  return true;
}

}  // namespace libwebm
<commit_msg>msvc/vpxpes2ts: Fix MSVC integer conversion warning.<commit_after>// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "m2ts/vpxpes2ts.h"

#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <vector>

namespace libwebm {
// TODO(tomfinegan): Dedupe this and PesHeaderField.
// Stores a value and its size in bits for writing into a MPEG2 TS Header.
// Maximum size is 64 bits. Users may call the Check() method to perform minimal
// validation (size > 0 and <= 64).
struct TsHeaderField {
  TsHeaderField(std::uint64_t value, std::uint32_t size_in_bits,
                std::uint8_t byte_index, std::uint8_t bits_to_shift)
      : bits(value),
        num_bits(size_in_bits),
        index(byte_index),
        shift(bits_to_shift) {}
  TsHeaderField() = delete;
  TsHeaderField(const TsHeaderField&) = default;
  TsHeaderField(TsHeaderField&&) = default;
  ~TsHeaderField() = default;
  bool Check() const {
    return num_bits > 0 && num_bits <= 64 && shift >= 0 && shift < 64;
  }

  // Value to be stored in the field.
  std::uint64_t bits;

  // Number of bits in the value.
  const int num_bits;

  // Index into the header for the byte in which |bits| will be written.
  const std::uint8_t index;

  // Number of bits to left shift value before or'ing. Ignored for whole bytes.
  const int shift;
};

// Data storage for MPEG2 Transport Stream headers.
// https://en.wikipedia.org/wiki/MPEG_transport_stream#Packet
struct TsHeader {
  TsHeader(bool payload_start, bool adaptation_flag, std::uint8_t counter)
      : is_payload_start(payload_start),
        has_adaptation(adaptation_flag),
        counter_value(counter) {}
  TsHeader() = delete;
  TsHeader(const TsHeader&) = default;
  TsHeader(TsHeader&&) = default;
  ~TsHeader() = default;

  void Write(PacketDataBuffer* buffer) const;

  // Indicates the packet is the beginning of a new fragmented payload.
  const bool is_payload_start;

  // Indicates the packet contains an adaptation field.
  const bool has_adaptation;

  // The sync byte is the bit pattern of 0x47 (ASCII char 'G').
  const std::uint8_t kTsHeaderSyncByte = 0x47;
  const std::uint8_t sync_byte = kTsHeaderSyncByte;

  // Value for |continuity_counter|. Used to detect gaps when demuxing.
  const std::uint8_t counter_value;

  // Set when FEC is impossible. Always 0.
  const TsHeaderField transport_error_indicator = TsHeaderField(0, 1, 1, 7);

  // This MPEG2 TS header is the start of a new payload (aka PES packet).
  const TsHeaderField payload_unit_start_indicator =
      TsHeaderField(is_payload_start ? 1 : 0, 1, 1, 6);

  // Set when the current packet has a higher priority than other packets with
  // the same PID. Always 0 for VPX.
  const TsHeaderField transport_priority = TsHeaderField(0, 1, 1, 5);

  // https://en.wikipedia.org/wiki/MPEG_transport_stream#Packet_Identifier_.28PID.29
  // 0x0020-0x1FFA May be assigned as needed to Program Map Tables, elementary
  // streams and other data tables.
  // Note: Though we hard code to 0x20, this value is actually 13 bits-- the
  // buffer for the header is always set to 0, so it doesn't matter in practice.
  const TsHeaderField pid = TsHeaderField(0x20, 8, 2, 0);

  // Indicates scrambling key. Unused; always 0.
  const TsHeaderField scrambling_control = TsHeaderField(0, 2, 3, 6);

  // Adaptation field flag. Unused; always 0.
  // TODO(tomfinegan): Not sure this is OK. Might need to add support for
  // writing the Adaptation Field.
  const TsHeaderField adaptation_field_flag =
      TsHeaderField(has_adaptation ? 1 : 0, 1, 3, 5);

  // Payload flag. All output packets created here have payloads. Always 1.
  const TsHeaderField payload_flag = TsHeaderField(1, 1, 3, 4);

  // Continuity counter. Two bit field that is incremented for every packet.
  const TsHeaderField continuity_counter =
      TsHeaderField(counter_value, 4, 3, 3);
};

void TsHeader::Write(PacketDataBuffer* buffer) const {
  std::uint8_t* byte = &(*buffer)[0];
  *byte = sync_byte;

  *++byte = 0;
  *byte |= transport_error_indicator.bits << transport_error_indicator.shift;
  *byte |= payload_unit_start_indicator.bits
           << payload_unit_start_indicator.shift;
  *byte |= transport_priority.bits << transport_priority.shift;

  *++byte = pid.bits & 0xff;

  *++byte = 0;
  *byte |= scrambling_control.bits << scrambling_control.shift;
  *byte |= adaptation_field_flag.bits << adaptation_field_flag.shift;
  *byte |= payload_flag.bits << payload_flag.shift;
  *byte |= continuity_counter.bits;  // last 4 bits.
}

bool VpxPes2Ts::ConvertToFile() {
  output_file_ = FilePtr(fopen(output_file_name_.c_str(), "wb"), FILEDeleter());
  if (output_file_ == nullptr) {
    std::fprintf(stderr, "VpxPes2Ts: Cannot open %s for output.\n",
                 output_file_name_.c_str());
    return false;
  }
  pes_converter_.reset(new Webm2Pes(input_file_name_, this));
  if (pes_converter_ == nullptr) {
    std::fprintf(stderr, "VpxPes2Ts: Out of memory.\n");
    return false;
  }
  return pes_converter_->ConvertToPacketReceiver();
}

bool VpxPes2Ts::ReceivePacket(const PacketDataBuffer& packet_data) {
  const int kTsHeaderSize = 4;
  const int kTsPayloadSize = 184;
  const int kTsPacketSize = kTsHeaderSize + kTsPayloadSize;
  int bytes_to_packetize = packet_data.size();
  std::uint8_t continuity_counter = 0;
  std::size_t read_pos = 0;

  ts_buffer_.reserve(kTsPacketSize);

  while (bytes_to_packetize > 0) {
    if (continuity_counter > 0xf)
      continuity_counter = 0;

    // Calculate payload size (need to know if we'll have to pad with an empty
    // adaptation field).
    int payload_size = std::min(bytes_to_packetize, kTsPayloadSize);

    // Write the TS header.
    const TsHeader header(
        bytes_to_packetize == static_cast<int>(packet_data.size()),
        payload_size != kTsPayloadSize, continuity_counter);
    header.Write(&ts_buffer_);
    int write_pos = kTsHeaderSize;

    // (pre)Pad payload with an empty adaptation field. All packets must be
    // |kTsPacketSize| (188).
    if (payload_size < kTsPayloadSize) {
      // We need at least 2 bytes to write an empty adaptation field.
      if (payload_size == (kTsPayloadSize - 1)) {
        payload_size--;
      }

      // Padding adaptation field:
      //   8 bits: number of adaptation field bytes following this byte.
      //   8 bits: unused (in this program) flags.
      // This is followed by a run of 0xff to reach |kTsPayloadSize| (184)
      // bytes.
      const int pad_size = kTsPayloadSize - payload_size - 1 - 1;
      ts_buffer_[write_pos++] = pad_size + 1;
      ts_buffer_[write_pos++] = 0;

      const std::uint8_t kStuffingByte = 0xff;
      for (int i = 0; i < pad_size; ++i) {
        ts_buffer_[write_pos++] = kStuffingByte;
      }
    }

    for (int i = 0; i < payload_size; ++i) {
      ts_buffer_[write_pos++] = packet_data[read_pos++];
    }

    bytes_to_packetize -= payload_size;
    continuity_counter++;

    if (write_pos != kTsPacketSize) {
      fprintf(stderr, "VpxPes2Ts: Invalid packet length.\n");
      return false;
    }

    // Write contents of |ts_buffer_| to |output_file_|.
    // TODO(tomfinegan): Writing 188 bytes at a time isn't exactly efficient...
    // Fix me.
    if (static_cast<int>(std::fwrite(&ts_buffer_[0], 1, kTsPacketSize,
                                     output_file_.get())) != kTsPacketSize) {
      std::fprintf(stderr, "VpxPes2Ts: TS packet write failed.\n");
      return false;
    }
  }

  return true;
}

}  // namespace libwebm
<|endoftext|>