<commit_before>#include "kwm.h"
#include "helpers.h"
#include "daemon.h"
#include "display.h"
#include "space.h"
#include "window.h"
#include "keys.h"
#include "interpreter.h"
#include "scratchpad.h"
#include "border.h"
#include "config.h"
#include "command.h"
#include "cursor.h"
#include "axlib/axlib.h"

#define internal static
const std::string KwmCurrentVersion = "Kwm Version 3.0.1";
std::map<const char *, space_info> WindowTree;

ax_state AXState = {};
ax_display *FocusedDisplay = NULL;
ax_application *FocusedApplication = NULL;
ax_window *MarkedWindow = NULL;

kwm_mach KWMMach = {};
kwm_path KWMPath = {};
kwm_settings KWMSettings = {};
kwm_thread KWMThread = {};
kwm_hotkeys KWMHotkeys = {};
kwm_border FocusedBorder = {};
kwm_border MarkedBorder = {};
scratchpad Scratchpad = {};

CGEventRef CGEventCallback(CGEventTapProxy Proxy, CGEventType Type, CGEventRef Event, void *Refcon)
{
    switch(Type)
    {
        case kCGEventTapDisabledByTimeout:
        case kCGEventTapDisabledByUserInput:
        {
            if(!KWMMach.DisableEventTapInternal)
            {
                DEBUG("Restarting Event Tap");
                CGEventTapEnable(KWMMach.EventTap, true);
            }
        } break;
        case kCGEventKeyDown:
        {
            /* TODO(koekeishiya): Is there a better way to decide whether
                                  we should eat the CGEventRef or not (?) */
            if(KWMSettings.UseBuiltinHotkeys)
            {
                hotkey Eventkey = {}, *Hotkey = NULL;
                Hotkey = new hotkey;
                if(Hotkey)
                {
                    CreateHotkeyFromCGEvent(Event, &Eventkey);
                    if(HotkeyExists(Eventkey.Mod, Eventkey.Key, Hotkey, KWMHotkeys.ActiveMode->Name))
                    {
                        AXLibConstructEvent(AXEvent_HotkeyPressed, Hotkey, false);
                        if(!Hotkey->Passthrough)
                            return NULL;
                    }
                    else
                    {
                        delete Hotkey;
                    }
                }
            }
        } break;
        case kCGEventMouseMoved:
        {
            if(KWMSettings.Focus == FocusModeAutoraise)
                AXLibConstructEvent(AXEvent_MouseMoved, NULL, false);
        } break;
        default: {} break;
    }

    return Event;
}

internal bool
CheckPrivileges()
{
    bool Result = false;
    const void * Keys[] = { kAXTrustedCheckOptionPrompt };
    const void * Values[] = { kCFBooleanTrue };

    CFDictionaryRef Options;
    Options = CFDictionaryCreate(kCFAllocatorDefault,
                                 Keys, Values, sizeof(Keys) / sizeof(*Keys),
                                 &kCFCopyStringDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks);

    Result = AXIsProcessTrustedWithOptions(Options);
    CFRelease(Options);

    return Result;
}

internal bool
CheckArguments(int argc, char **argv)
{
    bool Result = false;

    if(argc == 2)
    {
        std::string Arg = argv[1];
        if(Arg == "--version")
        {
            std::cout << KwmCurrentVersion << std::endl;
            Result = true;
        }
    }

    return Result;
}

internal bool
GetKwmFilePath()
{
    bool Result = false;
    char PathBuf[PROC_PIDPATHINFO_MAXSIZE];
    pid_t Pid = getpid();
    int Ret = proc_pidpath(Pid, PathBuf, sizeof(PathBuf));
    if (Ret > 0)
    {
        KWMPath.FilePath = PathBuf;

        std::size_t Split = KWMPath.FilePath.find_last_of("/\\");
        KWMPath.FilePath = KWMPath.FilePath.substr(0, Split);
        Result = true;
    }

    return Result;
}

internal void
KwmClearSettings()
{
    KWMHotkeys.Modes.clear();
    KWMSettings.WindowRules.clear();
    KWMSettings.SpaceSettings.clear();
    KWMSettings.DisplaySettings.clear();
    KWMHotkeys.ActiveMode = GetBindingMode("default");
}

internal void
KwmExecuteConfig()
{
    char *HomeP = std::getenv("HOME");
    if(!HomeP)
    {
        DEBUG("Failed to get environment variable 'HOME'");
        return;
    }

    KWMPath.EnvHome = HomeP;
    KwmParseConfig(KWMPath.ConfigFile);
}

internal void
KwmExecuteInitScript()
{
    std::string InitFile = KWMPath.EnvHome + "/" + KWMPath.ConfigFolder + "/init";

    struct stat Buffer;
    if(stat(InitFile.c_str(), &Buffer) == 0)
        KwmExecuteThreadedSystemCommand(InitFile);
}

internal void
SignalHandler(int Signum)
{
    ShowAllScratchpadWindows();
    DEBUG("SignalHandler() " << Signum);

    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);
    exit(Signum);
}

internal void
Fatal(const std::string &Err)
{
    std::cout << Err << std::endl;
    exit(1);
}

internal void
KwmInit()
{
    if(!CheckPrivileges())
        Fatal("Error: Could not access OSX Accessibility!");

    if(KwmStartDaemon())
        pthread_create(&KWMThread.Daemon, NULL, &KwmDaemonHandleConnectionBG, NULL);
    else
        Fatal("Error: Could not start daemon!");

    /*
    signal(SIGSEGV, SignalHandler);
    signal(SIGABRT, SignalHandler);
    signal(SIGTRAP, SignalHandler);
    signal(SIGTERM, SignalHandler);
    signal(SIGKILL, SignalHandler);
    signal(SIGINT, SignalHandler);
    */

    KWMSettings.SplitRatio = 0.5;
    KWMSettings.SplitMode = SPLIT_OPTIMAL;
    KWMSettings.DefaultOffset = CreateDefaultScreenOffset();

    KWMSettings.UseBuiltinHotkeys = true;
    KWMSettings.UseMouseFollowsFocus = true;
    KWMSettings.OptimalRatio = 1.618;
    KWMSettings.LockToContainer = true;

    KWMSettings.Space = SpaceModeBSP;
    KWMSettings.Focus = FocusModeAutoraise;
    KWMSettings.Cycle = CycleModeScreen;

    FocusedBorder.Radius = -1;
    MarkedBorder.Radius = -1;

    KWMPath.ConfigFile = "kwmrc";
    KWMPath.ConfigFolder = ".kwm";
    KWMPath.BSPLayouts = "layouts";
    KWMHotkeys.ActiveMode = GetBindingMode("default");

    GetKwmFilePath();
}

void KwmQuit()
{
    ShowAllScratchpadWindows();
    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);

    exit(0);
}

void KwmReloadConfig()
{
    KwmClearSettings();
    KwmExecuteConfig();
}

int main(int argc, char **argv)
{
    if(CheckArguments(argc, argv))
        return 0;

    NSApplicationLoad();
    if(!AXLibDisplayHasSeparateSpaces())
        Fatal("Error: 'Displays have separate spaces' must be enabled!");

    /* NOTE(koekeishiya): Initialize AXLIB */
    AXLibInit(&AXState);
    AXLibStartEventLoop();

    ax_display *MainDisplay = AXLibMainDisplay();
    ax_display *Display = MainDisplay;
    do
    {
        ax_space *PrevSpace = Display->Space;
        Display->Space = AXLibGetActiveSpace(Display);
        Display->PrevSpace = PrevSpace;
        Display = AXLibNextDisplay(Display);
    } while(Display != MainDisplay);

    FocusedDisplay = MainDisplay;
    FocusedApplication = AXLibGetFocusedApplication();
    /* ----------------------------------- */

    KwmInit();
    KwmExecuteConfig();
    KwmExecuteInitScript();
    CreateWindowNodeTree(MainDisplay);

    if(CGSIsSecureEventInputSet())
        fprintf(stderr, "Secure Keyboard Entry is enabled, hotkeys will not work!\n");

    KWMMach.EventMask = ((1 << kCGEventKeyDown) |
                         (1 << kCGEventMouseMoved));

    KWMMach.EventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, KWMMach.EventMask, CGEventCallback, NULL);
    if(!KWMMach.EventTap || !CGEventTapIsEnabled(KWMMach.EventTap))
        Fatal("Error: Could not create event-tap!");

    CFRunLoopAddSource(CFRunLoopGetMain(),
                       CFMachPortCreateRunLoopSource(kCFAllocatorDefault, KWMMach.EventTap, 0),
                       kCFRunLoopCommonModes);
    CGEventTapEnable(KWMMach.EventTap, true);
    CFRunLoopRun();
    return 0;
}
<commit_msg>re-enable signalhandlers<commit_after>#include "kwm.h"
#include "helpers.h"
#include "daemon.h"
#include "display.h"
#include "space.h"
#include "window.h"
#include "keys.h"
#include "interpreter.h"
#include "scratchpad.h"
#include "border.h"
#include "config.h"
#include "command.h"
#include "cursor.h"
#include "axlib/axlib.h"

#define internal static
const std::string KwmCurrentVersion = "Kwm Version 3.0.1";
std::map<const char *, space_info> WindowTree;

ax_state AXState = {};
ax_display *FocusedDisplay = NULL;
ax_application *FocusedApplication = NULL;
ax_window *MarkedWindow = NULL;

kwm_mach KWMMach = {};
kwm_path KWMPath = {};
kwm_settings KWMSettings = {};
kwm_thread KWMThread = {};
kwm_hotkeys KWMHotkeys = {};
kwm_border FocusedBorder = {};
kwm_border MarkedBorder = {};
scratchpad Scratchpad = {};

CGEventRef CGEventCallback(CGEventTapProxy Proxy, CGEventType Type, CGEventRef Event, void *Refcon)
{
    switch(Type)
    {
        case kCGEventTapDisabledByTimeout:
        case kCGEventTapDisabledByUserInput:
        {
            if(!KWMMach.DisableEventTapInternal)
            {
                DEBUG("Restarting Event Tap");
                CGEventTapEnable(KWMMach.EventTap, true);
            }
        } break;
        case kCGEventKeyDown:
        {
            /* TODO(koekeishiya): Is there a better way to decide whether
                                  we should eat the CGEventRef or not (?) */
            if(KWMSettings.UseBuiltinHotkeys)
            {
                hotkey Eventkey = {}, *Hotkey = NULL;
                Hotkey = new hotkey;
                if(Hotkey)
                {
                    CreateHotkeyFromCGEvent(Event, &Eventkey);
                    if(HotkeyExists(Eventkey.Mod, Eventkey.Key, Hotkey, KWMHotkeys.ActiveMode->Name))
                    {
                        AXLibConstructEvent(AXEvent_HotkeyPressed, Hotkey, false);
                        if(!Hotkey->Passthrough)
                            return NULL;
                    }
                    else
                    {
                        delete Hotkey;
                    }
                }
            }
        } break;
        case kCGEventMouseMoved:
        {
            if(KWMSettings.Focus == FocusModeAutoraise)
                AXLibConstructEvent(AXEvent_MouseMoved, NULL, false);
        } break;
        default: {} break;
    }

    return Event;
}

internal bool
CheckPrivileges()
{
    bool Result = false;
    const void * Keys[] = { kAXTrustedCheckOptionPrompt };
    const void * Values[] = { kCFBooleanTrue };

    CFDictionaryRef Options;
    Options = CFDictionaryCreate(kCFAllocatorDefault,
                                 Keys, Values, sizeof(Keys) / sizeof(*Keys),
                                 &kCFCopyStringDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks);

    Result = AXIsProcessTrustedWithOptions(Options);
    CFRelease(Options);

    return Result;
}

internal bool
CheckArguments(int argc, char **argv)
{
    bool Result = false;

    if(argc == 2)
    {
        std::string Arg = argv[1];
        if(Arg == "--version")
        {
            std::cout << KwmCurrentVersion << std::endl;
            Result = true;
        }
    }

    return Result;
}

internal bool
GetKwmFilePath()
{
    bool Result = false;
    char PathBuf[PROC_PIDPATHINFO_MAXSIZE];
    pid_t Pid = getpid();
    int Ret = proc_pidpath(Pid, PathBuf, sizeof(PathBuf));
    if (Ret > 0)
    {
        KWMPath.FilePath = PathBuf;

        std::size_t Split = KWMPath.FilePath.find_last_of("/\\");
        KWMPath.FilePath = KWMPath.FilePath.substr(0, Split);
        Result = true;
    }

    return Result;
}

internal void
KwmClearSettings()
{
    KWMHotkeys.Modes.clear();
    KWMSettings.WindowRules.clear();
    KWMSettings.SpaceSettings.clear();
    KWMSettings.DisplaySettings.clear();
    KWMHotkeys.ActiveMode = GetBindingMode("default");
}

internal void
KwmExecuteConfig()
{
    char *HomeP = std::getenv("HOME");
    if(!HomeP)
    {
        DEBUG("Failed to get environment variable 'HOME'");
        return;
    }

    KWMPath.EnvHome = HomeP;
    KwmParseConfig(KWMPath.ConfigFile);
}

internal void
KwmExecuteInitScript()
{
    std::string InitFile = KWMPath.EnvHome + "/" + KWMPath.ConfigFolder + "/init";

    struct stat Buffer;
    if(stat(InitFile.c_str(), &Buffer) == 0)
        KwmExecuteThreadedSystemCommand(InitFile);
}

internal void
SignalHandler(int Signum)
{
    ShowAllScratchpadWindows();
    DEBUG("SignalHandler() " << Signum);

    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);
    exit(Signum);
}

internal void
Fatal(const std::string &Err)
{
    std::cout << Err << std::endl;
    exit(1);
}

internal void
KwmInit()
{
    if(!CheckPrivileges())
        Fatal("Error: Could not access OSX Accessibility!");

    if(KwmStartDaemon())
        pthread_create(&KWMThread.Daemon, NULL, &KwmDaemonHandleConnectionBG, NULL);
    else
        Fatal("Error: Could not start daemon!");

    signal(SIGSEGV, SignalHandler);
    signal(SIGABRT, SignalHandler);
    signal(SIGTRAP, SignalHandler);
    signal(SIGTERM, SignalHandler);
    signal(SIGKILL, SignalHandler);
    signal(SIGINT, SignalHandler);

    KWMSettings.SplitRatio = 0.5;
    KWMSettings.SplitMode = SPLIT_OPTIMAL;
    KWMSettings.DefaultOffset = CreateDefaultScreenOffset();

    KWMSettings.UseBuiltinHotkeys = true;
    KWMSettings.UseMouseFollowsFocus = true;
    KWMSettings.OptimalRatio = 1.618;
    KWMSettings.LockToContainer = true;

    KWMSettings.Space = SpaceModeBSP;
    KWMSettings.Focus = FocusModeAutoraise;
    KWMSettings.Cycle = CycleModeScreen;

    FocusedBorder.Radius = -1;
    MarkedBorder.Radius = -1;

    KWMPath.ConfigFile = "kwmrc";
    KWMPath.ConfigFolder = ".kwm";
    KWMPath.BSPLayouts = "layouts";
    KWMHotkeys.ActiveMode = GetBindingMode("default");

    GetKwmFilePath();
}

void KwmQuit()
{
    ShowAllScratchpadWindows();
    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);

    exit(0);
}

void KwmReloadConfig()
{
    KwmClearSettings();
    KwmExecuteConfig();
}

int main(int argc, char **argv)
{
    if(CheckArguments(argc, argv))
        return 0;

    NSApplicationLoad();
    if(!AXLibDisplayHasSeparateSpaces())
        Fatal("Error: 'Displays have separate spaces' must be enabled!");

    /* NOTE(koekeishiya): Initialize AXLIB */
    AXLibInit(&AXState);
    AXLibStartEventLoop();

    ax_display *MainDisplay = AXLibMainDisplay();
    ax_display *Display = MainDisplay;
    do
    {
        ax_space *PrevSpace = Display->Space;
        Display->Space = AXLibGetActiveSpace(Display);
        Display->PrevSpace = PrevSpace;
        Display = AXLibNextDisplay(Display);
    } while(Display != MainDisplay);

    FocusedDisplay = MainDisplay;
    FocusedApplication = AXLibGetFocusedApplication();
    /* ----------------------------------- */

    KwmInit();
    KwmExecuteConfig();
    KwmExecuteInitScript();
    CreateWindowNodeTree(MainDisplay);

    if(CGSIsSecureEventInputSet())
        fprintf(stderr, "Secure Keyboard Entry is enabled, hotkeys will not work!\n");

    KWMMach.EventMask = ((1 << kCGEventKeyDown) |
                         (1 << kCGEventMouseMoved));

    KWMMach.EventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, KWMMach.EventMask, CGEventCallback, NULL);
    if(!KWMMach.EventTap || !CGEventTapIsEnabled(KWMMach.EventTap))
        Fatal("Error: Could not create event-tap!");

    CFRunLoopAddSource(CFRunLoopGetMain(),
                       CFMachPortCreateRunLoopSource(kCFAllocatorDefault, KWMMach.EventTap, 0),
                       kCFRunLoopCommonModes);
    CGEventTapEnable(KWMMach.EventTap, true);
    CFRunLoopRun();
    return 0;
}
<|endoftext|>


<commit_before>#ifndef utils_hh_INCLUDED
#define utils_hh_INCLUDED

#include "exception.hh"
#include "assert.hh"

#include <memory>
#include <algorithm>
#include <vector>

namespace Kakoune
{
// *** Singleton ***
//
// Singleton helper class, every singleton type T should inherit
// from Singleton<T> to provide a consistent interface.
template<typename T>
class Singleton
{
public:
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    static T& instance()
    {
        assert (ms_instance);
        return *ms_instance;
    }

    static void delete_instance()
    {
        delete ms_instance;
        ms_instance = nullptr;
    }

protected:
    Singleton()
    {
        assert(not ms_instance);
        ms_instance = static_cast<T*>(this);
    }

    ~Singleton()
    {
        assert(ms_instance == this);
        ms_instance = nullptr;
    }

private:
    static T* ms_instance;
};

template<typename T>
T* Singleton<T>::ms_instance = nullptr;

// *** safe_ptr: objects that assert nobody references them when they die ***

template<typename T>
class safe_ptr
{
public:
    safe_ptr() : m_ptr(nullptr) {}
    explicit safe_ptr(T* ptr) : m_ptr(ptr) { if (ptr) ptr->inc_safe_count(); }
    safe_ptr(const safe_ptr& other) : safe_ptr(other.m_ptr) {}
    safe_ptr(safe_ptr&& other) : m_ptr(other.m_ptr) { other.m_ptr = nullptr; }
    ~safe_ptr() { if (m_ptr) m_ptr->dec_safe_count(); }

    safe_ptr& operator=(const safe_ptr& other)
    {
        if (m_ptr != other.m_ptr)
        {
            if (m_ptr)
                m_ptr->dec_safe_count();
            m_ptr = other.m_ptr;
            if (m_ptr)
                m_ptr->inc_safe_count();
        }
        return *this;
   }

   safe_ptr& operator=(safe_ptr&& other)
   {
       if (m_ptr != other.m_ptr)
       {
           if (m_ptr)
               m_ptr->dec_safe_count();
           m_ptr = other.m_ptr;
           other.m_ptr = nullptr;
       }
       return *this;
   }

   void reset(T* ptr)
   {
       *this = safe_ptr(ptr);
   }

   bool operator== (const safe_ptr& other) const { return m_ptr == other.m_ptr; }
   bool operator!= (const safe_ptr& other) const { return m_ptr != other.m_ptr; }
   bool operator== (T* ptr) const { return m_ptr == ptr; }
   bool operator!= (T* ptr) const { return m_ptr != ptr; }

   T& operator*  () const { return *m_ptr; }
   T* operator-> () const { return m_ptr; }

   T* get() const { return m_ptr; }

   explicit operator bool() const { return m_ptr; }

private:
   T* m_ptr;
};

class SafeCountable
{
public:
   SafeCountable() : m_count(0) {}
   ~SafeCountable() { assert(m_count == 0); }

   void inc_safe_count() const { ++m_count; }
   void dec_safe_count() const { --m_count; assert(m_count >= 0); }

private:
   mutable int m_count;
};

// *** Containers helpers ***

template<typename Container>
struct ReversedContainer
{
    ReversedContainer(Container& container) : container(container) {}
    Container& container;

    decltype(container.rbegin()) begin() { return container.rbegin(); }
    decltype(container.rend())   end()   { return container.rend(); }
};

template<typename Container>
ReversedContainer<Container> reversed(Container&& container)
{
    return ReversedContainer<Container>(container);
}

template<typename Container, typename T>
auto find(Container&& container, const T& value) -> decltype(container.begin())
{
    return std::find(container.begin(), container.end(), value);
}

template<typename Container, typename T>
auto find_if(Container&& container, T op) -> decltype(container.begin())
{
    return std::find_if(container.begin(), container.end(), op);
}

template<typename Container, typename T>
bool contains(Container&& container, const T& value)
{
    return (not container.empty()) and find(container, value) != container.end();
}

// *** On scope end ***
//
// on_scope_end provides a way to register some code to be
// executed when current scope closes.
//
// usage:
// auto cleaner = on_scope_end([]() { ... });
//
// This permits to cleanup c-style resources without implementing
// a wrapping class
template<typename T>
class OnScopeEnd
{
public:
    OnScopeEnd(T func) : m_func(func) {}
    ~OnScopeEnd() { m_func(); }
private:
    T m_func;
};

template<typename T>
OnScopeEnd<T> on_scope_end(T t)
{
    return OnScopeEnd<T>(t);
}

// *** Misc helper functions ***

template<typename T>
bool operator== (const std::unique_ptr<T>& lhs, T* rhs)
{
    return lhs.get() == rhs;
}

inline String escape(const String& name)
{
    return name.replace("([ \\t;])", R"(\\\1)");
}

template<typename T>
const T& clamp(const T& val, const T& min, const T& max)
{
    return (val < min ? min : (val > max ? max : val));
}

}

#endif // utils_hh_INCLUDED
<commit_msg>safe_ptr have no overhead when KAK_DEBUG is not defined<commit_after>#ifndef utils_hh_INCLUDED
#define utils_hh_INCLUDED

#include "exception.hh"
#include "assert.hh"

#include <memory>
#include <algorithm>
#include <vector>

namespace Kakoune
{
// *** Singleton ***
//
// Singleton helper class, every singleton type T should inherit
// from Singleton<T> to provide a consistent interface.
template<typename T>
class Singleton
{
public:
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    static T& instance()
    {
        assert (ms_instance);
        return *ms_instance;
    }

    static void delete_instance()
    {
        delete ms_instance;
        ms_instance = nullptr;
    }

protected:
    Singleton()
    {
        assert(not ms_instance);
        ms_instance = static_cast<T*>(this);
    }

    ~Singleton()
    {
        assert(ms_instance == this);
        ms_instance = nullptr;
    }

private:
    static T* ms_instance;
};

template<typename T>
T* Singleton<T>::ms_instance = nullptr;

// *** safe_ptr: objects that assert nobody references them when they die ***

template<typename T>
class safe_ptr
{
public:
    safe_ptr() : m_ptr(nullptr) {}
    explicit safe_ptr(T* ptr) : m_ptr(ptr)
    {
        #ifdef KAK_DEBUG
        if (m_ptr)
            m_ptr->inc_safe_count();
        #endif
    }
    safe_ptr(const safe_ptr& other) : safe_ptr(other.m_ptr) {}
    safe_ptr(safe_ptr&& other) : m_ptr(other.m_ptr) { other.m_ptr = nullptr; }
    ~safe_ptr()
    {
        #ifdef KAK_DEBUG
        if (m_ptr)
            m_ptr->dec_safe_count();
        #endif
    }

    safe_ptr& operator=(const safe_ptr& other)
    {
        #ifdef KAK_DEBUG
        if (m_ptr != other.m_ptr)
        {
            if (m_ptr)
                m_ptr->dec_safe_count();
            if (other.m_ptr)
                other.m_ptr->inc_safe_count();
        }
        #endif
        m_ptr = other.m_ptr;
        return *this;
   }

   safe_ptr& operator=(safe_ptr&& other)
   {
       #ifdef KAK_DEBUG
       if (m_ptr)
           m_ptr->dec_safe_count();
       #endif
       m_ptr = other.m_ptr;
       other.m_ptr = nullptr;
       return *this;
   }

   void reset(T* ptr)
   {
       *this = safe_ptr(ptr);
   }

   bool operator== (const safe_ptr& other) const { return m_ptr == other.m_ptr; }
   bool operator!= (const safe_ptr& other) const { return m_ptr != other.m_ptr; }
   bool operator== (T* ptr) const { return m_ptr == ptr; }
   bool operator!= (T* ptr) const { return m_ptr != ptr; }

   T& operator*  () const { return *m_ptr; }
   T* operator-> () const { return m_ptr; }

   T* get() const { return m_ptr; }

   explicit operator bool() const { return m_ptr; }

private:
   T* m_ptr;
};

class SafeCountable
{
public:
#ifdef KAK_DEBUG
   SafeCountable() : m_count(0) {}
   ~SafeCountable() { assert(m_count == 0); }

   void inc_safe_count() const { ++m_count; }
   void dec_safe_count() const { --m_count; assert(m_count >= 0); }

private:
   mutable int m_count;
#endif
};

// *** Containers helpers ***

template<typename Container>
struct ReversedContainer
{
    ReversedContainer(Container& container) : container(container) {}
    Container& container;

    decltype(container.rbegin()) begin() { return container.rbegin(); }
    decltype(container.rend())   end()   { return container.rend(); }
};

template<typename Container>
ReversedContainer<Container> reversed(Container&& container)
{
    return ReversedContainer<Container>(container);
}

template<typename Container, typename T>
auto find(Container&& container, const T& value) -> decltype(container.begin())
{
    return std::find(container.begin(), container.end(), value);
}

template<typename Container, typename T>
auto find_if(Container&& container, T op) -> decltype(container.begin())
{
    return std::find_if(container.begin(), container.end(), op);
}

template<typename Container, typename T>
bool contains(Container&& container, const T& value)
{
    return (not container.empty()) and find(container, value) != container.end();
}

// *** On scope end ***
//
// on_scope_end provides a way to register some code to be
// executed when current scope closes.
//
// usage:
// auto cleaner = on_scope_end([]() { ... });
//
// This permits to cleanup c-style resources without implementing
// a wrapping class
template<typename T>
class OnScopeEnd
{
public:
    OnScopeEnd(T func) : m_func(func) {}
    ~OnScopeEnd() { m_func(); }
private:
    T m_func;
};

template<typename T>
OnScopeEnd<T> on_scope_end(T t)
{
    return OnScopeEnd<T>(t);
}

// *** Misc helper functions ***

template<typename T>
bool operator== (const std::unique_ptr<T>& lhs, T* rhs)
{
    return lhs.get() == rhs;
}

inline String escape(const String& name)
{
    return name.replace("([ \\t;])", R"(\\\1)");
}

template<typename T>
const T& clamp(const T& val, const T& min, const T& max)
{
    return (val < min ? min : (val > max ? max : val));
}

}

#endif // utils_hh_INCLUDED
<|endoftext|>


<commit_before>
// Standard C++ includes
#include <stdlib.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <assert.h>
#include <float.h>
#include <math.h>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

#include </usr/local/include/mysql-connector-c++/driver/mysql_public_iface.h>
#include <time.h>

#include "hClustering.h"
#include "preProcessing.h"
#include "smallNumberClustering.h"

using namespace std;

int main(int argc, char** argv){

    string path = string(argv[0]);
    int found=path.rfind('/hCluster');
	string logFile = path;
	logFile.replace (found-7, found,"../../../../log/clustering.log");

	stringstream sql;
	int clusterN;
	int conFeatureN;
	int catFeatureN;
	int boolFeatureN;
	int range;
	int layer = 1;
	int version;
	string var;
	int keepStep = 5;

	//argument is the productName
    if (argc <5){
		cout<<" Wrong number of arguments, you need 4 (product name, region, environment and number of clusters)"<<endl;
		return EXIT_FAILURE;
	}
	string productName = argv[1];
	//cout<<productName<<endl;
	if ((productName != "camera") && (productName != "printer")){
		cout<<"Wrong Product Type! You should enter either printer or camera"<<endl;
		return EXIT_FAILURE;
	}

	string region = argv[2];
	//cout<<region<<endl;
	if ((region != "us") && (region != "ca")){
		cout<<"Wrong Region! You should enter either us or ca"<<endl;
		return EXIT_FAILURE;
	}

	string env = argv[3];
	if ((env != "test") && (env != "development") && (env != "production") && (env != "bestbuy")){
		cout<<"Wrong environment! You should either enter test, development, bestbuy or production"<<endl;
		return EXIT_FAILURE;
	}

	clusterN = atoi(argv[4]);
	if (clusterN<2 || clusterN>9){
		cout<<"your number of clusters should be between 2 and 9"<<endl;
		return EXIT_FAILURE;
	}

	string tableName = productName;
	tableName.append("s");
	map<const string, int> productNames;
	productNames["camera"] = 1;
	productNames["printer"] = 2;
	double* weights;
	map<const string, double> weightHash;
	weightHash["price"] = 1;
	//	weightHash["itemweight"] = 0;
		weightHash["opticalzoom"] = 4;
		weightHash["displaysize"] = 1;
		weightHash["maximumresolution"] = 1;
	//	weightHash["slr"] = 0;
	//	weightHash["waterproof"] = 0;
	switch(productNames[productName]){

		case 1:

					conFeatureN= 4;
					catFeatureN= 1;
					boolFeatureN= 0;
					range= 2;
					break;

		case 2:

					conFeatureN= 5;
					catFeatureN= 1;
					boolFeatureN= 2;
					weights = new double [conFeatureN + boolFeatureN];
					range= 2;
					weights[0] = 1;
					for (int f=1; f<conFeatureN-1; f++){
						weights[f] = 1;
					}
						weights[conFeatureN-1] = 1;

					    for (int f=0; f<boolFeatureN; f++){
					    	weights[conFeatureN+f] = 1;
					    }
					break;
		default:

					conFeatureN= 4;
					catFeatureN= 1;
					boolFeatureN= 0;
					range= 2;
					break;
	}

	ostringstream session_idStream;
	ostringstream layerStream;
	layerStream<<layer;

	string nodeString;
	string command, command2, nullCheck;

	string* indicatorNames = new string [conFeatureN + boolFeatureN];

	string *catFeatureNames = new string[catFeatureN];
	string *boolFeatureNames = new string [boolFeatureN];
	string *conFeatureNames = new string[conFeatureN];
	double **conFeatureRange = new double* [conFeatureN];
	double ***conFeatureRangeC = new double** [clusterN];

	catFeatureNames[0] = "brand";

	conFeatureNames[0]="listpriceint";
	conFeatureNames[1]="displaysize";
    conFeatureNames[2]="opticalzoom";
    conFeatureNames[3]="maximumresolution";
//    conFeatureNames[4]="itemweight";

	double *average = new double[conFeatureN];

  	bool *conFilteredFeatures = new bool[conFeatureN];
	bool *catFilteredFeatures = new bool[catFeatureN];
	bool *boolFilteredFeatures = new bool[boolFeatureN];

   	for(int f=0; f<conFeatureN; f++){
		conFilteredFeatures[f] = 0;
		conFeatureRange[f] = new double [range];
	}

	for (int c=0; c<clusterN; c++){
		conFeatureRangeC[c] = new double* [conFeatureN];
		for(int f=0; f<conFeatureN; f++){
			conFeatureRangeC[c][f] = new double [range];
		}
	}

	for (int f=0; f<catFeatureN; f++){
	    catFilteredFeatures[f] = 0;
	}

    for (int f=0; f<boolFeatureN; f++){
		boolFilteredFeatures[f] = 0;
	}

 string filteringCommand = preClustering(productNames, productName, conFeatureNames, catFeatureNames, boolFeatureNames, indicatorNames, region);

	nullCheck = "Select * from ";
	nullCheck += productName;
	nullCheck += "s where (instock=1 AND ((price IS NULL) ";
  for (int f=1; f<conFeatureN; f++){
  	nullCheck += "OR (";
  	nullCheck += conFeatureNames[f];
	nullCheck += " IS NULL ";
	nullCheck += ") ";
  }
  nullCheck += "))";

   sql::Statement	*stmt;

	sql::ResultSet	*res;
	sql::ResultSet	*res2;
	sql::ResultSet	*res3;
    sql::ResultSet	*resClus;
    sql::ResultSet	*resNodes;

		string line;
		string buf;
		vector<string> tokens;
		ifstream myfile;
		int i=0;
		string ymlFile = path;
		ymlFile.replace (found-7, found,"../../../../config/database.yml");

	    myfile.open(ymlFile.c_str());

	  if (myfile.is_open()){
		while (! myfile.eof()){
			getline (myfile,line);
			stringstream ss(line);
			while(ss>>buf){
				tokens.push_back(buf);
				i++;	}
		}
	    myfile.close();
       }
	   else{
			cout<<"Can't open file "<<myfile<<endl;
	   }

	env += ":";

	while (tokens.size() > 0 && tokens.at(0) != env){
		tokens.erase(tokens.begin());
	}

	string databaseString = tokens.at(findVec(tokens, "database:") + 1);
	string usernameString = tokens.at(findVec(tokens, "username:") + 1);
	string passwordString = tokens.at(findVec(tokens, "password:") + 1);
	string hostString = tokens.at(findVec(tokens, "host:") + 1);
	string databaseName = tokens.at(findVec(tokens, "database:") + 1);

	    #define PORT "3306"
		#define DB   databaseName
		#define HOST hostString
		#define USER usernameString
	    #define PASS passwordString

///////////////////////////////////////////////

			try {

				sql::Driver * driver = get_driver_instance();

			    std::auto_ptr< sql::Connection > con(driver->connect(HOST, USER, PASS));
				sql::Statement*  stmt(con->createStatement());

				command = "USE ";
				command += databaseName;

				stmt->execute(command);

				res = stmt->executeQuery(nullCheck);

			    if (res->rowsCount() >0){
			      cout<<"There are some null values in "<<productName<<"s table"<<endl;
			    }

				command = "SELECT version from ";
				command += productName;
				command += "_clusters where (region='";
				command += region;
				command += "') order by id DESC LIMIT 1";

				res = stmt->executeQuery(command);

				if (res->next()){
					version = res->getInt("version");
					version++;
				}
				else{
					version = 0;
				}
				cout<<"version is "<<version<<endl;

	   if (version > keepStep){
				///Archiving the old clusters and nodes & deleteing the old ones
				command2 = "INSERT into ";
				command2 += productName;
				command2 += "_clusters_archive select * from ";
				command2 += productName;
				command2 += "_clusters where version=";
				ostringstream vstr1;
				vstr1 << version-keepStep;
				command2 += vstr1.str();
				command2 += " and region=\'";
				command2 += region;
				command2 += "\';";
				stmt->execute(command2);

				command2 = "INSERT into ";
				command2 += productName;
				command2 += "_nodes_archive select * from ";
				command2 += productName;
				command2 += "_nodes where version=";
				ostringstream vstr2;
				vstr2 << version - keepStep;
				command2 += vstr2.str();
				command2 += " and region=\'";
				command2 += region;
				command2 += "\';";

				stmt->execute(command2);
			}

				bool clustered = 0;
			    res = stmt->executeQuery(filteringCommand);
				int maxSize = res->rowsCount();

			  time_t rawtime;
			  struct tm * timeinfo;

			  time ( &rawtime );
			  timeinfo = localtime( &rawtime );
			  ofstream myfile2;

			    myfile2.open(logFile.c_str(), ios::app);

		     	myfile2 <<endl<<timeinfo->tm_year+1900<<"-"<< timeinfo->tm_mon+1<<"-"<<timeinfo->tm_mday<<" "<< timeinfo->tm_hour<<endl;

				myfile2<<"Version: "<<version<<endl;

			   while (maxSize>clusterN){

					for (int j=0; j<conFeatureN; j++){
						average[j] = 0.0;
					}
					maxSize = hClustering(layer, clusterN,  conFeatureN,  boolFeatureN, average, conFeatureRange, conFeatureRangeC, res, res2, resClus, resNodes,
							stmt, conFeatureNames, boolFeatureNames, productName, weightHash, version, region);
					myfile2<<"layer "<<layer<<endl;
					cout<<"layer "<<layer<<endl;
					layer++;
					clustered = 1;
				}
				if (clustered){
				leafClustering(conFeatureN, boolFeatureN, clusterN, conFeatureNames, boolFeatureNames,res, res2, res3, stmt, productName, version, region);
				myfile2<<"layer "<<layer<<endl;
			}else{
					smallNumberClustering(conFeatureN, boolFeatureN, clusterN, conFeatureNames, boolFeatureNames, res, res2, stmt, productName, version, region);
					myfile2<<"layer "<<layer<<endl;
				}

//Clearing the old clusters and nodes
command2 = "DELETE from ";
command2 += productName;
command2 += "_clusters where version=";
ostringstream vstr3;
vstr3 << version-keepStep;
command2 += vstr3.str();
command2 += " and region=\'";
command2 += region;
command2 += "\';";
stmt->execute(command2);

command2 = "DELETE from ";
command2 += productName;
command2 += "_nodes where version=";
ostringstream vstr4;
vstr4 << version-keepStep;
command2 += vstr4.str();
command2 += " and region=\'";
command2 += region;
command2 += "\';";
stmt->execute(command2);

	myfile2<<"The end."<<endl;
 myfile2.close();

 	} catch (sql::SQLException &e) {

		return EXIT_FAILURE;

	}

return 1; //EXIT_SUCCESS;
}
<commit_msg>Changed clustering code to allow for flooring<commit_after>
// Standard C++ includes
#include <stdlib.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <assert.h>
#include <float.h>
#include <math.h>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

#include </usr/local/include/mysql-connector-c++/driver/mysql_public_iface.h>
#include <time.h>

#include "hClustering.h"
#include "preProcessing.h"
#include "smallNumberClustering.h"

using namespace std;

int main(int argc, char** argv){

    string path = string(argv[0]);
    int found=path.rfind('/hCluster');
	string logFile = path;
	logFile.replace (found-7, found,"../../../../log/clustering.log");

	stringstream sql;
	int clusterN;
	int conFeatureN;
	int catFeatureN;
	int boolFeatureN;
	int range;
	int layer = 1;
	int version;
	string var;
	int keepStep = 5;
   string exampleUsage = "Example: " << argv[0] << " Printer us development 9\n";

	//argument is the productName
    if (argc <5){
		cout<<" Wrong number of arguments, you need 4 (product name, region, environment and number of clusters)" << endl << exampleUsage;
		return EXIT_FAILURE;
	}
	string productName = argv[1];
	//cout<<productName<<endl;
	if (!(productName == "camera" || productName == "printer" || productName == "flooring")){
		cout<<"Unrecognized product type. Please enter 'printer', 'pamera', or 'flooring'." << endl << exampleUsage;
		return EXIT_FAILURE;
	}

	string region = argv[2];
	//cout<<region<<endl;
	if ((region != "us") && (region != "ca")){
		cout<<"Wrong Region! You should enter either us or ca" << endl << exampleUsage;
		return EXIT_FAILURE;
	}

	string env = argv[3];
	if ((env != "test") && (env != "development") && (env != "production") && (env != "bestbuy")){
		cout<<"Wrong environment! You should either enter test, development, bestbuy or production" << endl << exampleUsage;
		return EXIT_FAILURE;
	}

	clusterN = atoi(argv[4]);
	if (clusterN<2 || clusterN>9){
		cout<<"Please enter a number of clusters between 2 and 9" << endl << exampleUsage;
		return EXIT_FAILURE;
	}

	string tableName = productName;
	tableName.append("s");
	map<const string, int> productNames;
	productNames["camera"] = 1;
	productNames["printer"] = 2;
	double* weights;
	map<const string, double> weightHash;
	weightHash["price"] = 1;
	//	weightHash["itemweight"] = 0;
		weightHash["opticalzoom"] = 4;
		weightHash["displaysize"] = 1;
		weightHash["maximumresolution"] = 1;
	//	weightHash["slr"] = 0;
	//	weightHash["waterproof"] = 0;
	switch(productNames[productName]){

		case 1:

					conFeatureN= 4;
					catFeatureN= 1;
					boolFeatureN= 0;
					range= 2;
					break;

		case 2:

					conFeatureN= 5;
					catFeatureN= 1;
					boolFeatureN= 2;
					weights = new double [conFeatureN + boolFeatureN];
					range= 2;
					weights[0] = 1;
					for (int f=1; f<conFeatureN-1; f++){
						weights[f] = 1;
					}
						weights[conFeatureN-1] = 1;

					    for (int f=0; f<boolFeatureN; f++){
					    	weights[conFeatureN+f] = 1;
					    }
					break;
		default:

					conFeatureN= 4;
					catFeatureN= 1;
					boolFeatureN= 0;
					range= 2;
					break;
	}

	ostringstream session_idStream;
	ostringstream layerStream;
	layerStream<<layer;

	string nodeString;
	string command, command2, nullCheck;

	string* indicatorNames = new string [conFeatureN + boolFeatureN];

	string *catFeatureNames = new string[catFeatureN];
	string *boolFeatureNames = new string [boolFeatureN];
	string *conFeatureNames = new string[conFeatureN];
	double **conFeatureRange = new double* [conFeatureN];
	double ***conFeatureRangeC = new double** [clusterN];

	catFeatureNames[0] = "brand";

	conFeatureNames[0]="listpriceint";
	conFeatureNames[1]="displaysize";
    conFeatureNames[2]="opticalzoom";
    conFeatureNames[3]="maximumresolution";
//    conFeatureNames[4]="itemweight";

	double *average = new double[conFeatureN];

  	bool *conFilteredFeatures = new bool[conFeatureN];
	bool *catFilteredFeatures = new bool[catFeatureN];
	bool *boolFilteredFeatures = new bool[boolFeatureN];

   	for(int f=0; f<conFeatureN; f++){
		conFilteredFeatures[f] = 0;
		conFeatureRange[f] = new double [range];
	}

	for (int c=0; c<clusterN; c++){
		conFeatureRangeC[c] = new double* [conFeatureN];
		for(int f=0; f<conFeatureN; f++){
			conFeatureRangeC[c][f] = new double [range];
		}
	}

	for (int f=0; f<catFeatureN; f++){
	    catFilteredFeatures[f] = 0;
	}

    for (int f=0; f<boolFeatureN; f++){
		boolFilteredFeatures[f] = 0;
	}

 string filteringCommand = preClustering(productNames, productName, conFeatureNames, catFeatureNames, boolFeatureNames, indicatorNames, region);

	nullCheck = "Select * from ";
	nullCheck += productName;
	nullCheck += "s where (instock=1 AND ((price IS NULL) ";
  for (int f=1; f<conFeatureN; f++){
  	nullCheck += "OR (";
  	nullCheck += conFeatureNames[f];
	nullCheck += " IS NULL ";
	nullCheck += ") ";
  }
  nullCheck += "))";

   sql::Statement	*stmt;

	sql::ResultSet	*res;
	sql::ResultSet	*res2;
	sql::ResultSet	*res3;
    sql::ResultSet	*resClus;
    sql::ResultSet	*resNodes;

		string line;
		string buf;
		vector<string> tokens;
		ifstream myfile;
		int i=0;
		string ymlFile = path;
		ymlFile.replace (found-7, found,"../../../../config/database.yml");

	    myfile.open(ymlFile.c_str());

	  if (myfile.is_open()){
		while (! myfile.eof()){
			getline (myfile,line);
			stringstream ss(line);
			while(ss>>buf){
				tokens.push_back(buf);
				i++;	}
		}
	    myfile.close();
       }
	   else{
			cout<<"Can't open file "<<myfile<<endl;
	   }

	env += ":";

	while (tokens.size() > 0 && tokens.at(0) != env){
		tokens.erase(tokens.begin());
	}

	string databaseString = tokens.at(findVec(tokens, "database:") + 1);
	string usernameString = tokens.at(findVec(tokens, "username:") + 1);
	string passwordString = tokens.at(findVec(tokens, "password:") + 1);
	string hostString = tokens.at(findVec(tokens, "host:") + 1);
	string databaseName = tokens.at(findVec(tokens, "database:") + 1);

	    #define PORT "3306"
		#define DB   databaseName
		#define HOST hostString
		#define USER usernameString
	    #define PASS passwordString

///////////////////////////////////////////////

			try {

				sql::Driver * driver = get_driver_instance();

			    std::auto_ptr< sql::Connection > con(driver->connect(HOST, USER, PASS));
				sql::Statement*  stmt(con->createStatement());

				command = "USE ";
				command += databaseName;

				stmt->execute(command);

				res = stmt->executeQuery(nullCheck);

			    if (res->rowsCount() >0){
			      cout<<"There are some null values in "<<productName<<"s table"<<endl;
			    }

				command = "SELECT version from ";
				command += productName;
				command += "_clusters where (region='";
				command += region;
				command += "') order by id DESC LIMIT 1";

				res = stmt->executeQuery(command);

				if (res->next()){
					version = res->getInt("version");
					version++;
				}
				else{
					version = 0;
				}
				cout<<"version is "<<version<<endl;

	   if (version > keepStep){
				///Archiving the old clusters and nodes & deleteing the old ones
				command2 = "INSERT into ";
				command2 += productName;
				command2 += "_clusters_archive select * from ";
				command2 += productName;
				command2 += "_clusters where version=";
				ostringstream vstr1;
				vstr1 << version-keepStep;
				command2 += vstr1.str();
				command2 += " and region=\'";
				command2 += region;
				command2 += "\';";
				stmt->execute(command2);

				command2 = "INSERT into ";
				command2 += productName;
				command2 += "_nodes_archive select * from ";
				command2 += productName;
				command2 += "_nodes where version=";
				ostringstream vstr2;
				vstr2 << version - keepStep;
				command2 += vstr2.str();
				command2 += " and region=\'";
				command2 += region;
				command2 += "\';";

				stmt->execute(command2);
			}

				bool clustered = 0;
			    res = stmt->executeQuery(filteringCommand);
				int maxSize = res->rowsCount();

			  time_t rawtime;
			  struct tm * timeinfo;

			  time ( &rawtime );
			  timeinfo = localtime( &rawtime );
			  ofstream myfile2;

			    myfile2.open(logFile.c_str(), ios::app);

		     	myfile2 <<endl<<timeinfo->tm_year+1900<<"-"<< timeinfo->tm_mon+1<<"-"<<timeinfo->tm_mday<<" "<< timeinfo->tm_hour<<endl;

				myfile2<<"Version: "<<version<<endl;

			   while (maxSize>clusterN){

					for (int j=0; j<conFeatureN; j++){
						average[j] = 0.0;
					}
					maxSize = hClustering(layer, clusterN,  conFeatureN,  boolFeatureN, average, conFeatureRange, conFeatureRangeC, res, res2, resClus, resNodes,
							stmt, conFeatureNames, boolFeatureNames, productName, weightHash, version, region);
					myfile2<<"layer "<<layer<<endl;
					cout<<"layer "<<layer<<endl;
					layer++;
					clustered = 1;
				}
				if (clustered){
				leafClustering(conFeatureN, boolFeatureN, clusterN, conFeatureNames, boolFeatureNames,res, res2, res3, stmt, productName, version, region);
				myfile2<<"layer "<<layer<<endl;
			}else{
					smallNumberClustering(conFeatureN, boolFeatureN, clusterN, conFeatureNames, boolFeatureNames, res, res2, stmt, productName, version, region);
					myfile2<<"layer "<<layer<<endl;
				}

//Clearing the old clusters and nodes
command2 = "DELETE from ";
command2 += productName;
command2 += "_clusters where version=";
ostringstream vstr3;
vstr3 << version-keepStep;
command2 += vstr3.str();
command2 += " and region=\'";
command2 += region;
command2 += "\';";
stmt->execute(command2);

command2 = "DELETE from ";
command2 += productName;
command2 += "_nodes where version=";
ostringstream vstr4;
vstr4 << version-keepStep;
command2 += vstr4.str();
command2 += " and region=\'";
command2 += region;
command2 += "\';";
stmt->execute(command2);

	myfile2<<"The end."<<endl;
 myfile2.close();

 	} catch (sql::SQLException &e) {

		return EXIT_FAILURE;

	}

return 1; //EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2017 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file tunes.cpp
 */

#include "tunes.h"

#include <px4_log.h>
#include <math.h>
#include <ctype.h>

#define TUNE_ERROR -1
#define TUNE_STOP 0
#define TUNE_CONTINUE 1

#define BEAT_TIME_CONVERSION_MS (60 * 1000 * 4)
#define BEAT_TIME_CONVERSION_US BEAT_TIME_CONVERSION_MS * 1000
#define BEAT_TIME_CONVERSION BEAT_TIME_CONVERSION_US

// semitone offsets from C for the characters 'A'-'G'
const uint8_t Tunes::_note_tab[] = {9, 11, 0, 2, 4, 5, 7};

Tunes::Tunes(unsigned default_tempo, unsigned default_octave, unsigned default_note_length,
	     NoteMode default_mode):
	_default_tempo(default_tempo),
	_default_note_length(default_note_length),
	_default_mode(default_mode),
	_default_octave(default_octave)
{
	config_tone();
}

Tunes::Tunes(): Tunes(120, 4, 4, NoteMode::NORMAL)
{
}

void Tunes::config_tone()
{
	// reset pointer
	_tune = nullptr;
	_next = nullptr;
	// reset music parameter
	_tempo = _default_tempo;
	_note_length = _default_note_length;
	_note_mode = _default_mode;
	_octave = _default_octave;
}

int Tunes::set_control(const tune_control_s &tune_control)
{
	bool reset_playing_tune = false;

	if (tune_control.tune_id < _default_tunes_size) {
		switch (tune_control.tune_id) {
		case tune_control_s::TUNE_ID_CUSTOM:
			_frequency = (unsigned)tune_control.frequency;
			_duration = (unsigned)tune_control.duration;
			_using_custom_msg = true;
			break;

		case tune_control_s::TUNE_ID_STARTUP:
		case tune_control_s::TUNE_ID_ERROR:
		case tune_control_s::TUNE_ID_NOTIFY_POSITIVE:
		case tune_control_s::TUNE_ID_NOTIFY_NEUTRAL:
		case tune_control_s::TUNE_ID_NOTIFY_NEGATIVE:
			reset_playing_tune = true;
			config_tone();

		case tune_control_s::TUNE_ID_ARMING_WARNING:
		case tune_control_s::TUNE_ID_BATTERY_WARNING_SLOW:
		case tune_control_s::TUNE_ID_BATTERY_WARNING_FAST:
		case tune_control_s::TUNE_ID_GPS_WARNING:
		case tune_control_s::TUNE_ID_PARACHUTE_RELEASE:
		case tune_control_s::TUNE_ID_EKF_WARNING:
		case tune_control_s::TUNE_ID_BARO_WARNING:
		case tune_control_s::TUNE_ID_SINGLE_BEEP:
		case tune_control_s::TUNE_ID_HOME_SET:
		default:

			// TODO: come up with a better strategy
			if (_tune == nullptr || reset_playing_tune || tune_control.tune_override) {
				_tune = _default_tunes[tune_control.tune_id];
				_next = _tune;
			}

			break;
		}

	} else {
		PX4_WARN("Tune ID not recognized.");
		return -EINVAL;
	}

	return OK;
}

void Tunes::set_string(const char *string)
{
	// set tune string the first time
	if (_tune == nullptr) {
		_tune = string;
		_next = _tune;
	}
}

int Tunes::get_next_tune(unsigned &frequency, unsigned &duration, unsigned &silence)
{
	// Return the vaules for frequency and duration if the custom msg was received
	if (_using_custom_msg) {
		_using_custom_msg = false;
		frequency = _frequency;
		duration = _duration;
		silence = 0;
		return TUNE_STOP;
	}

	// make sure we still have a tune
	if ((_next == nullptr) || (_tune == nullptr)) {
		return TUNE_ERROR;
	}

	// parse characters out of the string until we have resolved a note
	unsigned note = 0;
	unsigned note_length = _note_length;

	while (note == 0) {
		// we always need at least one character from the string
		int c = next_char();

		if (c == 0) {
			goto tune_end;
		}

		_next++;

		switch (c) {
		case 'L':	// select note length
			_note_length = next_number();

			if (_note_length < 1) {
				goto tune_error;
			}

			break;

		case 'O':	// select octave
			_octave = next_number();

			if (_octave > 6) {
				_octave = 6;
			}

			break;

		case '<':	// decrease octave
			if (_octave > 0) {
				_octave--;
			}

			break;

		case '>':	// increase octave
			if (_octave < 6) {
				_octave++;
			}

			break;

		case 'M':	// select inter-note gap
			c = next_char();

			if (c == 0) {
				goto tune_error;
			}

			_next++;

			switch (c) {
			case 'N':
				_note_mode = NoteMode::NORMAL;
				break;

			case 'L':
				_note_mode = NoteMode::LEGATO;
				break;

			case 'S':
				_note_mode = NoteMode::STACCATO;
				break;

			case 'F':
				_repeat = false;
				break;

			case 'B':
				_repeat = true;
				break;

			default:
				goto tune_error;
			}

			break;

		case 'P':	// pause for a note length
			frequency = 0;
			duration = 0;
			silence = rest_duration(next_number(), next_dots());
			return TUNE_CONTINUE;

		case 'T': {	// change tempo
				unsigned nt = next_number();

				if ((nt >= 32) && (nt <= 255)) {
					_tempo = nt;

				} else {
					goto tune_error;
				}

				break;
			}

		case 'N':	// play an arbitrary note
			note = next_number();

			if (note > 84) {
				goto tune_error;
			}

			if (note == 0) {
				// this is a rest - pause for the current note length
				silence = rest_duration(_note_length, next_dots());
				return TUNE_CONTINUE;
			}

			break;

		case 'A'...'G':	// play a note in the current octave
			note = _note_tab[c - 'A'] + (_octave * 12) + 1;
			c = next_char();

			switch (c) {
			case '#':	// up a semitone
			case '+':
				if (note < 84) {
					note++;
				}

				_next++;
				break;

			case '-':	// down a semitone
				if (note > 1) {
					note--;
				}

				_next++;
				break;

			default:
				// 0 / no next char here is OK
				break;
			}

			// shorthand length notation
			note_length = next_number();

			if (note_length == 0) {
				note_length = _note_length;
			}

			break;

		default:
			goto tune_error;
		}
	}

	// compute the duration of the note and the following silence (if any)
	duration = note_duration(silence, note_length, next_dots());

	// compute the note frequency
	frequency = note_to_frequency(note);

	return TUNE_CONTINUE;

	// tune looks bad (unexpected EOF, bad character, etc.)
tune_error:
	// syslog(LOG_ERR, "tune error\n");
	_repeat = false;		// don't loop on error
	config_tone();
	return TUNE_ERROR;
	// stop (and potentially restart) the tune
tune_end:
	// restore intial parameter
	config_tone();

	if (_repeat) {
		return TUNE_CONTINUE;

	} else {
		return TUNE_STOP;
	}
}

unsigned Tunes::note_to_frequency(unsigned note)
{
	// compute the frequency (Hz)
	return (unsigned)(880.0f * powf(2.0f, ((int)note - 46) / 12.0f));
}

unsigned Tunes::note_duration(unsigned &silence, unsigned note_length, unsigned dots)
{
	unsigned whole_note_period = BEAT_TIME_CONVERSION / _tempo;

	if (note_length == 0) {
		note_length = 1;
	}

	unsigned note_period = whole_note_period / note_length;

	switch (_note_mode) {
	case NoteMode::NORMAL:
		silence = note_period / 8;
		break;

	case NoteMode::STACCATO:
		silence = note_period / 4;
		break;

	case NoteMode::LEGATO:
	default:
		silence = 0;
		break;
	}

	note_period -= silence;

	unsigned dot_extension = note_period / 2;

	while (dots--) {
		note_period += dot_extension;
		dot_extension /= 2;
	}

	return note_period;
}

unsigned Tunes::rest_duration(unsigned rest_length, unsigned dots)
{
	unsigned whole_note_period = BEAT_TIME_CONVERSION / _tempo;

	if (rest_length == 0) {
		rest_length = 1;
	}

	unsigned rest_period = whole_note_period / rest_length;

	unsigned dot_extension = rest_period / 2;

	while (dots--) {
		rest_period += dot_extension;
		dot_extension /= 2;
	}

	return rest_period;
}

int Tunes::next_char()
{
	while (isspace(*_next)) {
		_next++;
	}

	return toupper(*_next);
}

unsigned Tunes::next_number()
{
	unsigned number = 0;
	int c;

	for (;;) {
		c = next_char();

		if (!isdigit(c)) {
			return number;
		}

		_next++;
		number = (number * 10) + (c - '0');
	}
}

unsigned Tunes::next_dots()
{
	unsigned dots = 0;

	while (next_char() == '.') {
		_next++;
		dots++;
	}

	return dots;
}
<commit_msg>tunes: add pointer to the beginning of a tune to allow tune replay<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2017 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file tunes.cpp
 */

#include "tunes.h"

#include <px4_log.h>
#include <math.h>
#include <ctype.h>

#define TUNE_ERROR -1
#define TUNE_STOP 0
#define TUNE_CONTINUE 1

#define BEAT_TIME_CONVERSION_MS (60 * 1000 * 4)
#define BEAT_TIME_CONVERSION_US BEAT_TIME_CONVERSION_MS * 1000
#define BEAT_TIME_CONVERSION BEAT_TIME_CONVERSION_US

// semitone offsets from C for the characters 'A'-'G'
const uint8_t Tunes::_note_tab[] = {9, 11, 0, 2, 4, 5, 7};

Tunes::Tunes(unsigned default_tempo, unsigned default_octave, unsigned default_note_length,
	     NoteMode default_mode):
	_default_tempo(default_tempo),
	_default_note_length(default_note_length),
	_default_mode(default_mode),
	_default_octave(default_octave)
{
	config_tone(false);
}

Tunes::Tunes(): Tunes(120, 4, 4, NoteMode::NORMAL)
{
}

void Tunes::config_tone(bool repeat_flag)
{
	// reset pointer
	if (!repeat_flag)	{
		_tune = nullptr;
		_next = nullptr;

	} else {
		_tune = _start_tune;
		_next = _tune;
	}

	// reset music parameter
	_tempo = _default_tempo;
	_note_length = _default_note_length;
	_note_mode = _default_mode;
	_octave = _default_octave;
}

int Tunes::set_control(const tune_control_s &tune_control)
{
	bool reset_playing_tune = false;

	if (tune_control.tune_id < _default_tunes_size) {
		switch (tune_control.tune_id) {
		case tune_control_s::TUNE_ID_CUSTOM:
			_frequency = (unsigned)tune_control.frequency;
			_duration = (unsigned)tune_control.duration;
			_using_custom_msg = true;
			break;

		case tune_control_s::TUNE_ID_STARTUP:
		case tune_control_s::TUNE_ID_ERROR:
		case tune_control_s::TUNE_ID_NOTIFY_POSITIVE:
		case tune_control_s::TUNE_ID_NOTIFY_NEUTRAL:
		case tune_control_s::TUNE_ID_NOTIFY_NEGATIVE:
			reset_playing_tune = true;
			config_tone(false);

		case tune_control_s::TUNE_ID_ARMING_WARNING:
		case tune_control_s::TUNE_ID_BATTERY_WARNING_SLOW:
		case tune_control_s::TUNE_ID_BATTERY_WARNING_FAST:
		case tune_control_s::TUNE_ID_GPS_WARNING:
		case tune_control_s::TUNE_ID_PARACHUTE_RELEASE:
		case tune_control_s::TUNE_ID_EKF_WARNING:
		case tune_control_s::TUNE_ID_BARO_WARNING:
		case tune_control_s::TUNE_ID_SINGLE_BEEP:
		case tune_control_s::TUNE_ID_HOME_SET:
		default:

			// TODO: come up with a better strategy
			if (_tune == nullptr || reset_playing_tune || tune_control.tune_override) {
				_tune = _default_tunes[tune_control.tune_id];
				_start_tune = _default_tunes[tune_control.tune_id];
				_next = _tune;
			}

			break;
		}

	} else {
		PX4_WARN("Tune ID not recognized.");
		return -EINVAL;
	}

	return OK;
}

void Tunes::set_string(const char *string)
{
	// set tune string the first time
	if (_tune == nullptr) {
		_tune = string;
		_start_tune = string;
		_next = _tune;
	}
}

int Tunes::get_next_tune(unsigned &frequency, unsigned &duration, unsigned &silence)
{
	// Return the vaules for frequency and duration if the custom msg was received
	if (_using_custom_msg) {
		_using_custom_msg = false;
		frequency = _frequency;
		duration = _duration;
		silence = 0;
		return TUNE_STOP;
	}

	// make sure we still have a tune
	if ((_next == nullptr) || (_tune == nullptr)) {
		return TUNE_ERROR;
	}

	// parse characters out of the string until we have resolved a note
	unsigned note = 0;
	unsigned note_length = _note_length;

	while (note == 0) {
		// we always need at least one character from the string
		int c = next_char();

		if (c == 0) {
			goto tune_end;
		}

		_next++;

		switch (c) {
		case 'L':	// select note length
			_note_length = next_number();

			if (_note_length < 1) {
				goto tune_error;
			}

			break;

		case 'O':	// select octave
			_octave = next_number();

			if (_octave > 6) {
				_octave = 6;
			}

			break;

		case '<':	// decrease octave
			if (_octave > 0) {
				_octave--;
			}

			break;

		case '>':	// increase octave
			if (_octave < 6) {
				_octave++;
			}

			break;

		case 'M':	// select inter-note gap
			c = next_char();

			if (c == 0) {
				goto tune_error;
			}

			_next++;

			switch (c) {
			case 'N':
				_note_mode = NoteMode::NORMAL;
				break;

			case 'L':
				_note_mode = NoteMode::LEGATO;
				break;

			case 'S':
				_note_mode = NoteMode::STACCATO;
				break;

			case 'F':
				_repeat = false;
				break;

			case 'B':
				_repeat = true;
				break;

			default:
				goto tune_error;
			}

			break;

		case 'P':	// pause for a note length
			frequency = 0;
			duration = 0;
			silence = rest_duration(next_number(), next_dots());
			return TUNE_CONTINUE;

		case 'T': {	// change tempo
				unsigned nt = next_number();

				if ((nt >= 32) && (nt <= 255)) {
					_tempo = nt;

				} else {
					goto tune_error;
				}

				break;
			}

		case 'N':	// play an arbitrary note
			note = next_number();

			if (note > 84) {
				goto tune_error;
			}

			if (note == 0) {
				// this is a rest - pause for the current note length
				silence = rest_duration(_note_length, next_dots());
				return TUNE_CONTINUE;
			}

			break;

		case 'A'...'G':	// play a note in the current octave
			note = _note_tab[c - 'A'] + (_octave * 12) + 1;
			c = next_char();

			switch (c) {
			case '#':	// up a semitone
			case '+':
				if (note < 84) {
					note++;
				}

				_next++;
				break;

			case '-':	// down a semitone
				if (note > 1) {
					note--;
				}

				_next++;
				break;

			default:
				// 0 / no next char here is OK
				break;
			}

			// shorthand length notation
			note_length = next_number();

			if (note_length == 0) {
				note_length = _note_length;
			}

			break;

		default:
			goto tune_error;
		}
	}

	// compute the duration of the note and the following silence (if any)
	duration = note_duration(silence, note_length, next_dots());

	// compute the note frequency
	frequency = note_to_frequency(note);

	return TUNE_CONTINUE;

	// tune looks bad (unexpected EOF, bad character, etc.)
tune_error:
	// syslog(LOG_ERR, "tune error\n");
	_repeat = false;		// don't loop on error
	config_tone(_repeat);
	return TUNE_ERROR;
	// stop (and potentially restart) the tune
tune_end:
	// restore intial parameter
	config_tone(_repeat);

	if (_repeat) {
		return TUNE_CONTINUE;

	} else {
		return TUNE_STOP;
	}
}

unsigned Tunes::note_to_frequency(unsigned note)
{
	// compute the frequency (Hz)
	return (unsigned)(880.0f * powf(2.0f, ((int)note - 46) / 12.0f));
}

unsigned Tunes::note_duration(unsigned &silence, unsigned note_length, unsigned dots)
{
	unsigned whole_note_period = BEAT_TIME_CONVERSION / _tempo;

	if (note_length == 0) {
		note_length = 1;
	}

	unsigned note_period = whole_note_period / note_length;

	switch (_note_mode) {
	case NoteMode::NORMAL:
		silence = note_period / 8;
		break;

	case NoteMode::STACCATO:
		silence = note_period / 4;
		break;

	case NoteMode::LEGATO:
	default:
		silence = 0;
		break;
	}

	note_period -= silence;

	unsigned dot_extension = note_period / 2;

	while (dots--) {
		note_period += dot_extension;
		dot_extension /= 2;
	}

	return note_period;
}

unsigned Tunes::rest_duration(unsigned rest_length, unsigned dots)
{
	unsigned whole_note_period = BEAT_TIME_CONVERSION / _tempo;

	if (rest_length == 0) {
		rest_length = 1;
	}

	unsigned rest_period = whole_note_period / rest_length;

	unsigned dot_extension = rest_period / 2;

	while (dots--) {
		rest_period += dot_extension;
		dot_extension /= 2;
	}

	return rest_period;
}

int Tunes::next_char()
{
	while (isspace(*_next)) {
		_next++;
	}

	return toupper(*_next);
}

unsigned Tunes::next_number()
{
	unsigned number = 0;
	int c;

	for (;;) {
		c = next_char();

		if (!isdigit(c)) {
			return number;
		}

		_next++;
		number = (number * 10) + (c - '0');
	}
}

unsigned Tunes::next_dots()
{
	unsigned dots = 0;

	while (next_char() == '.') {
		_next++;
		dots++;
	}

	return dots;
}
<|endoftext|>


<commit_before>#ifndef __GET_DRVS_H
#define __GET_DRVS_H

#include "eval.hh"

#include <string>
#include <map>

#include <boost/shared_ptr.hpp>

namespace nix {

struct MetaValue
{
    enum { tpNone, tpString, tpStrings, tpInt } type;
    string stringValue;
    Strings stringValues;
    int intValue;
};

typedef std::map<string, MetaValue> MetaInfo;

struct DrvInfo
{
private:
    string drvPath;
    string outPath;

    bool metaInfoRead;
    MetaInfo meta;

public:
    string name;
    string attrPath; /* path towards the derivation */
    string system;

    /* !!! make this private */
    Bindings * attrs;

    DrvInfo() : metaInfoRead(false), attrs(0) { };

    string queryDrvPath(EvalState & state) const;
    string queryOutPath(EvalState & state) const;
    MetaInfo queryMetaInfo(EvalState & state) const;
    MetaValue queryMetaInfo(EvalState & state, const string & name) const;

    void setDrvPath(const string & s)
    {
        drvPath = s;
    }

    void setOutPath(const string & s)
    {
        outPath = s;
    }

    void setMetaInfo(const MetaInfo & meta);
};

typedef list<DrvInfo> DrvInfos;

/* If value `v' denotes a derivation, store information about the
   derivation in `drv' and return true.  Otherwise, return false. */
bool getDerivation(EvalState & state, Value & v, DrvInfo & drv);

void getDerivations(EvalState & state, Value & v, const string & pathPrefix,
    Bindings & autoArgs, DrvInfos & drvs);

}

#endif /* !__GET_DRVS_H */
<commit_msg>* Sync with the trunk.<commit_after>#ifndef __GET_DRVS_H
#define __GET_DRVS_H

#include "eval.hh"

#include <string>
#include <map>

#include <boost/shared_ptr.hpp>

namespace nix {

struct MetaValue
{
    enum { tpNone, tpString, tpStrings, tpInt } type;
    string stringValue;
    Strings stringValues;
    int intValue;
};

typedef std::map<string, MetaValue> MetaInfo;

struct DrvInfo
{
private:
    string drvPath;
    string outPath;

    bool metaInfoRead;
    MetaInfo meta;

public:
    string name;
    string attrPath; /* path towards the derivation */
    string system;

    /* !!! make this private */
    Bindings * attrs;

    DrvInfo() : metaInfoRead(false), attrs(0) { };

    string queryDrvPath(EvalState & state) const;
    string queryOutPath(EvalState & state) const;
    MetaInfo queryMetaInfo(EvalState & state) const;
    MetaValue queryMetaInfo(EvalState & state, const string & name) const;

    void setDrvPath(const string & s)
    {
        drvPath = s;
    }

    void setOutPath(const string & s)
    {
        outPath = s;
    }

    void setMetaInfo(const MetaInfo & meta);
};

#if HAVE_BOEHMGC
typedef list<DrvInfo, traceable_allocator<DrvInfo> > DrvInfos;
#else
typedef list<DrvInfo> DrvInfos;
#endif

/* If value `v' denotes a derivation, store information about the
   derivation in `drv' and return true.  Otherwise, return false. */
bool getDerivation(EvalState & state, Value & v, DrvInfo & drv);

void getDerivations(EvalState & state, Value & v, const string & pathPrefix,
    Bindings & autoArgs, DrvInfos & drvs);

}

#endif /* !__GET_DRVS_H */
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <vector>

#include "libx6adc.h"
#include "constants.h"

using namespace std;

// N-wide hex output with 0x
template <unsigned int N>
std::ostream& hexn(std::ostream& out) {
  return out << "0x" << std::hex << std::setw(N) << std::setfill('0');
}

int main ()
{
  cout << "BBN X6-1000 Test Executable" << endl;

  set_logging_level(5);

  int numDevices;
  numDevices = get_num_devices();

  cout << numDevices << " X6 device" << (numDevices > 1 ? "s": "")  << " found" << endl;

  if (numDevices < 1)
  	return 0;

  char s[] = "stdout";
  set_log(s);

  cout << "Attempting to initialize libaps" << endl;

  init();

  int rc;
  rc = connect_by_ID(0);

  cout << "connect(0) returned " << rc << endl;

  cout << "Firmware revision: " << read_firmware_version(0) << endl;

  cout << "current logic temperature method 1 = " << get_logic_temperature(0, 0) << endl;
  cout << "current logic temperature method 2 = " << get_logic_temperature(0, 1) << endl;

  cout << "ADC0 stream ID: " << hexn<8> << read_register(0, 0x0800, 64) << endl;
  cout << "ADC1 stream ID: " << hexn<8> << read_register(0, 0x0800, 65) << std::dec << endl;

  cout << "current PLL frequency = " << get_sampleRate(0)/1e6 << " MHz" << endl;

  cout << "Set sample rate to 100 MHz" << endl;

  set_sampleRate(0,100e6);

  cout << "current PLL frequency = " << get_sampleRate(0)/1e6 << " MHz" << endl;

  cout << "Set sample rate back to 1000 MHz" << endl;

  set_sampleRate(0,1e9);

  cout << "current PLL frequency = " << get_sampleRate(0)/1e6 << " MHz" << endl;

  cout << "setting trigger source = EXTERNAL" << endl;

  set_trigger_source(0, EXTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "setting averager parameters to record 10 segments of 1024 samples" << endl;

  set_averager_settings(0, 1024, 10, 1, 1);

  cout << "Acquiring" << endl;

  acquire(0);

  cout << "Waiting for acquisition to complete" << endl;
  int success = wait_for_acquisition(0, 1);
  if (success == X6_OK) {
    cout << "Acquistion finished" << endl;
  } else if (success == X6_TIMEOUT) {
    cout << "Acquisition timed out" << endl;
  } else {
    cout << "Unknown error in wait_for_acquisition" << endl;
  }

  cout << "Transferring waveform ch1" << endl;
  vector<int64_t> buffer(10240);
  transfer_waveform(0, 1, buffer.data(), 1024);

  cout << "Stopping" << endl;

  stop(0);

  rc = disconnect(0);

  cout << "disconnect(0) returned " << rc << endl;

  return 0;
}<commit_msg>Update test for double transfer_waveform.<commit_after>#include <iostream>
#include <iomanip>
#include <vector>

#include "libx6adc.h"
#include "constants.h"

using namespace std;

// N-wide hex output with 0x
template <unsigned int N>
std::ostream& hexn(std::ostream& out) {
  return out << "0x" << std::hex << std::setw(N) << std::setfill('0');
}

int main ()
{
  cout << "BBN X6-1000 Test Executable" << endl;

  set_logging_level(5);

  int numDevices;
  numDevices = get_num_devices();

  cout << numDevices << " X6 device" << (numDevices > 1 ? "s": "")  << " found" << endl;

  if (numDevices < 1)
  	return 0;

  char s[] = "stdout";
  set_log(s);

  cout << "Attempting to initialize libaps" << endl;

  init();

  int rc;
  rc = connect_by_ID(0);

  cout << "connect(0) returned " << rc << endl;

  cout << "Firmware revision: " << read_firmware_version(0) << endl;

  cout << "current logic temperature method 1 = " << get_logic_temperature(0, 0) << endl;
  cout << "current logic temperature method 2 = " << get_logic_temperature(0, 1) << endl;

  cout << "ADC0 stream ID: " << hexn<8> << read_register(0, 0x0800, 64) << endl;
  cout << "ADC1 stream ID: " << hexn<8> << read_register(0, 0x0800, 65) << std::dec << endl;

  cout << "current PLL frequency = " << get_sampleRate(0)/1e6 << " MHz" << endl;

  cout << "Set sample rate to 100 MHz" << endl;

  set_sampleRate(0,100e6);

  cout << "current PLL frequency = " << get_sampleRate(0)/1e6 << " MHz" << endl;

  cout << "Set sample rate back to 1000 MHz" << endl;

  set_sampleRate(0,1e9);

  cout << "current PLL frequency = " << get_sampleRate(0)/1e6 << " MHz" << endl;

  cout << "setting trigger source = EXTERNAL" << endl;

  set_trigger_source(0, EXTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "setting averager parameters to record 10 segments of 1024 samples" << endl;

  set_averager_settings(0, 1024, 10, 1, 1);

  cout << "Acquiring" << endl;

  acquire(0);

  cout << "Waiting for acquisition to complete" << endl;
  int success = wait_for_acquisition(0, 1);
  if (success == X6_OK) {
    cout << "Acquistion finished" << endl;
  } else if (success == X6_TIMEOUT) {
    cout << "Acquisition timed out" << endl;
  } else {
    cout << "Unknown error in wait_for_acquisition" << endl;
  }

  cout << "Transferring waveform ch1" << endl;
  vector<double> buffer(10240);
  transfer_waveform(0, 0, buffer.data(), 1024);

  cout << "Stopping" << endl;

  stop(0);

  rc = disconnect(0);

  cout << "disconnect(0) returned " << rc << endl;

  return 0;
}<|endoftext|>


<commit_before>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <iostream>
#include <boost/config.hpp>
#include <fcntl.h>
#include <stdio.h>

int test_main();

extern bool tests_failure;

#include "libtorrent/assert.hpp"
#include <signal.h>

void sig_handler(int sig)
{
	char stack_text[10000];
	print_backtrace(stack_text, sizeof(stack_text), 30);
	char const* sig_name = 0;
	switch (sig)
	{
#define SIG(x) case x: sig_name = #x; break
		SIG(SIGSEGV);
		SIG(SIGBUS);
		SIG(SIGILL);
		SIG(SIGABRT);
		SIG(SIGFPE);
		SIG(SIGSYS);
#undef SIG
	};
	fprintf(stderr, "signal: %s caught:\n%s\n", sig_name, stack_text);
	exit(138);
}

int main()
{
#ifdef O_NONBLOCK
	// on darwin, stdout is set to non-blocking mode by default
	// which sometimes causes tests to fail with EAGAIN just
	// by printing logs
	int flags = fcntl(fileno(stdout), F_GETFL, 0);
	fcntl(fileno(stdout), F_SETFL, flags & ~O_NONBLOCK);
	flags = fcntl(fileno(stderr), F_GETFL, 0);
	fcntl(fileno(stderr), F_SETFL, flags & ~O_NONBLOCK);
#endif

	signal(SIGSEGV, &sig_handler);
	signal(SIGBUS, &sig_handler);
	signal(SIGILL, &sig_handler);
	signal(SIGABRT, &sig_handler);
	signal(SIGFPE, &sig_handler);
	signal(SIGSYS, &sig_handler);

#ifndef BOOST_NO_EXCEPTIONS
	try
	{
#endif
		test_main();
#ifndef BOOST_NO_EXCEPTIONS
	}
	catch (std::exception const& e)
	{
		std::cerr << "Terminated with exception: \"" << e.what() << "\"\n";
		tests_failure = true;
	}
	catch (...)
	{
		std::cerr << "Terminated with unknown exception\n";
		tests_failure = true;
	}
#endif
	fflush(stdout);
	fflush(stderr);
	return tests_failure ? 1 : 0;
}

<commit_msg>fix windows unit test build<commit_after>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <iostream>
#include <boost/config.hpp>
#include <fcntl.h>
#include <stdio.h>

int test_main();

extern bool tests_failure;

#include "libtorrent/assert.hpp"
#include <signal.h>

void sig_handler(int sig)
{
	char stack_text[10000];
	print_backtrace(stack_text, sizeof(stack_text), 30);
	char const* sig_name = 0;
	switch (sig)
	{
#define SIG(x) case x: sig_name = #x; break
		SIG(SIGSEGV);
#ifdef SIGBUS
		SIG(SIGBUS);
#endif
		SIG(SIGILL);
		SIG(SIGABRT);
		SIG(SIGFPE);
#ifdef SIGSYS
		SIG(SIGSYS);
#endif
#undef SIG
	};
	fprintf(stderr, "signal: %s caught:\n%s\n", sig_name, stack_text);
	exit(138);
}

int main()
{
#ifdef O_NONBLOCK
	// on darwin, stdout is set to non-blocking mode by default
	// which sometimes causes tests to fail with EAGAIN just
	// by printing logs
	int flags = fcntl(fileno(stdout), F_GETFL, 0);
	fcntl(fileno(stdout), F_SETFL, flags & ~O_NONBLOCK);
	flags = fcntl(fileno(stderr), F_GETFL, 0);
	fcntl(fileno(stderr), F_SETFL, flags & ~O_NONBLOCK);
#endif

	signal(SIGSEGV, &sig_handler);
#ifdef SIGBUS
	signal(SIGBUS, &sig_handler);
#endif
	signal(SIGILL, &sig_handler);
	signal(SIGABRT, &sig_handler);
	signal(SIGFPE, &sig_handler);
#ifdef SIGSYS
	signal(SIGSYS, &sig_handler);
#endif

#ifndef BOOST_NO_EXCEPTIONS
	try
	{
#endif
		test_main();
#ifndef BOOST_NO_EXCEPTIONS
	}
	catch (std::exception const& e)
	{
		std::cerr << "Terminated with exception: \"" << e.what() << "\"\n";
		tests_failure = true;
	}
	catch (...)
	{
		std::cerr << "Terminated with unknown exception\n";
		tests_failure = true;
	}
#endif
	fflush(stdout);
	fflush(stderr);
	return tests_failure ? 1 : 0;
}

<|endoftext|>


<commit_before>// force debugging asserts
#ifdef OPTIMIZE
	#warning Debugging asserts have been re-enabled for testing.
	#undef OPTIMIZE
#endif

#include "core/test_error.hpp"
#include "core/test_storage.hpp"
#include "core/test_tensor.hpp"
#include "critics/test_criticsequencer.hpp"
#include "critics/test_mse.hpp"
#include "critics/test_nll.hpp"
#include "math/test_math_base.hpp"
#include "math/test_math_blas.hpp"
#include "nn/test_batchnorm.hpp"
#include "nn/test_concat.hpp"
#include "nn/test_dropconnect.hpp"
#include "nn/test_dropout.hpp"
#include "nn/test_identity.hpp"
#include "nn/test_linear.hpp"
#include "nn/test_logistic.hpp"
#include "nn/test_logsoftmax.hpp"
#include "nn/test_lstm.hpp"
#include "nn/test_relu.hpp"
#include "nn/test_sequencer.hpp"
#include "nn/test_sequential.hpp"
#include "nn/test_sparselinear.hpp"
#include "nn/test_tanh.hpp"
#include "opt/test_adam.hpp"
#include "opt/test_nadam.hpp"
#include "opt/test_rmsprop.hpp"
#include "opt/test_sgd.hpp"
#include "serialization/test_csvserializer.hpp"
#include "serialization/test_jsonserializer.hpp"
#include "serialization/test_serialized.hpp"
#include "util/test_args.hpp"
#include "util/test_batcher.hpp"
#include "util/test_random.hpp"
using namespace nnlib;

#include <iostream>
#include <string>
#include <initializer_list>
#include <tuple>
#include <functional>
using namespace std;

#include "toy_problems/classification.hpp"
#include "toy_problems/timeseries.hpp"

#define UNIT_TEST(Prefix, Class) { string("Testing ") + Prefix + #Class, Test##Class }
#define TOY_PROBLEM(Name) { string("Running toy problem: ") + #Name, Toy##Name }

int main()
{
	int ret = 0;

	initializer_list<pair<string, function<void()>>> unit_tests = {
		UNIT_TEST("core/", Error),
		UNIT_TEST("core/", Storage),
		UNIT_TEST("core/", Tensor),
		UNIT_TEST("critics/", CriticSequencer),
		UNIT_TEST("critics/", MSE),
		UNIT_TEST("critics/", NLL),
		UNIT_TEST("math/", MathBase),
		UNIT_TEST("math/", MathBLAS),
		UNIT_TEST("nn/", BatchNorm),
		UNIT_TEST("nn/", Concat),
		UNIT_TEST("nn/", DropConnect),
		UNIT_TEST("nn/", Dropout),
		UNIT_TEST("nn/", Identity),
		UNIT_TEST("nn/", Linear),
		UNIT_TEST("nn/", Logistic),
		UNIT_TEST("nn/", LogSoftMax),
		UNIT_TEST("nn/", LSTM),
		UNIT_TEST("nn/", ReLU),
		UNIT_TEST("nn/", Sequencer),
		UNIT_TEST("nn/", Sequential),
		UNIT_TEST("nn/", SparseLinear),
		UNIT_TEST("nn/", TanH),
		UNIT_TEST("opt/", Adam),
		UNIT_TEST("opt/", Nadam),
		UNIT_TEST("opt/", RMSProp),
		UNIT_TEST("opt/", SGD),
		UNIT_TEST("serialization/", CSVSerializer),
		UNIT_TEST("serialization/", JSONSerializer),
		UNIT_TEST("serialization/", Serialized),
		UNIT_TEST("util/", Args),
		UNIT_TEST("util/", Batcher),
		UNIT_TEST("util/", Random)
	};

	initializer_list<pair<string, function<void()>>> toy_problems = {
		TOY_PROBLEM(Classification),
		TOY_PROBLEM(TimeSeries)
	};

	try
	{
		for(auto test : unit_tests)
		{
			cout << test.first << "..." << flush;
			test.second();
			cout << " Passed!" << endl;
		}

		for(auto test : toy_problems)
		{
			cout << test.first << "..." << flush;
			test.second();
			cout << " Passed!" << endl;
		}

		cout << "All tests passed!" << endl;
	}
	catch(const Error &e)
	{
		cerr << endl << "An error occurred:\n\t" << e.what() << endl;
		ret = 1;
	}
	return ret;
}
<commit_msg>Added random seed to tests.<commit_after>// force debugging asserts
#ifdef OPTIMIZE
	#warning Debugging asserts have been re-enabled for testing.
	#undef OPTIMIZE
#endif

#include "core/test_error.hpp"
#include "core/test_storage.hpp"
#include "core/test_tensor.hpp"
#include "critics/test_criticsequencer.hpp"
#include "critics/test_mse.hpp"
#include "critics/test_nll.hpp"
#include "math/test_math_base.hpp"
#include "math/test_math_blas.hpp"
#include "nn/test_batchnorm.hpp"
#include "nn/test_concat.hpp"
#include "nn/test_dropconnect.hpp"
#include "nn/test_dropout.hpp"
#include "nn/test_identity.hpp"
#include "nn/test_linear.hpp"
#include "nn/test_logistic.hpp"
#include "nn/test_logsoftmax.hpp"
#include "nn/test_lstm.hpp"
#include "nn/test_relu.hpp"
#include "nn/test_sequencer.hpp"
#include "nn/test_sequential.hpp"
#include "nn/test_sparselinear.hpp"
#include "nn/test_tanh.hpp"
#include "opt/test_adam.hpp"
#include "opt/test_nadam.hpp"
#include "opt/test_rmsprop.hpp"
#include "opt/test_sgd.hpp"
#include "serialization/test_csvserializer.hpp"
#include "serialization/test_jsonserializer.hpp"
#include "serialization/test_serialized.hpp"
#include "util/test_args.hpp"
#include "util/test_batcher.hpp"
#include "util/test_random.hpp"
using namespace nnlib;

#include <iostream>
#include <string>
#include <initializer_list>
#include <tuple>
#include <functional>
using namespace std;

#include "toy_problems/classification.hpp"
#include "toy_problems/timeseries.hpp"

#define UNIT_TEST(Prefix, Class) { string("Testing ") + Prefix + #Class, Test##Class }
#define TOY_PROBLEM(Name) { string("Running toy problem: ") + #Name, Toy##Name }

int main()
{
	RandomEngine::seed(0);

	int ret = 0;

	initializer_list<pair<string, function<void()>>> unit_tests = {
		UNIT_TEST("core/", Error),
		UNIT_TEST("core/", Storage),
		UNIT_TEST("core/", Tensor),
		UNIT_TEST("critics/", CriticSequencer),
		UNIT_TEST("critics/", MSE),
		UNIT_TEST("critics/", NLL),
		UNIT_TEST("math/", MathBase),
		UNIT_TEST("math/", MathBLAS),
		UNIT_TEST("nn/", BatchNorm),
		UNIT_TEST("nn/", Concat),
		UNIT_TEST("nn/", DropConnect),
		UNIT_TEST("nn/", Dropout),
		UNIT_TEST("nn/", Identity),
		UNIT_TEST("nn/", Linear),
		UNIT_TEST("nn/", Logistic),
		UNIT_TEST("nn/", LogSoftMax),
		UNIT_TEST("nn/", LSTM),
		UNIT_TEST("nn/", ReLU),
		UNIT_TEST("nn/", Sequencer),
		UNIT_TEST("nn/", Sequential),
		UNIT_TEST("nn/", SparseLinear),
		UNIT_TEST("nn/", TanH),
		UNIT_TEST("opt/", Adam),
		UNIT_TEST("opt/", Nadam),
		UNIT_TEST("opt/", RMSProp),
		UNIT_TEST("opt/", SGD),
		UNIT_TEST("serialization/", CSVSerializer),
		UNIT_TEST("serialization/", JSONSerializer),
		UNIT_TEST("serialization/", Serialized),
		UNIT_TEST("util/", Args),
		UNIT_TEST("util/", Batcher),
		UNIT_TEST("util/", Random)
	};

	initializer_list<pair<string, function<void()>>> toy_problems = {
		TOY_PROBLEM(Classification),
		TOY_PROBLEM(TimeSeries)
	};

	try
	{
		for(auto test : unit_tests)
		{
			cout << test.first << "..." << flush;
			test.second();
			cout << " Passed!" << endl;
		}

		for(auto test : toy_problems)
		{
			cout << test.first << "..." << flush;
			test.second();
			cout << " Passed!" << endl;
		}

		cout << "All tests passed!" << endl;
	}
	catch(const Error &e)
	{
		cerr << endl << "An error occurred:\n\t" << e.what() << endl;
		ret = 1;
	}
	return ret;
}
<|endoftext|>


<commit_before>#include <cctype>
#include <string>
#include <iostream>

#include "../include/munchar.hpp"
#include "../include/munchar_lexemes.hpp"

using namespace Munchar;
using namespace Munchar::Lexemes;

template<typename T>
void pass(const T& t, const char* input, const char* result) {
  const char* after = t(input);
  if (std::string(input, after-input) != std::string(result)) {
    throw std::string("test should have passed on ") + input + ", " + result;
  }
  std::cerr << ".";
}

template<typename T>
void fail(const T& t, const char* input) {
  const char* after = t(input);
  if (after) {
    throw std::string("test should have failed on ") + input;
  }
}

int main() {

  try {
    pass('a'_lit, "abc", "a");
    fail('a'_lit, "bcd");
    fail('a'_lit, "");

    pass("abc"_lit, "abcdefg", "abc");
    fail("abc"_lit, "bcdefgh");
    fail("abc"_lit, "ab");
    fail("abc"_lit, "");

    pass("abc"_cls, "abcdefg", "a");
    pass("abc"_cls, "bcdefgh", "b");
    pass("abc"_cls, "cdefghi", "c");
    fail("abc"_cls, "defghij");
    fail("abc"_cls, "");

    pass(MUNCHAR_STATIC_PREDICATE(::isdigit), "12345", "1");
    pass(P(::isdigit), "12345", "1");
    fail(MUNCHAR_STATIC_PREDICATE(::isdigit), "a2345");
    fail(P(::isdigit), "a2345");
    fail(MUNCHAR_STATIC_PREDICATE(::isdigit), "");
    fail(P(::isdigit), "");

    pass("foo"_lit ^ "bar"_lit, "foobarhux", "foobar");
    pass(P(::isalpha) ^ P(::isdigit), "a1 blah", "a1");
    pass("foo"_lit ^ "bar"_lit ^ "hux"_lit, "foobarhuxbaz", "foobarhux");
    fail("foo"_lit ^ "bar"_lit, "foobah");
    fail("foo"_lit ^ "bar"_lit, "foob");
    fail("foo"_lit ^ "bar"_lit, "boof");
    fail("foo"_lit ^ "bar"_lit, "");
    fail("foo"_lit ^ "bar"_lit ^ "hux"_lit, "foobar");
    fail("foo"_lit ^ "bar"_lit ^ "hux"_lit, "");
    fail(P(::isalpha) ^ P(::isdigit), "a");
    fail(P(::isalpha) ^ P(::isdigit), "1a");
    fail(P(::isalpha) ^ P(::isdigit), "");

    pass("foo"_lit | "bar"_lit, "foobarhux", "foo");
    pass("foo"_lit | "bar"_lit, "barfoohux", "bar");
    pass("foo"_lit | "bar"_lit | "hux"_lit, "huxleberry", "hux");
    pass(P(::isalpha) | P(::isdigit), "a1 blah", "a");
    pass(P(::isalpha) | P(::isdigit), "1a blah", "1");
    fail("foo"_lit | "bar"_lit, "bahfoo");
    fail("foo"_lit | "bar"_lit, "boofoo");
    fail("foo"_lit | "bar"_lit, "boof");
    fail("foo"_lit | "bar"_lit, "");
    fail("foo"_lit | "bar"_lit | "hux"_lit, "huckleberry");
    fail(P(::isalpha) | P(::isdigit), ".");
    fail(P(::isalpha) | P(::isdigit), "!");
    fail(P(::isalpha) | P(::isdigit), "");

    pass(~("foo"_lit | "bar"_lit), "barhux", "bar");
    pass(~("foo"_lit | "bar"_lit), "bludge", "");
    pass(~("foo"_lit | "bar"_lit), "", "");

    pass(*("foo"_lit | "bar"_lit), "foobarfoofoobarstop", "foobarfoofoobar");
    pass(*("foo"_lit | "bar"_lit), "f", "");
    pass(*("foo"_lit | "bar"_lit), "", "");
  }
  catch (std::string& msg) {
    std::cerr << msg << std::endl;
    return 1;
  }
  std::cerr << std::endl << "all tests passed" << std::endl;
  return 0;
}<commit_msg>more tests<commit_after>#include <cctype>
#include <string>
#include <iostream>

#include "../include/munchar.hpp"
#include "../include/munchar_lexemes.hpp"

using namespace Munchar;
using namespace Munchar::Lexemes;

size_t COUNT = 0;

template<typename T>
void pass(const T& t, const char* input, const char* result) {
  const char* after = t(input);
  if (std::string(input, after-input) != std::string(result)) {
    throw std::string("test should have passed on ") + input + ", " + result;
  }
  ++COUNT;
  std::cerr << ".";
}

template<typename T>
void fail(const T& t, const char* input) {
  const char* after = t(input);
  if (after) {
    throw std::string("test should have failed on ") + input;
  }
}

int main() {

  try {
    pass('a'_lit, "abc", "a");
    fail('a'_lit, "bcd");
    fail('a'_lit, "");

    pass("abc"_lit, "abcdefg", "abc");
    fail("abc"_lit, "bcdefgh");
    fail("abc"_lit, "ab");
    fail("abc"_lit, "");

    pass("abc"_cls, "abcdefg", "a");
    pass("abc"_cls, "bcdefgh", "b");
    pass("abc"_cls, "cdefghi", "c");
    fail("abc"_cls, "defghij");
    fail("abc"_cls, "");

    pass(MUNCHAR_STATIC_PREDICATE(::isdigit), "12345", "1");
    pass(P(::isdigit), "12345", "1");
    fail(MUNCHAR_STATIC_PREDICATE(::isdigit), "a2345");
    fail(P(::isdigit), "a2345");
    fail(MUNCHAR_STATIC_PREDICATE(::isdigit), "");
    fail(P(::isdigit), "");

    pass("foo"_lit ^ "bar"_lit, "foobarhux", "foobar");
    pass(P(::isalpha) ^ P(::isdigit), "a1 blah", "a1");
    pass("foo"_lit ^ "bar"_lit ^ "hux"_lit, "foobarhuxbaz", "foobarhux");
    fail("foo"_lit ^ "bar"_lit, "foobah");
    fail("foo"_lit ^ "bar"_lit, "foob");
    fail("foo"_lit ^ "bar"_lit, "boof");
    fail("foo"_lit ^ "bar"_lit, "");
    fail("foo"_lit ^ "bar"_lit ^ "hux"_lit, "foobar");
    fail("foo"_lit ^ "bar"_lit ^ "hux"_lit, "");
    fail(P(::isalpha) ^ P(::isdigit), "a");
    fail(P(::isalpha) ^ P(::isdigit), "1a");
    fail(P(::isalpha) ^ P(::isdigit), "");

    pass("foo"_lit | "bar"_lit, "foobarhux", "foo");
    pass("foo"_lit | "bar"_lit, "barfoohux", "bar");
    pass("foo"_lit | "bar"_lit | "hux"_lit, "huxleberry", "hux");
    pass(P(::isalpha) | P(::isdigit), "a1 blah", "a");
    pass(P(::isalpha) | P(::isdigit), "1a blah", "1");
    fail("foo"_lit | "bar"_lit, "bahfoo");
    fail("foo"_lit | "bar"_lit, "boofoo");
    fail("foo"_lit | "bar"_lit, "boof");
    fail("foo"_lit | "bar"_lit, "");
    fail("foo"_lit | "bar"_lit | "hux"_lit, "huckleberry");
    fail(P(::isalpha) | P(::isdigit), ".");
    fail(P(::isalpha) | P(::isdigit), "!");
    fail(P(::isalpha) | P(::isdigit), "");

    pass(~("foo"_lit | "bar"_lit), "barhux", "bar");
    pass(~("foo"_lit | "bar"_lit), "bludge", "");
    pass(~("foo"_lit | "bar"_lit), "", "");

    pass(*("foo"_lit | "bar"_lit), "foobarfoofoobarstop", "foobarfoofoobar");
    pass(*("foo"_lit | "bar"_lit), "f", "");
    pass(*("foo"_lit | "bar"_lit), "", "");

    pass(+("foo"_lit | "bar"_lit), "foobarfoofoobarstop", "foobarfoofoobar");
    fail(+("foo"_lit | "bar"_lit), "f");
    fail(+("foo"_lit | "bar"_lit), "");

  }
  catch (std::string& msg) {
    std::cerr << msg << std::endl;
    return 1;
  }
  std::cerr << std::endl << COUNT << " tests passed (that's all of them)" << std::endl;
  return 0;
}<|endoftext|>


<commit_before>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TEST_HPP
#define TEST_HPP

void report_failure(char const* str, char const* file, int line);

#include <boost/config.hpp>
#include <exception>
#include <sstream>

#if defined(_MSC_VER)
#define COUNTER_GUARD(x)
#else
#define COUNTER_GUARD(type) \
    struct BOOST_PP_CAT(type, _counter_guard) \
    { \
        ~BOOST_PP_CAT(type, _counter_guard()) \
        { \
            TEST_CHECK(counted_type<type>::count == 0); \
        } \
    } BOOST_PP_CAT(type, _guard)
#endif

#define TEST_REPORT_AUX(x, line, file) \
	report_failure(x, line, file)

#ifdef BOOST_NO_EXCEPTIONS
#define TEST_CHECK(x) \
	if (!(x)) \
		TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__);
#define TEST_EQUAL(x, y) \
	if (x != y) { \
		std::stringstream s__; \
		s__ << "TEST_EQUAL_ERROR: " << #x << ": " << x << " expected: " << y << std::endl; \
		TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
	}
#else
#define TEST_CHECK(x) \
	try \
	{ \
		if (!(x)) \
			TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__); \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#define TEST_EQUAL(x, y) \
	try { \
		if (x != y) { \
			std::stringstream s__; \
			s__ << "TEST_EQUAL_ERROR: " << #x << ": " << x << " expected: " << y << std::endl; \
			TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
		} \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}
#endif

#define TEST_ERROR(x) \
	TEST_REPORT_AUX((std::string("ERROR: \"") + x + "\"").c_str(), __FILE__, __LINE__)

#define TEST_NOTHROW(x) \
	try \
	{ \
		x; \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#endif // TEST_HPP

<commit_msg>test update<commit_after>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TEST_HPP
#define TEST_HPP

void report_failure(char const* str, char const* file, int line);

#include <boost/config.hpp>
#include <exception>
#include <sstream>

#if defined(_MSC_VER)
#define COUNTER_GUARD(x)
#else
#define COUNTER_GUARD(type) \
    struct BOOST_PP_CAT(type, _counter_guard) \
    { \
        ~BOOST_PP_CAT(type, _counter_guard()) \
        { \
            TEST_CHECK(counted_type<type>::count == 0); \
        } \
    } BOOST_PP_CAT(type, _guard)
#endif

#define TEST_REPORT_AUX(x, line, file) \
	report_failure(x, line, file)

#ifdef BOOST_NO_EXCEPTIONS
#define TEST_CHECK(x) \
	if (!(x)) \
		TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__);
#define TEST_EQUAL(x, y) \
	if (x != y) { \
		std::stringstream s__; \
		s__ << "TEST_EQUAL_ERROR: " #x ": " << x << " expected: " << y << std::endl; \
		TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
	}
#else
#define TEST_CHECK(x) \
	try \
	{ \
		if (!(x)) \
			TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__); \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#define TEST_EQUAL(x, y) \
	try { \
		if (x != y) { \
			std::stringstream s__; \
			s__ << "TEST_EQUAL_ERROR: " #x ": " << x << " expected: " << y << std::endl; \
			TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
		} \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}
#endif

#define TEST_ERROR(x) \
	TEST_REPORT_AUX((std::string("ERROR: \"") + x + "\"").c_str(), __FILE__, __LINE__)

#define TEST_NOTHROW(x) \
	try \
	{ \
		x; \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#endif // TEST_HPP

<|endoftext|>