<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sqlparserclient.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 05:13:37 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

#ifndef SVX_SQLPARSERCLIENT_HXX
#include "sqlparserclient.hxx"
#endif
#include "ParseContext.hxx"

//........................................................................
namespace svxform
{
//........................................................................

    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::lang;

    //====================================================================
    //= OSQLParserClient
    //====================================================================
    //--------------------------------------------------------------------
    OSQLParserClient::OSQLParserClient(const Reference< XMultiServiceFactory >& _rxORB)
    {
        m_xORB = _rxORB;
    }
    //--------------------------------------------------------------------
    //add by BerryJia for fixing Bug97420 Time:2002-9-12-11:00(PRC time)
    void OSQLParserClient::create() const
    {
        if (!getFactory().is())
            ODbtoolsClient::create();
        if (getFactory().is())
             m_xParser = getFactory()->createSQLParser(m_xORB,getParseContext());
    }

//........................................................................
}   // namespace svxform
//........................................................................

<commit_msg>INTEGRATION: CWS dba24b (1.6.480); FILE MERGED 2007/09/04 21:44:21 fs 1.6.480.1: during #i73237#: slight refactoring<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sqlparserclient.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-01 14:59:17 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

#ifndef SVX_SQLPARSERCLIENT_HXX
#include "sqlparserclient.hxx"
#endif
#include "ParseContext.hxx"

//........................................................................
namespace svxform
{
//........................................................................

    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::lang;

    //====================================================================
    //= OSQLParserClient
    //====================================================================
    //--------------------------------------------------------------------
    OSQLParserClient::OSQLParserClient(const Reference< XMultiServiceFactory >& _rxORB)
    {
        m_xORB = _rxORB;
    }
    //--------------------------------------------------------------------
    bool OSQLParserClient::ensureLoaded() const
    {
        if ( !ODbtoolsClient::ensureLoaded() )
            return false;
         m_xParser = getFactory()->createSQLParser(m_xORB,getParseContext());
        return m_xParser.is();
    }

//........................................................................
}   // namespace svxform
//........................................................................

<|endoftext|>


<commit_before>/*
   Copyright 2013-2014 Daniele Di Sarli

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <pthread.h>
#include <syslog.h>
#include <errno.h>
#include "comsock.h"
#include "client.h"
#include <errno.h>
#include <err.h>
#include <bsd/libutil.h>

using namespace std;

void logServerExit(int __status, int __pri, const char *fmt...);
void startDaemon();
void enableALS(bool enable);
void *IPCHandler(void *arg);
void *clientHandler(void *arg);
char* acpi_call(string data);
int getLidStatus();

volatile bool active = false;

int g_socket = -1;

const string SOCKET_PATH = "/var/run/als-controller.socket";
char* C_SOCKET_PATH = (char*)SOCKET_PATH.c_str();

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t start = PTHREAD_COND_INITIALIZER;

/** Signal mask */
static sigset_t g_sigset;

/*void sigHandler(int sig)
{
    if(sig == SIGUSR1) {
        ..
    }
}*/

void *sigManager(void *arg) {
  int signum;

  while(1) {
    sigwait(&g_sigset, &signum);

    if(signum == SIGINT || signum == SIGTERM) {
        logServerExit(EXIT_SUCCESS, LOG_INFO, "Terminated.");
    }
  }

  return NULL;
}

void logServerExit(int __status, int __pri, const char *fmt...) {
    closeServerChannel(C_SOCKET_PATH, g_socket);
    enableALS(false);
    syslog(__pri, fmt);
    if(__status != EXIT_SUCCESS)
        syslog(LOG_INFO, "Terminated.");
    closelog();
    exit(__status);
}

char* acpi_call(string data) {
    int fd = open("/proc/acpi/call", O_RDWR);
    if(fd == -1) {
        logServerExit(EXIT_FAILURE, LOG_CRIT, "Error opening /proc/acpi/call");
    }
    if(write(fd, data.c_str(), data.length() + 1) == -1) {
        syslog(LOG_ERR, "Error writing to /proc/acpi/call");
        return NULL;
    }

    int buf_size = 100;
    char* buf = (char*)calloc(buf_size, sizeof(char));
    int nread = read(fd, buf, buf_size-1);
    if(nread == -1) {
        syslog(LOG_ERR, "Error reading from /proc/acpi/call");
        return NULL;
    }

    close(fd);

    //syslog(LOG_DEBUG, buf);
    return buf;
}

void enableALS(bool enable) {
    if(enable) {
        acpi_call("\\_SB.ATKD.ALSC 0x1");
        acpi_call("\\_SB.PCI0.LPCB.EC0.TALS 0x1");
    } else {
        acpi_call("\\_SB.PCI0.LPCB.EC0.TALS 0x0");
    }

    if (enable)
        syslog(LOG_INFO, "ALS enabled");
    else
        syslog(LOG_INFO, "ALS disabled");
}

void setScreenBacklight(int percent) {
    int ret = 0;
    char cmd[100];
    snprintf(cmd, 100, "xbacklight -set %d", percent);
    ret = system(cmd);
    if (ret < 0) {
        syslog(LOG_ERR, "Failed to set screen backlight.");
    }
}

void setKeyboardBacklight(int percent) {
    int value = 0;
    int ret = 0;
    if(percent <= 25) value = 0;
    else if(percent <= 50) value = 1;
    else if(percent <= 75) value = 2;
    else if(percent <= 100) value = 3;

    char cmd[150];
    snprintf(cmd, 150, "echo %d | tee /sys/class/leds/asus::kbd_backlight/brightness", value);
    ret = system(cmd);
    if (ret < 0) {
        syslog(LOG_ERR, "Failed to set keyboard backlight.");
    }
}

/**
 * @brief getLidStatus
 * @return 1 if opened, 0 if closed, -1 on error, -2 if unknown
 */
int getLidStatus() {
    int fd = open("/proc/acpi/button/lid/LID/state", O_RDONLY);
    if(fd == -1) {
        syslog(LOG_ERR, "Error opening /sys/bus/acpi/devices/ACPI0008:00/ali");
        return -1;
    } else {
        char str[100];
        int count = read(fd, str, 100);
        str[count] = '\0';
        close(fd);
        string s = string(str);
        if(s.find("open") != string::npos) {
            return 1;
        } else if(s.find("closed") != string::npos) {
            return 0;
        } else {
            return -2;
        }
    }
}

int getAmbientLightPercent() {
    int fd = open("/sys/bus/acpi/devices/ACPI0008:00/ali", O_RDONLY);
    if(fd == -1) {
        logServerExit(EXIT_FAILURE, LOG_CRIT, "Error opening /sys/bus/acpi/devices/ACPI0008:00/ali");
    }
    char strals[100];
    int count = read(fd, strals, 100);
    strals[count] = '\0';
    close(fd);

    // 0x32 (min illuminance), 0xC8, 0x190, 0x258, 0x320 (max illuminance).
    int als = atoi(strals);
    //printf("\"%s\"\n", strals);
    //printf("Illuminance detected: %d\n", als);

    float percent = 0;

    switch(als) {
    case 0x32:
        percent = 10;
        break;
    case 0xC8:
        percent = 25;
        break;
    case 0x190:
        percent = 50;
        break;
    case 0x258:
        percent = 75;
        break;
    case 0x320:
        percent = 100;
        break;
    }

    return percent;
}

int main(int argc, char *argv[])
{
    /*struct sigaction sa;
    sa.sa_handler = sigHandler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGUSR1, &sa, NULL);*/

    if(argc > 1) {
        Client c = Client(argc, argv, SOCKET_PATH);
        c.Run();
        exit(EXIT_SUCCESS);
    }

    struct pidfh *pfh;
    pid_t otherpid;
    pfh = pidfile_open("/var/run/als-controller.pid", 0600, &otherpid);
    if (pfh == NULL) {
        if (errno == EEXIST) {
                    errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
                        (intmax_t)otherpid);
        }
        /* If we cannot create pidfile from other reasons, only warn. */
        warn("Cannot open or create pidfile");
    }

    if (daemon(0, 0) == -1) {
        warn("Cannot daemonize");
        pidfile_remove(pfh);
        exit(EXIT_FAILURE);
    }

    pidfile_write(pfh);

    /* Change the file mode mask */
    umask(0);

    /* Open the log file */
    openlog("als-controller", LOG_PID, LOG_DAEMON);

    startDaemon();
    pidfile_remove(pfh);
    return 0;
}

void startDaemon()
{
    syslog(LOG_NOTICE, "Started.");

    /* Maschera i signal handler. La maschera viene ereditata dai thread successivi
     * (quindi questi segnali verranno bloccati in tutti i thread).
     * In particolare, il thread "sigthread" si occuperà di gestire tutti i segnali
     * che qui stiamo bloccando. */
    sigemptyset(&g_sigset);
    sigaddset(&g_sigset, SIGINT);
    sigaddset(&g_sigset, SIGTERM);
    if(pthread_sigmask(SIG_SETMASK, &g_sigset, NULL) != 0) {
        logServerExit(EXIT_FAILURE, LOG_CRIT, "Sigmask error.");
    }

    pthread_t sigthread;
    if(pthread_create(&sigthread, NULL, sigManager, NULL) != 0) {
        logServerExit(EXIT_FAILURE, LOG_CRIT, "Creating thread.");
    }

    pthread_t thread_id;
    int err = pthread_create(&thread_id, NULL, IPCHandler, NULL);
    if(err != 0) {
        syslog(LOG_CRIT, "Cannot create thread");
        exit(EXIT_FAILURE);
    }

    while(1) {

        pthread_mutex_lock(&mtx);
        while(!active) {
            pthread_cond_wait(&start, &mtx);
        }
        pthread_mutex_unlock(&mtx);

        if(getLidStatus() == 0) {
            setKeyboardBacklight(0);
        } else {

            float als = getAmbientLightPercent();
            //printf("Illuminance percent: %f\n", als);

            if(als <= 10) {
                setScreenBacklight(40);
                setKeyboardBacklight(100);
            } else if(als <= 25) {
                setScreenBacklight(60);
                setKeyboardBacklight(0);
            } else if(als <= 50) {
                setScreenBacklight(75);
                setKeyboardBacklight(0);
            } else if(als <= 75) {
                setScreenBacklight(90);
                setKeyboardBacklight(0);
            } else if(als <= 100) {
                setScreenBacklight(100);
                setKeyboardBacklight(0);
            }
        }

        sleep(3);
    }

    logServerExit(EXIT_SUCCESS, LOG_NOTICE, "Terminated.");
}

void *IPCHandler(void *arg)
{
    unlink(C_SOCKET_PATH);
    g_socket = createServerChannel(C_SOCKET_PATH);
    if(g_socket == -1) {
      logServerExit(EXIT_FAILURE, LOG_CRIT, "Error creating socket");
    }

    // Permessi 777 sulla socket
    if(chmod(C_SOCKET_PATH, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0) {
      closeServerChannel(C_SOCKET_PATH, g_socket);
      return NULL;
    }

    while(1)
    {
        int client = acceptConnection(g_socket);
        if(client == -1) {
            syslog(LOG_ERR, "Error accepting client connection.");
        } else {
            pthread_t thread_id;
            int err = pthread_create(&thread_id, NULL, clientHandler, (void *)(size_t)client);
            if(err != 0) {
                logServerExit(EXIT_FAILURE, LOG_CRIT, "Error creating client thread.");
            }
        }
    }
}

void *clientHandler(void *arg)
{
    int client = (int)(size_t)arg;
    message_t msg;

    if(receiveMessage(client, &msg) == -1) {
        syslog(LOG_ERR, "Error receiving message from client.");
        return NULL;
    }

    if(msg.type == MSG_ENABLE) {
        enableALS(true);
        pthread_mutex_lock(&mtx);
        active = true;
        pthread_mutex_unlock(&mtx);
        pthread_cond_signal(&start);
    } else if(msg.type == MSG_DISABLE) {
        pthread_mutex_lock(&mtx);
        active = false;
        pthread_mutex_unlock(&mtx);
        enableALS(false);
    } else if(msg.type == MSG_STATUS) {
        bool status = false;
        pthread_mutex_lock(&mtx);
        status = active;
        pthread_mutex_unlock(&mtx);

        int sent;
        message_t msg;

        msg.type = status ? MSG_ENABLED : MSG_DISABLED;
        msg.buffer = NULL;
        msg.length = 0;

        sent = sendMessage(client, &msg);
        if(sent == -1) {
            syslog(LOG_ERR, "Error sending reply to client.");
            return NULL;
        }
    }

    return NULL;
}
<commit_msg>Fix error message<commit_after>/*
   Copyright 2013-2014 Daniele Di Sarli

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <pthread.h>
#include <syslog.h>
#include <errno.h>
#include "comsock.h"
#include "client.h"
#include <errno.h>
#include <err.h>
#include <bsd/libutil.h>

using namespace std;

void logServerExit(int __status, int __pri, const char *fmt...);
void startDaemon();
void enableALS(bool enable);
void *IPCHandler(void *arg);
void *clientHandler(void *arg);
char* acpi_call(string data);
int getLidStatus();

volatile bool active = false;

int g_socket = -1;

const string SOCKET_PATH = "/var/run/als-controller.socket";
char* C_SOCKET_PATH = (char*)SOCKET_PATH.c_str();

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t start = PTHREAD_COND_INITIALIZER;

/** Signal mask */
static sigset_t g_sigset;

/*void sigHandler(int sig)
{
    if(sig == SIGUSR1) {
        ..
    }
}*/

void *sigManager(void *arg) {
  int signum;

  while(1) {
    sigwait(&g_sigset, &signum);

    if(signum == SIGINT || signum == SIGTERM) {
        logServerExit(EXIT_SUCCESS, LOG_INFO, "Terminated.");
    }
  }

  return NULL;
}

void logServerExit(int __status, int __pri, const char *fmt...) {
    closeServerChannel(C_SOCKET_PATH, g_socket);
    enableALS(false);
    syslog(__pri, fmt);
    if(__status != EXIT_SUCCESS)
        syslog(LOG_INFO, "Terminated.");
    closelog();
    exit(__status);
}

char* acpi_call(string data) {
    int fd = open("/proc/acpi/call", O_RDWR);
    if(fd == -1) {
        logServerExit(EXIT_FAILURE, LOG_CRIT, "Error opening /proc/acpi/call");
    }
    if(write(fd, data.c_str(), data.length() + 1) == -1) {
        syslog(LOG_ERR, "Error writing to /proc/acpi/call");
        return NULL;
    }

    int buf_size = 100;
    char* buf = (char*)calloc(buf_size, sizeof(char));
    int nread = read(fd, buf, buf_size-1);
    if(nread == -1) {
        syslog(LOG_ERR, "Error reading from /proc/acpi/call");
        return NULL;
    }

    close(fd);

    //syslog(LOG_DEBUG, buf);
    return buf;
}

void enableALS(bool enable) {
    if(enable) {
        acpi_call("\\_SB.ATKD.ALSC 0x1");
        acpi_call("\\_SB.PCI0.LPCB.EC0.TALS 0x1");
    } else {
        acpi_call("\\_SB.PCI0.LPCB.EC0.TALS 0x0");
    }

    if (enable)
        syslog(LOG_INFO, "ALS enabled");
    else
        syslog(LOG_INFO, "ALS disabled");
}

void setScreenBacklight(int percent) {
    int ret = 0;
    char cmd[100];
    snprintf(cmd, 100, "xbacklight -set %d", percent);
    ret = system(cmd);
    if (ret < 0) {
        syslog(LOG_ERR, "Failed to set screen backlight.");
    }
}

void setKeyboardBacklight(int percent) {
    int value = 0;
    int ret = 0;
    if(percent <= 25) value = 0;
    else if(percent <= 50) value = 1;
    else if(percent <= 75) value = 2;
    else if(percent <= 100) value = 3;

    char cmd[150];
    snprintf(cmd, 150, "echo %d | tee /sys/class/leds/asus::kbd_backlight/brightness", value);
    ret = system(cmd);
    if (ret < 0) {
        syslog(LOG_ERR, "Failed to set keyboard backlight.");
    }
}

/**
 * @brief getLidStatus
 * @return 1 if opened, 0 if closed, -1 on error, -2 if unknown
 */
int getLidStatus() {
    int fd = open("/proc/acpi/button/lid/LID/state", O_RDONLY);
    if(fd == -1) {
        syslog(LOG_ERR, "Error opening /proc/acpi/button/lid/LID/state");
        return -1;
    } else {
        char str[100];
        int count = read(fd, str, 100);
        str[count] = '\0';
        close(fd);
        string s = string(str);
        if(s.find("open") != string::npos) {
            return 1;
        } else if(s.find("closed") != string::npos) {
            return 0;
        } else {
            return -2;
        }
    }
}

int getAmbientLightPercent() {
    int fd = open("/sys/bus/acpi/devices/ACPI0008:00/ali", O_RDONLY);
    if(fd == -1) {
        logServerExit(EXIT_FAILURE, LOG_CRIT, "Error opening /sys/bus/acpi/devices/ACPI0008:00/ali");
    }
    char strals[100];
    int count = read(fd, strals, 100);
    strals[count] = '\0';
    close(fd);

    // 0x32 (min illuminance), 0xC8, 0x190, 0x258, 0x320 (max illuminance).
    int als = atoi(strals);
    //printf("\"%s\"\n", strals);
    //printf("Illuminance detected: %d\n", als);

    float percent = 0;

    switch(als) {
    case 0x32:
        percent = 10;
        break;
    case 0xC8:
        percent = 25;
        break;
    case 0x190:
        percent = 50;
        break;
    case 0x258:
        percent = 75;
        break;
    case 0x320:
        percent = 100;
        break;
    }

    return percent;
}

int main(int argc, char *argv[])
{
    /*struct sigaction sa;
    sa.sa_handler = sigHandler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGUSR1, &sa, NULL);*/

    if(argc > 1) {
        Client c = Client(argc, argv, SOCKET_PATH);
        c.Run();
        exit(EXIT_SUCCESS);
    }

    struct pidfh *pfh;
    pid_t otherpid;
    pfh = pidfile_open("/var/run/als-controller.pid", 0600, &otherpid);
    if (pfh == NULL) {
        if (errno == EEXIST) {
                    errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
                        (intmax_t)otherpid);
        }
        /* If we cannot create pidfile from other reasons, only warn. */
        warn("Cannot open or create pidfile");
    }

    if (daemon(0, 0) == -1) {
        warn("Cannot daemonize");
        pidfile_remove(pfh);
        exit(EXIT_FAILURE);
    }

    pidfile_write(pfh);

    /* Change the file mode mask */
    umask(0);

    /* Open the log file */
    openlog("als-controller", LOG_PID, LOG_DAEMON);

    startDaemon();
    pidfile_remove(pfh);
    return 0;
}

void startDaemon()
{
    syslog(LOG_NOTICE, "Started.");

    /* Maschera i signal handler. La maschera viene ereditata dai thread successivi
     * (quindi questi segnali verranno bloccati in tutti i thread).
     * In particolare, il thread "sigthread" si occuperà di gestire tutti i segnali
     * che qui stiamo bloccando. */
    sigemptyset(&g_sigset);
    sigaddset(&g_sigset, SIGINT);
    sigaddset(&g_sigset, SIGTERM);
    if(pthread_sigmask(SIG_SETMASK, &g_sigset, NULL) != 0) {
        logServerExit(EXIT_FAILURE, LOG_CRIT, "Sigmask error.");
    }

    pthread_t sigthread;
    if(pthread_create(&sigthread, NULL, sigManager, NULL) != 0) {
        logServerExit(EXIT_FAILURE, LOG_CRIT, "Creating thread.");
    }

    pthread_t thread_id;
    int err = pthread_create(&thread_id, NULL, IPCHandler, NULL);
    if(err != 0) {
        syslog(LOG_CRIT, "Cannot create thread");
        exit(EXIT_FAILURE);
    }

    while(1) {

        pthread_mutex_lock(&mtx);
        while(!active) {
            pthread_cond_wait(&start, &mtx);
        }
        pthread_mutex_unlock(&mtx);

        if(getLidStatus() == 0) {
            setKeyboardBacklight(0);
        } else {

            float als = getAmbientLightPercent();
            //printf("Illuminance percent: %f\n", als);

            if(als <= 10) {
                setScreenBacklight(40);
                setKeyboardBacklight(100);
            } else if(als <= 25) {
                setScreenBacklight(60);
                setKeyboardBacklight(0);
            } else if(als <= 50) {
                setScreenBacklight(75);
                setKeyboardBacklight(0);
            } else if(als <= 75) {
                setScreenBacklight(90);
                setKeyboardBacklight(0);
            } else if(als <= 100) {
                setScreenBacklight(100);
                setKeyboardBacklight(0);
            }
        }

        sleep(3);
    }

    logServerExit(EXIT_SUCCESS, LOG_NOTICE, "Terminated.");
}

void *IPCHandler(void *arg)
{
    unlink(C_SOCKET_PATH);
    g_socket = createServerChannel(C_SOCKET_PATH);
    if(g_socket == -1) {
      logServerExit(EXIT_FAILURE, LOG_CRIT, "Error creating socket");
    }

    // Permessi 777 sulla socket
    if(chmod(C_SOCKET_PATH, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0) {
      closeServerChannel(C_SOCKET_PATH, g_socket);
      return NULL;
    }

    while(1)
    {
        int client = acceptConnection(g_socket);
        if(client == -1) {
            syslog(LOG_ERR, "Error accepting client connection.");
        } else {
            pthread_t thread_id;
            int err = pthread_create(&thread_id, NULL, clientHandler, (void *)(size_t)client);
            if(err != 0) {
                logServerExit(EXIT_FAILURE, LOG_CRIT, "Error creating client thread.");
            }
        }
    }
}

void *clientHandler(void *arg)
{
    int client = (int)(size_t)arg;
    message_t msg;

    if(receiveMessage(client, &msg) == -1) {
        syslog(LOG_ERR, "Error receiving message from client.");
        return NULL;
    }

    if(msg.type == MSG_ENABLE) {
        enableALS(true);
        pthread_mutex_lock(&mtx);
        active = true;
        pthread_mutex_unlock(&mtx);
        pthread_cond_signal(&start);
    } else if(msg.type == MSG_DISABLE) {
        pthread_mutex_lock(&mtx);
        active = false;
        pthread_mutex_unlock(&mtx);
        enableALS(false);
    } else if(msg.type == MSG_STATUS) {
        bool status = false;
        pthread_mutex_lock(&mtx);
        status = active;
        pthread_mutex_unlock(&mtx);

        int sent;
        message_t msg;

        msg.type = status ? MSG_ENABLED : MSG_DISABLED;
        msg.buffer = NULL;
        msg.length = 0;

        sent = sendMessage(client, &msg);
        if(sent == -1) {
            syslog(LOG_ERR, "Error sending reply to client.");
            return NULL;
        }
    }

    return NULL;
}
<|endoftext|>


<commit_before>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <sstream>
#include "logstore.h"
#include "regionAllocator.h"
#include "diskTreeComponent.h"

#include <assert.h>
#include <limits.h>
#include <math.h>
#include <pthread.h>
#include <sys/time.h>
#include <time.h>

#define LOG_NAME   "check_logTree.log"
#define NUM_ENTRIES_A 10000
#define NUM_ENTRIES_B 10
#define NUM_ENTRIES_C 0

#define OFFSET      (NUM_ENTRIES * 10)

#include <stasis/transactional.h>
#undef begin
#undef end

#include "check_util.h"

void insertProbeIter_str(int  NUM_ENTRIES)
{
    srand(1000);
    unlink("storefile.txt");
    unlink("logfile.txt");

    sync();

    logtable<datatuple>::init_stasis();

    int xid = Tbegin();

    Tcommit(xid);

    xid = Tbegin();
    diskTreeComponent::internalNodes *lt = new diskTreeComponent::internalNodes(xid, 1000, 10000, 40);

    long oldpagenum = -1;

    std::vector<std::string> arr;
    preprandstr(NUM_ENTRIES, arr, 50, false);
    std::sort(arr.begin(), arr.end(), &mycmp);

    //for(int i = 0; i < NUM_ENTRIES; i++)
    //{
    //   printf("%s\t", arr[i].c_str());
    //   int keylen = arr[i].length()+1;
    //  printf("%d\n", keylen);
    //}

    printf("Stage 1: Writing %d keys\n", NUM_ENTRIES);

    for(int i = 0; i < NUM_ENTRIES; i++)
    {
        int keylen = arr[i].length()+1;
        byte *currkey = (byte*)malloc(keylen);
        for(int j=0; j<keylen-1; j++)
            currkey[j] = arr[i][j];
        currkey[keylen-1]='\0';

        //printf("\n#########\ni=%d\nkey:\t%s\nkeylen:%d\n",i,((char*)currkey),keylen);
        long pagenum = lt->findPage(xid, currkey, keylen);
        //printf("pagenum:%d\n", pagenum);
        assert(pagenum == -1 || pagenum == oldpagenum || oldpagenum == -1);
        //printf("TlsmAppendPage %d\n",i);

        lt->appendPage(xid, currkey, keylen, i + OFFSET);

        pagenum = lt->findPage(xid, currkey,keylen);
        oldpagenum = pagenum;
        //printf("pagenum:%d\n", pagenum);
        assert(pagenum == i + OFFSET);
        free(currkey);

    }

    printf("Writes complete.");

    Tcommit(xid);
    xid = Tbegin();

    printf("\nTREE STRUCTURE\n");
    lt->print_tree(xid);

    printf("Stage 2: Looking up %d keys\n", NUM_ENTRIES);

    for(int i = 0; i < NUM_ENTRIES; i++) {
        int keylen = arr[i].length()+1;
        byte *currkey = (byte*)malloc(keylen);
        for(int j=0; j<keylen-1; j++)
            currkey[j] = arr[i][j];
        currkey[keylen-1]='\0';

        //printf("\n#########\ni=%d\nkey:\t%s\nkeylen:%d\n",i,((char*)currkey),keylen);
        long pagenum = lt->findPage(xid, currkey, keylen);
        //printf("pagenum:%d\n", pagenum);
        assert(pagenum == i + OFFSET);
        free(currkey);
    }

    printf("Stage 3: Iterating over %d keys\n", NUM_ENTRIES);

    int64_t count = 0;
    RegionAllocator * ro_alloc = new RegionAllocator();
    diskTreeComponent::internalNodes::iterator * it = new diskTreeComponent::internalNodes::iterator(xid, ro_alloc, lt->get_root_rec());

    while(it->next()) {
        byte * key;
        byte **key_ptr = &key;
        size_t keysize = it->key((byte**)key_ptr);

        pageid_t *value;
        pageid_t **value_ptr = &value;
        size_t valsize = it->value((byte**)value_ptr);
        assert(valsize == sizeof(pageid_t));
        assert(!mycmp(std::string((char*)key), arr[count]) && !mycmp(arr[count],std::string((char*)key)));
        assert(keysize == arr[count].length()+1);
        count++;
    }
    assert(count == NUM_ENTRIES);

    it->close();
    delete it;
    delete ro_alloc;
	Tcommit(xid);
	logtable<datatuple>::deinit_stasis();
}

void insertProbeIter_int(int  NUM_ENTRIES)
{

    unlink("storefile.txt");
    unlink("logfile.txt");

    sync();

    bufferManagerNonBlockingSlowHandleType = IO_HANDLE_PFILE;

    Tinit();

    int xid = Tbegin();

    Tcommit(xid);

    xid = Tbegin();
    diskTreeComponent::internalNodes *lt = new diskTreeComponent::internalNodes(xid, 1000, 10000, 40);

    long oldpagenum = -1;

    for(int32_t i = 0; i < NUM_ENTRIES; i++) {
        int keylen = sizeof(int32_t);
        byte *currkey = (byte*)malloc(keylen);
        memcpy(currkey, (byte*)(&i), keylen);
        //currkey[]='\0';

        printf("\n#########\ni=%d\nkey:\t%d\nkeylen:%d\n",i,*((int32_t*)currkey),keylen);
        pageid_t pagenum = lt->findPage(xid, currkey, keylen);
        printf("pagenum:%lld\n", (long long)pagenum);
        assert(pagenum == -1 || pagenum == oldpagenum || oldpagenum == -1);
        printf("TlsmAppendPage %d\n",i);

        lt->appendPage(xid, currkey, keylen, i + OFFSET);

        pagenum = lt->findPage(xid, currkey,keylen);
        oldpagenum = pagenum;
        printf("pagenum:%lld\n", (long long)pagenum);
        assert(pagenum == i + OFFSET);
        free(currkey);
    }

    printf("Writes complete.");

    Tcommit(xid);
    xid = Tbegin();

    printf("\nTREE STRUCTURE\n");
    lt->print_tree(xid);

    for(int32_t i = 1; i < NUM_ENTRIES; i++) {
        int keylen = sizeof(int32_t);
        byte *currkey = (byte*)malloc(keylen);
        memcpy(currkey, (byte*)(&i), keylen);

        printf("\n#########\ni=%d\nkey:\t%d\nkeylen:%d\n",i,*((int32_t*)currkey),keylen);
        pageid_t pagenum = lt->findPage(xid, currkey, keylen);
        printf("pagenum:%lld\n", (long long) pagenum);
        assert(pagenum == i + OFFSET);
        free(currkey);
    }

    /*
      int64_t count = 0;

      lladdIterator_t * it = lsmTreeIterator_open(xid, tree);

      while(lsmTreeIterator_next(xid, it)) {
      lsmkey_t * key;
      lsmkey_t **key_ptr = &key;
      int size = lsmTreeIterator_key(xid, it, (byte**)key_ptr);
      assert(size == sizeof(lsmkey_t));
      long *value;
      long **value_ptr = &value;
      size = lsmTreeIterator_value(xid, it, (byte**)value_ptr);
      assert(size == sizeof(pageid_t));
      assert(*key + OFFSET == *value);
      assert(*key == count);
      count++;
      }
      assert(count == NUM_ENTRIES);

      lsmTreeIterator_close(xid, it);

    */
    Tcommit(xid);
    Tdeinit();
}

/** @test
 */
int main()
{
    insertProbeIter_str(NUM_ENTRIES_A);
    //insertProbeIter_int(NUM_ENTRIES_A);

    return 0;
}

<commit_msg>remove line from unit test that had no effect, but broke compilation<commit_after>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <sstream>
#include "logstore.h"
#include "regionAllocator.h"
#include "diskTreeComponent.h"

#include <assert.h>
#include <limits.h>
#include <math.h>
#include <pthread.h>
#include <sys/time.h>
#include <time.h>

#define LOG_NAME   "check_logTree.log"
#define NUM_ENTRIES_A 10000
#define NUM_ENTRIES_B 10
#define NUM_ENTRIES_C 0

#define OFFSET      (NUM_ENTRIES * 10)

#include <stasis/transactional.h>
#undef begin
#undef end

#include "check_util.h"

void insertProbeIter_str(int  NUM_ENTRIES)
{
    srand(1000);
    unlink("storefile.txt");
    unlink("logfile.txt");

    sync();

    logtable<datatuple>::init_stasis();

    int xid = Tbegin();

    Tcommit(xid);

    xid = Tbegin();
    diskTreeComponent::internalNodes *lt = new diskTreeComponent::internalNodes(xid, 1000, 10000, 40);

    long oldpagenum = -1;

    std::vector<std::string> arr;
    preprandstr(NUM_ENTRIES, arr, 50, false);
    std::sort(arr.begin(), arr.end(), &mycmp);

    //for(int i = 0; i < NUM_ENTRIES; i++)
    //{
    //   printf("%s\t", arr[i].c_str());
    //   int keylen = arr[i].length()+1;
    //  printf("%d\n", keylen);
    //}

    printf("Stage 1: Writing %d keys\n", NUM_ENTRIES);

    for(int i = 0; i < NUM_ENTRIES; i++)
    {
        int keylen = arr[i].length()+1;
        byte *currkey = (byte*)malloc(keylen);
        for(int j=0; j<keylen-1; j++)
            currkey[j] = arr[i][j];
        currkey[keylen-1]='\0';

        //printf("\n#########\ni=%d\nkey:\t%s\nkeylen:%d\n",i,((char*)currkey),keylen);
        long pagenum = lt->findPage(xid, currkey, keylen);
        //printf("pagenum:%d\n", pagenum);
        assert(pagenum == -1 || pagenum == oldpagenum || oldpagenum == -1);
        //printf("TlsmAppendPage %d\n",i);

        lt->appendPage(xid, currkey, keylen, i + OFFSET);

        pagenum = lt->findPage(xid, currkey,keylen);
        oldpagenum = pagenum;
        //printf("pagenum:%d\n", pagenum);
        assert(pagenum == i + OFFSET);
        free(currkey);

    }

    printf("Writes complete.");

    Tcommit(xid);
    xid = Tbegin();

    printf("\nTREE STRUCTURE\n");
    lt->print_tree(xid);

    printf("Stage 2: Looking up %d keys\n", NUM_ENTRIES);

    for(int i = 0; i < NUM_ENTRIES; i++) {
        int keylen = arr[i].length()+1;
        byte *currkey = (byte*)malloc(keylen);
        for(int j=0; j<keylen-1; j++)
            currkey[j] = arr[i][j];
        currkey[keylen-1]='\0';

        //printf("\n#########\ni=%d\nkey:\t%s\nkeylen:%d\n",i,((char*)currkey),keylen);
        long pagenum = lt->findPage(xid, currkey, keylen);
        //printf("pagenum:%d\n", pagenum);
        assert(pagenum == i + OFFSET);
        free(currkey);
    }

    printf("Stage 3: Iterating over %d keys\n", NUM_ENTRIES);

    int64_t count = 0;
    RegionAllocator * ro_alloc = new RegionAllocator();
    diskTreeComponent::internalNodes::iterator * it = new diskTreeComponent::internalNodes::iterator(xid, ro_alloc, lt->get_root_rec());

    while(it->next()) {
        byte * key;
        byte **key_ptr = &key;
        size_t keysize = it->key((byte**)key_ptr);

        pageid_t *value;
        pageid_t **value_ptr = &value;
        size_t valsize = it->value((byte**)value_ptr);
        assert(valsize == sizeof(pageid_t));
        assert(!mycmp(std::string((char*)key), arr[count]) && !mycmp(arr[count],std::string((char*)key)));
        assert(keysize == arr[count].length()+1);
        count++;
    }
    assert(count == NUM_ENTRIES);

    it->close();
    delete it;
    delete ro_alloc;
	Tcommit(xid);
	logtable<datatuple>::deinit_stasis();
}

void insertProbeIter_int(int  NUM_ENTRIES)
{

    unlink("storefile.txt");
    unlink("logfile.txt");

    sync();

    Tinit();

    int xid = Tbegin();

    Tcommit(xid);

    xid = Tbegin();
    diskTreeComponent::internalNodes *lt = new diskTreeComponent::internalNodes(xid, 1000, 10000, 40);

    long oldpagenum = -1;

    for(int32_t i = 0; i < NUM_ENTRIES; i++) {
        int keylen = sizeof(int32_t);
        byte *currkey = (byte*)malloc(keylen);
        memcpy(currkey, (byte*)(&i), keylen);
        //currkey[]='\0';

        printf("\n#########\ni=%d\nkey:\t%d\nkeylen:%d\n",i,*((int32_t*)currkey),keylen);
        pageid_t pagenum = lt->findPage(xid, currkey, keylen);
        printf("pagenum:%lld\n", (long long)pagenum);
        assert(pagenum == -1 || pagenum == oldpagenum || oldpagenum == -1);
        printf("TlsmAppendPage %d\n",i);

        lt->appendPage(xid, currkey, keylen, i + OFFSET);

        pagenum = lt->findPage(xid, currkey,keylen);
        oldpagenum = pagenum;
        printf("pagenum:%lld\n", (long long)pagenum);
        assert(pagenum == i + OFFSET);
        free(currkey);
    }

    printf("Writes complete.");

    Tcommit(xid);
    xid = Tbegin();

    printf("\nTREE STRUCTURE\n");
    lt->print_tree(xid);

    for(int32_t i = 1; i < NUM_ENTRIES; i++) {
        int keylen = sizeof(int32_t);
        byte *currkey = (byte*)malloc(keylen);
        memcpy(currkey, (byte*)(&i), keylen);

        printf("\n#########\ni=%d\nkey:\t%d\nkeylen:%d\n",i,*((int32_t*)currkey),keylen);
        pageid_t pagenum = lt->findPage(xid, currkey, keylen);
        printf("pagenum:%lld\n", (long long) pagenum);
        assert(pagenum == i + OFFSET);
        free(currkey);
    }

    /*
      int64_t count = 0;

      lladdIterator_t * it = lsmTreeIterator_open(xid, tree);

      while(lsmTreeIterator_next(xid, it)) {
      lsmkey_t * key;
      lsmkey_t **key_ptr = &key;
      int size = lsmTreeIterator_key(xid, it, (byte**)key_ptr);
      assert(size == sizeof(lsmkey_t));
      long *value;
      long **value_ptr = &value;
      size = lsmTreeIterator_value(xid, it, (byte**)value_ptr);
      assert(size == sizeof(pageid_t));
      assert(*key + OFFSET == *value);
      assert(*key == count);
      count++;
      }
      assert(count == NUM_ENTRIES);

      lsmTreeIterator_close(xid, it);

    */
    Tcommit(xid);
    Tdeinit();
}

/** @test
 */
int main()
{
    insertProbeIter_str(NUM_ENTRIES_A);
    //insertProbeIter_int(NUM_ENTRIES_A);

    return 0;
}

<|endoftext|>


<commit_before>#pragma once

// `krbn::device_observer` can be used safely in a multi-threaded environment.

#include "boost_defs.hpp"

#include "grabbable_state_manager.hpp"
#include "grabber_client.hpp"
#include "hid_observer.hpp"
#include "logger.hpp"
#include "time_utility.hpp"
#include "types.hpp"
#include <pqrs/dispatcher.hpp>
#include <pqrs/osx/iokit_hid_manager.hpp>
#include <pqrs/osx/iokit_types.hpp>

namespace krbn {
class device_observer final : public pqrs::dispatcher::extra::dispatcher_client {
public:
  device_observer(const device_observer&) = delete;

  device_observer(std::weak_ptr<grabber_client> grabber_client) : dispatcher_client(),
                                                                  grabber_client_(grabber_client) {
    // grabbable_state_manager_

    grabbable_state_manager_ = std::make_unique<grabbable_state_manager>();

    grabbable_state_manager_->grabbable_state_changed.connect([this](auto&& grabbable_state) {
      if (auto client = grabber_client_.lock()) {
        client->async_grabbable_state_changed(grabbable_state);
      }
    });

    // hid_manager_

    std::vector<pqrs::cf_ptr<CFDictionaryRef>> matching_dictionaries{
        pqrs::osx::iokit_hid_manager::make_matching_dictionary(
            pqrs::osx::iokit_hid_usage_page_generic_desktop,
            pqrs::osx::iokit_hid_usage_generic_desktop_keyboard),

        pqrs::osx::iokit_hid_manager::make_matching_dictionary(
            pqrs::osx::iokit_hid_usage_page_generic_desktop,
            pqrs::osx::iokit_hid_usage_generic_desktop_mouse),

        pqrs::osx::iokit_hid_manager::make_matching_dictionary(
            pqrs::osx::iokit_hid_usage_page_generic_desktop,
            pqrs::osx::iokit_hid_usage_generic_desktop_pointer),
    };

    hid_manager_ = std::make_unique<pqrs::osx::iokit_hid_manager>(weak_dispatcher_,
                                                                  matching_dictionaries);

    hid_manager_->device_matched.connect([this](auto&& registry_entry_id, auto&& device_ptr) {
      iokit_utility::log_matching_device(registry_entry_id, *device_ptr);

      auto hid = std::make_shared<krbn::human_interface_device>(*device_ptr,
                                                                registry_entry_id);
      hids_[registry_entry_id] = hid;
      auto device_name = hid->get_name_for_log();

      logger::get_logger().info("{0} is matched.", device_name);

      grabbable_state_manager_->update(grabbable_state(hid->get_registry_entry_id(),
                                                       grabbable_state::state::device_error,
                                                       grabbable_state::ungrabbable_temporarily_reason::none,
                                                       time_utility::mach_absolute_time_point()));

      if (hid->is_karabiner_virtual_hid_device()) {
        // Handle caps_lock_state_changed event only if the hid is Karabiner-VirtualHIDDevice.
        hid->values_arrived.connect([this](auto&& shared_event_queue) {
          for (const auto& e : shared_event_queue->get_entries()) {
            if (e.get_event().get_type() == event_queue::event::type::caps_lock_state_changed) {
              if (auto client = grabber_client_.lock()) {
                if (auto state = e.get_event().get_integer_value()) {
                  client->async_caps_lock_state_changed(*state);
                }
              }
            }
          }
        });
      } else {
        hid->values_arrived.connect([this](auto&& shared_event_queue) {
          grabbable_state_manager_->update(*shared_event_queue);
        });
      }

      auto observer = std::make_shared<hid_observer>(hid);
      hid_observers_[hid->get_registry_entry_id()] = observer;

      observer->device_observed.connect([this, registry_entry_id, device_name] {
        logger::get_logger().info("{0} is observed.", device_name);

        if (auto state = grabbable_state_manager_->get_grabbable_state(registry_entry_id)) {
          // Keep grabbable_state if the state is already changed by value_callback.
          if (state->get_state() == grabbable_state::state::device_error) {
            grabbable_state_manager_->update(grabbable_state(registry_entry_id,
                                                             grabbable_state::state::grabbable,
                                                             grabbable_state::ungrabbable_temporarily_reason::none,
                                                             time_utility::mach_absolute_time_point()));
          }
        }
      });

      observer->async_observe();
    });

    hid_manager_->device_terminated.connect([this](auto&& registry_entry_id) {
      auto it = hids_.find(registry_entry_id);
      if (it != std::end(hids_)) {
        logger::get_logger().info("{0} is terminated.", it->second->get_name_for_log());
      }

      hid_observers_.erase(registry_entry_id);
      hids_.erase(registry_entry_id);
    });

    hid_manager_->error_occurred.connect([](auto&& message, auto&& iokit_return) {
      logger::get_logger().error("{0}: {1}", message, iokit_return.to_string());
    });

    hid_manager_->async_start();

    logger::get_logger().info("device_observer is started.");
  }

  virtual ~device_observer(void) {
    detach_from_dispatcher([this] {
      hid_manager_ = nullptr;

      hid_observers_.clear();
      hids_.clear();

      grabbable_state_manager_ = nullptr;
    });

    logger::get_logger().info("device_observer is stopped.");
  }

private:
  std::weak_ptr<grabber_client> grabber_client_;

  std::unique_ptr<pqrs::osx::iokit_hid_manager> hid_manager_;
  std::unordered_map<pqrs::osx::iokit_registry_entry_id, std::shared_ptr<krbn::human_interface_device>> hids_;
  std::unordered_map<pqrs::osx::iokit_registry_entry_id, std::shared_ptr<hid_observer>> hid_observers_;
  std::unique_ptr<grabbable_state_manager> grabbable_state_manager_;
};
} // namespace krbn
<commit_msg>use hid_queue_value_monitor<commit_after>#pragma once

// `krbn::device_observer` can be used safely in a multi-threaded environment.

#include "event_queue.hpp"
#include "grabbable_state_manager/manager.hpp"
#include "grabber_client.hpp"
#include "iokit_utility.hpp"
#include "logger.hpp"
#include "time_utility.hpp"
#include "types.hpp"
#include <pqrs/dispatcher.hpp>
#include <pqrs/osx/iokit_hid_manager.hpp>
#include <pqrs/osx/iokit_hid_queue_value_monitor.hpp>
#include <pqrs/osx/iokit_types.hpp>

namespace krbn {
class device_observer final : public pqrs::dispatcher::extra::dispatcher_client {
public:
  device_observer(const device_observer&) = delete;

  device_observer(std::weak_ptr<grabber_client> grabber_client) : dispatcher_client(),
                                                                  grabber_client_(grabber_client) {
    // grabbable_state_manager_

    grabbable_state_manager_ = std::make_unique<grabbable_state_manager::manager>();

    grabbable_state_manager_->grabbable_state_changed.connect([this](auto&& grabbable_state) {
      if (auto client = grabber_client_.lock()) {
        client->async_grabbable_state_changed(grabbable_state);
      }
    });

    // hid_manager_

    std::vector<pqrs::cf_ptr<CFDictionaryRef>> matching_dictionaries{
        pqrs::osx::iokit_hid_manager::make_matching_dictionary(
            pqrs::osx::iokit_hid_usage_page_generic_desktop,
            pqrs::osx::iokit_hid_usage_generic_desktop_keyboard),

        pqrs::osx::iokit_hid_manager::make_matching_dictionary(
            pqrs::osx::iokit_hid_usage_page_generic_desktop,
            pqrs::osx::iokit_hid_usage_generic_desktop_mouse),

        pqrs::osx::iokit_hid_manager::make_matching_dictionary(
            pqrs::osx::iokit_hid_usage_page_generic_desktop,
            pqrs::osx::iokit_hid_usage_generic_desktop_pointer),
    };

    hid_manager_ = std::make_unique<pqrs::osx::iokit_hid_manager>(weak_dispatcher_,
                                                                  matching_dictionaries);

    hid_manager_->device_matched.connect([this](auto&& registry_entry_id, auto&& device_ptr) {
      if (device_ptr) {
        iokit_utility::log_matching_device(registry_entry_id, *device_ptr);

        auto device_id = make_device_id(registry_entry_id);
        auto device_name = iokit_utility::make_device_name_for_log(device_id,
                                                                   *device_ptr);

        grabbable_state_manager_->update(grabbable_state(device_id,
                                                         grabbable_state::state::device_error,
                                                         grabbable_state::ungrabbable_temporarily_reason::none,
                                                         time_utility::mach_absolute_time_point()));

        auto hid_queue_value_monitor = std::make_shared<pqrs::osx::iokit_hid_queue_value_monitor>(weak_dispatcher_,
                                                                                *device_ptr);
        hid_queue_value_monitors_[device_id] = hid_queue_value_monitor;

        if (iokit_utility::is_karabiner_virtual_hid_device(*device_ptr)) {
          // Handle caps_lock_state_changed event only if the hid is Karabiner-VirtualHIDDevice.
          hid_queue_value_monitor->values_arrived.connect([this, device_id](auto&& values_ptr) {
            auto event_queue = krbn::event_queue::make_queue(device_id, values_ptr);

            for (const auto& e : event_queue->get_entries()) {
              if (e.get_event().get_type() == event_queue::event::type::caps_lock_state_changed) {
                if (auto client = grabber_client_.lock()) {
                  if (auto state = e.get_event().get_integer_value()) {
                    client->async_caps_lock_state_changed(*state);
                  }
                }
              }
            }
          });
        } else {
          hid_queue_value_monitor->values_arrived.connect([this, device_id](auto&& values_ptr) {
            auto event_queue = krbn::event_queue::make_queue(device_id, values_ptr);
            grabbable_state_manager_->update(*event_queue);
          });
        }

        hid_queue_value_monitor->started.connect([this, device_id, device_name] {
          logger::get_logger().info("{0} is observed.", device_name);

          if (auto state = grabbable_state_manager_->get_grabbable_state(device_id)) {
            // Keep grabbable_state if the state is already changed by value_callback.
            if (state->get_state() == grabbable_state::state::device_error) {
              grabbable_state_manager_->update(grabbable_state(device_id,
                                                               grabbable_state::state::grabbable,
                                                               grabbable_state::ungrabbable_temporarily_reason::none,
                                                               time_utility::mach_absolute_time_point()));
            }
          }
        });

        hid_queue_value_monitor->async_start(kIOHIDOptionsTypeNone,
                                             std::chrono::milliseconds(3000));
      }
    });

    hid_manager_->device_terminated.connect([this](auto&& registry_entry_id) {
      auto device_id = krbn::make_device_id(registry_entry_id);

      krbn::logger::get_logger().info("device_id:{0} is terminated.", type_safe::get(device_id));

      hid_queue_value_monitors_.erase(device_id);
    });

    hid_manager_->error_occurred.connect([](auto&& message, auto&& iokit_return) {
      logger::get_logger().error("{0}: {1}", message, iokit_return.to_string());
    });

    hid_manager_->async_start();

    logger::get_logger().info("device_observer is started.");
  }

  virtual ~device_observer(void) {
    detach_from_dispatcher([this] {
      hid_manager_ = nullptr;
      hid_queue_value_monitors_.clear();
      grabbable_state_manager_ = nullptr;
    });

    logger::get_logger().info("device_observer is stopped.");
  }

private:
  std::weak_ptr<grabber_client> grabber_client_;

  std::unique_ptr<pqrs::osx::iokit_hid_manager> hid_manager_;
  std::unordered_map<device_id, std::shared_ptr<pqrs::osx::iokit_hid_queue_value_monitor>> hid_queue_value_monitors_;
  std::unique_ptr<grabbable_state_manager::manager> grabbable_state_manager_;
};
} // namespace krbn
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fieldmappingimpl.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 19:07:28 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef EXTENSIONS_ABP_FIELDMAPPINGIMPL_HXX
#define EXTENSIONS_ABP_FIELDMAPPINGIMPL_HXX

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef EXTENSIONS_ABP_ABPTYPES_HXX
#include "abptypes.hxx"
#endif
#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif

namespace com { namespace sun { namespace star {
    namespace lang {
        class XMultiServiceFactory;
    }
} } }
class Window;

//.........................................................................
namespace abp
{
//.........................................................................

    //.....................................................................
    namespace fieldmapping
    {
    //.....................................................................

        //-----------------------------------------------------------------
        /** invokes the field mapping dialog
            @param _rxORB
                service factory to use for creating UNO services
            @param _pParent
                window to use as parent for the dialog and error messages
            @param _rDataSourceName
                name of the data source which should be used
            @param _rTableName
                name of the table which should be used
            @param _rFieldAssignment
                Upon returning from the function, this is field with the field mapping. If the user cancelled the
                dialog, this is cleared.
        */
        sal_Bool invokeDialog(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
            class Window* _pParent,
            const ::rtl::OUString& _rDataSourceName,
            const ::rtl::OUString& _rTableName,
            MapString2String& /* [out] */ _rFieldAssignment
        ) SAL_THROW ( ( ) );

        //-----------------------------------------------------------------
        /** creates a default field mapping for usage with the address book SDBC driver

The column names as used by the SDBC driver for address books is stored in the configuration,
            and this function creates a mapping which uses this configuration information.

        */
        void defaultMapping(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
            MapString2String& /* [out] */ _rFieldAssignment
        ) SAL_THROW ( ( ) );

        //-----------------------------------------------------------------
        /** writes a field mapping for the template document address source
        */
        void writeTemplateAddressFieldMapping(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
            const MapString2String& _rFieldAssignment
        ) SAL_THROW ( ( ) );

    //.....................................................................
    }   // namespace fieldmapping
    //.....................................................................

    //.....................................................................
    namespace addressconfig
    {
    //.....................................................................

        //-----------------------------------------------------------------
        /** writes the data source / table name given into the configuration, to where the template documents
            expect it.
        */
        void writeTemplateAddressSource(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
            const ::rtl::OUString& _rDataSourceName,
            const ::rtl::OUString& _rTableName
        ) SAL_THROW ( ( ) );

        /** writes the configuration entry which states the the pilot has been completed successfully
        */
        void markPilotSuccess(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB
        ) SAL_THROW ( ( ) );

    //.....................................................................
    }   // namespace addressconfig
    //.....................................................................

//.........................................................................
}   // namespace abp
//.........................................................................

#endif // EXTENSIONS_ABP_FIELDMAPPINGIMPL_HXX

<commit_msg>INTEGRATION: CWS dba201b (1.2.470); FILE MERGED 2005/09/21 06:41:37 oj 1.2.470.2: RESYNC: (1.2-1.3); FILE MERGED 2005/07/18 10:51:13 fs 1.2.470.1: #i51833# also pass the XDataSource object around - the field mapping dialog needs it, since the data source is not registered at the database context<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fieldmappingimpl.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2005-09-23 12:49:35 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef EXTENSIONS_ABP_FIELDMAPPINGIMPL_HXX
#define EXTENSIONS_ABP_FIELDMAPPINGIMPL_HXX

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef EXTENSIONS_ABP_ABPTYPES_HXX
#include "abptypes.hxx"
#endif
#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef EXTENSIONS_ABP_ADDRESSSETTINGS_HXX
#include "addresssettings.hxx"
#endif

namespace com { namespace sun { namespace star {
    namespace lang {
        class XMultiServiceFactory;
    }
    namespace beans {
        class XPropertySet;
    }
} } }
class Window;

//.........................................................................
namespace abp
{
//.........................................................................

    //.....................................................................
    namespace fieldmapping
    {
    //.....................................................................

        //-----------------------------------------------------------------
        /** invokes the field mapping dialog
            @param _rxORB
                service factory to use for creating UNO services
            @param _pParent
                window to use as parent for the dialog and error messages
            @param _rSettings
                current settings. Upon return, the field mapping member of this
                structure will be filled with the settings the user did in the
                field mapping dialog.
        */
        sal_Bool invokeDialog(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
            class Window* _pParent,
            const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxDataSource,
            AddressSettings& _rSettings
        ) SAL_THROW ( ( ) );

        //-----------------------------------------------------------------
        /** creates a default field mapping for usage with the address book SDBC driver

The column names as used by the SDBC driver for address books is stored in the configuration,
            and this function creates a mapping which uses this configuration information.

        */
        void defaultMapping(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
            MapString2String& /* [out] */ _rFieldAssignment
        ) SAL_THROW ( ( ) );

        //-----------------------------------------------------------------
        /** writes a field mapping for the template document address source
        */
        void writeTemplateAddressFieldMapping(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
            const MapString2String& _rFieldAssignment
        ) SAL_THROW ( ( ) );

    //.....................................................................
    }   // namespace fieldmapping
    //.....................................................................

    //.....................................................................
    namespace addressconfig
    {
    //.....................................................................

        //-----------------------------------------------------------------
        /** writes the data source / table name given into the configuration, to where the template documents
            expect it.
        */
        void writeTemplateAddressSource(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
            const ::rtl::OUString& _rDataSourceName,
            const ::rtl::OUString& _rTableName
        ) SAL_THROW ( ( ) );

        /** writes the configuration entry which states the the pilot has been completed successfully
        */
        void markPilotSuccess(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB
        ) SAL_THROW ( ( ) );

    //.....................................................................
    }   // namespace addressconfig
    //.....................................................................

//.........................................................................
}   // namespace abp
//.........................................................................

#endif // EXTENSIONS_ABP_FIELDMAPPINGIMPL_HXX

<|endoftext|>


<commit_before>
#include <string>
#include <sstream>

#include "flame/base.h"
#include "pyflame.h"

#define NO_IMPORT_ARRAY
#define PY_ARRAY_UNIQUE_SYMBOL FLAME_PyArray_API
#include <numpy/ndarrayobject.h>

#if SIZE_MAX==NPY_MAX_UINT32
#define NPY_SIZE_T NPY_UINT32
#elif SIZE_MAX==NPY_MAX_UINT64
#define NPY_SIZE_T NPY_UINT64
#else
#error logic error with SIZE_MAX
#endif

#define TRY PyState *state = (PyState*)raw; try

namespace {

struct PyState {
    PyObject_HEAD
    PyObject *dict, *weak; //  __dict__ and __weakref__
    PyObject *attrs; // lookup name to attribute index (for StateBase)
    StateBase *state;
};

static
int PyState_traverse(PyObject *raw, visitproc visit, void *arg)
{
    PyState *state = (PyState*)raw;
    Py_VISIT(state->attrs);
    Py_VISIT(state->dict);
    return 0;
}

static
int PyState_clear(PyObject *raw)
{
    PyState *state = (PyState*)raw;
    Py_CLEAR(state->dict);
    Py_CLEAR(state->attrs);
    return 0;
}

static
void PyState_free(PyObject *raw)
{
    TRY {
        std::auto_ptr<StateBase> S(state->state);
        state->state = NULL;

        if(state->weak)
            PyObject_ClearWeakRefs(raw);

        PyState_clear(raw);

        Py_TYPE(raw)->tp_free(raw);
    } CATCH2V(std::exception, RuntimeError)
}

static
PyObject *PyState_getattro(PyObject *raw, PyObject *attr)
{
    TRY {
        PyObject *idx = PyDict_GetItem(state->attrs, attr);
        if(!idx) {
            return PyObject_GenericGetAttr(raw, attr);
        }
        int i = PyInt_AsLong(idx);

        StateBase::ArrayInfo info;

        if(!state->state->getArray(i, info))
            return PyErr_Format(PyExc_RuntimeError, "invalid attribute name (sub-class forgot %d)", i);

        if(info.ndim==0) { // Scalar
            switch(info.type) {
            case StateBase::ArrayInfo::Double:
                return PyFloat_FromDouble(*(double*)info.ptr);
            case StateBase::ArrayInfo::Sizet:
                return PyLong_FromSize_t(*(size_t*)info.ptr);
            }
            return PyErr_Format(PyExc_TypeError, "unsupported type code %d", info.type);
        }

        int pytype;
        switch(info.type) {
        case StateBase::ArrayInfo::Double: pytype = NPY_DOUBLE; break;
        case StateBase::ArrayInfo::Sizet: pytype = NPY_SIZE_T; break;
        default:
            return PyErr_Format(PyExc_TypeError, "unsupported type code %d", info.type);
        }

        npy_intp dims[StateBase::ArrayInfo::maxdims];
        std::copy(info.dim,
                  info.dim+StateBase::ArrayInfo::maxdims,
                  dims);

        // Alloc new array and copy in

        PyRef<PyArrayObject> obj(PyArray_SimpleNew(info.ndim, dims, pytype));

        // pull parts from PyArray into ArrayInfo so we can use ArrayInfo::raw() to access
        StateBase::ArrayInfo pyinfo;
        pyinfo.ptr = PyArray_BYTES(obj.py());
        pyinfo.ndim= PyArray_NDIM(obj.get());
        std::copy(PyArray_DIMS(obj.get()),
                  PyArray_DIMS(obj.get())+pyinfo.ndim,
                  pyinfo.dim);
        std::copy(PyArray_STRIDES(obj.get()),
                  PyArray_STRIDES(obj.get())+pyinfo.ndim,
                  pyinfo.stride);

        ndindex_iterate<StateBase::ArrayInfo::maxdims> idxiter(info.ndim, info.dim);

        for(; !idxiter.done; idxiter.next()) {
            void       *dest = pyinfo.raw(idxiter.index);
            const void *src  = info  .raw(idxiter.index);

            switch(info.type) {
            case StateBase::ArrayInfo::Double: *(double*)dest = *(double*)src; break;
            case StateBase::ArrayInfo::Sizet:  *(size_t*)dest = *(size_t*)src; break;
            }
        }

        return obj.releasePy();
    } CATCH()
}

static
int PyState_setattro(PyObject *raw, PyObject *attr, PyObject *val)
{
    TRY {
        PyObject *idx = PyDict_GetItem(state->attrs, attr);
        if(!idx)
            return PyObject_GenericSetAttr(raw, attr, val);
        int i = PyInt_AsLong(idx);

        StateBase::ArrayInfo info;

        if(!state->state->getArray(i, info)) {
            PyErr_Format(PyExc_RuntimeError, "invalid attribute name (sub-class forgot %d)", i);
            return -1;
        }

        if(info.ndim==0) {
            // Scalar (use python primative types)

            switch(info.type) {
            case StateBase::ArrayInfo::Double: {
                double *dest = (double*)info.ptr;
                if(PyFloat_Check(val))
                    *dest = PyFloat_AsDouble(val);
                else if(PyLong_Check(val))
                    *dest = PyLong_AsDouble(val);
                else if(PyInt_Check(val))
                    *dest = PyInt_AsLong(val);
                else
                    PyErr_Format(PyExc_ValueError, "Can't assign to double field");
            }
                break;
            case StateBase::ArrayInfo::Sizet: {
                size_t *dest = (size_t*)info.ptr;
                if(PyFloat_Check(val))
                    *dest = PyFloat_AsDouble(val);
                else if(PyLong_Check(val))
                    *dest = PyLong_AsUnsignedLongLong(val);
                else if(PyInt_Check(val))
                    *dest = PyInt_AsLong(val);
                else
                    PyErr_Format(PyExc_ValueError, "Can't assign to double field");
            }
                break;
            default:
                PyErr_Format(PyExc_TypeError, "unsupported type code %d", info.type);
            }

            return PyErr_Occurred() ? -1 : 0;
        }
        // array (use numpy)

        int pytype;
        switch(info.type) {
        case StateBase::ArrayInfo::Double: pytype = NPY_DOUBLE; break;
        case StateBase::ArrayInfo::Sizet: pytype = NPY_SIZE_T; break;
        default:
            PyErr_Format(PyExc_TypeError, "unsupported type code %d", info.type);
            return -1;
        }

        PyRef<PyArrayObject> arr(PyArray_FromObject(val, pytype, 1, 2));

        if(info.ndim!=(size_t)PyArray_NDIM(arr.py())) {
            PyErr_Format(PyExc_ValueError, "cardinality don't match");
            return -1;
        } else if(!std::equal(info.dim, info.dim+info.ndim,
                                    PyArray_DIMS(arr.py()))) {
            PyErr_Format(PyExc_ValueError, "shape does not match don't match");
            return -1;
        }

        // pull parts from PyArray into ArrayInfo so we can use ArrayInfo::raw() to access
        StateBase::ArrayInfo pyinfo;
        pyinfo.ptr = PyArray_BYTES(arr.py());
        pyinfo.ndim= PyArray_NDIM(arr.get());
        std::copy(PyArray_DIMS(arr.get()),
                  PyArray_DIMS(arr.get())+pyinfo.ndim,
                  pyinfo.dim);
        std::copy(PyArray_STRIDES(arr.get()),
                  PyArray_STRIDES(arr.get())+pyinfo.ndim,
                  pyinfo.stride);

        ndindex_iterate<StateBase::ArrayInfo::maxdims> idxiter(info.ndim, info.dim);

        for(; !idxiter.done; idxiter.next()) {
            const void *src  = pyinfo  .raw(idxiter.index);
            void       *dest = info.raw(idxiter.index);

            switch(info.type) {
            case StateBase::ArrayInfo::Double: *(double*)dest = *(double*)src; break;
            case StateBase::ArrayInfo::Sizet:  *(size_t*)dest = *(size_t*)src; break;
            }
        }

        if(info.ndim==1) {
            for(size_t i=0; i<info.dim[0]; i++) {
                const void *src = PyArray_GETPTR1(arr.py(), i);
                void *dest  = info.raw(&i);
                switch(info.type) {
                case StateBase::ArrayInfo::Double: *(double*)dest = *(double*)src; break;
                case StateBase::ArrayInfo::Sizet:  *(size_t*)dest = *(size_t*)src; break;
                }
            }
        } else if(info.ndim==2) {
            size_t idx[2];
            for(idx[0]=0; idx[0]<info.dim[0]; idx[0]++) {
                for(idx[1]=0; idx[1]<info.dim[1]; idx[1]++) {
                    const void *src = PyArray_GETPTR2(arr.py(), idx[0], idx[1]);
                    void *dest  = info.raw(idx);
                    switch(info.type) {
                    case StateBase::ArrayInfo::Double: *(double*)dest = *(double*)src; break;
                    case StateBase::ArrayInfo::Sizet:  *(size_t*)dest = *(size_t*)src; break;
                    }
                }
            }
        }

        return 0;
    } CATCH3(std::exception, RuntimeError, -1)
}

static
PyObject* PyState_str(PyObject *raw)
{
    TRY {
        std::ostringstream strm;
        state->state->show(strm, 0);
        return PyString_FromString(strm.str().c_str());
    } CATCH()
}

static
PyObject* PyState_iter(PyObject *raw)
{
    TRY {
        return PyObject_GetIter(state->attrs);
    }CATCH()
}

static
Py_ssize_t PyState_len(PyObject *raw)
{
    TRY{
        return PyObject_Length(state->attrs);
    }CATCH1(-1)
}

static PySequenceMethods PyState_seq = {
    &PyState_len
};

static
PyObject* PyState_clone(PyObject *raw, PyObject *unused)
{
    TRY {
        std::auto_ptr<StateBase> newstate(state->state->clone());

        PyObject *ret = wrapstate(newstate.get());
        newstate.release();
        return ret;
    } CATCH()
}

static PyMethodDef PyState_methods[] = {
    {"clone", (PyCFunction)&PyState_clone, METH_NOARGS,
     "clone()\n\n"
     "Returns a new State instance which is a copy of this one"
    },
    {NULL, NULL, 0, NULL}
};

static PyTypeObject PyStateType = {
#if PY_MAJOR_VERSION >= 3
    PyVarObject_HEAD_INIT(NULL, 0)
#else
    PyObject_HEAD_INIT(NULL)
    0,
#endif
    "flame._internal.State",
    sizeof(PyState),
};

} // namespace

PyObject* wrapstate(StateBase* b)
{
    try {

        PyRef<PyState> state(PyStateType.tp_alloc(&PyStateType, 0));

        state->state = b;
        state->attrs = state->weak = state->dict = 0;

        state->attrs = PyDict_New();
        if(!state->attrs)
            return NULL;

        for(unsigned i=0; true; i++)
        {
            StateBase::ArrayInfo info;

            if(!b->getArray(i, info))
                break;

            bool skip = info.ndim>3;
            switch(info.type) {
            case StateBase::ArrayInfo::Double:
            case StateBase::ArrayInfo::Sizet:
                break;
            default:
                skip = true;
            }

            if(skip) continue;

            PyRef<> name(PyInt_FromLong(i));
            if(PyDict_SetItemString(state->attrs, info.name, name.py()))
                throw std::runtime_error("Failed to insert into Dict");

        }

        return state.releasePy();
    } CATCH()
}

StateBase* unwrapstate(PyObject* raw)
{
    if(!PyObject_TypeCheck(raw, &PyStateType))
        throw std::invalid_argument("Argument is not a State");
    PyState *state = (PyState*)raw;
    return state->state;
}

static const char pymdoc[] =
        "The interface to a sub-class of C++ StateBase.\n"
        "Can't be constructed from python, see Machine.allocState()\n"
        "\n"
        "Provides access to some C++ member variables via the Machine::getArray() interface.\n"
        ;

int registerModState(PyObject *mod)
{
    PyStateType.tp_doc = pymdoc;

    PyStateType.tp_str = &PyState_str;
    PyStateType.tp_repr = &PyState_str;
    PyStateType.tp_dealloc = &PyState_free;

    PyStateType.tp_iter = &PyState_iter;
    PyStateType.tp_as_sequence = &PyState_seq;

    PyStateType.tp_weaklistoffset = offsetof(PyState, weak);
    PyStateType.tp_traverse = &PyState_traverse;
    PyStateType.tp_clear = &PyState_clear;

    PyStateType.tp_dictoffset = offsetof(PyState, dict);
    PyStateType.tp_getattro = &PyState_getattro;
    PyStateType.tp_setattro = &PyState_setattro;

    PyStateType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC;
    PyStateType.tp_methods = PyState_methods;

    if(PyType_Ready(&PyStateType))
        return -1;

    Py_INCREF(&PyStateType);
    if(PyModule_AddObject(mod, "State", (PyObject*)&PyStateType)) {
        Py_DECREF(&PyStateType);
        return -1;
    }

    return 0;
}
<commit_msg>expose StateBase::show()<commit_after>
#include <string>
#include <sstream>

#include "flame/base.h"
#include "pyflame.h"

#define NO_IMPORT_ARRAY
#define PY_ARRAY_UNIQUE_SYMBOL FLAME_PyArray_API
#include <numpy/ndarrayobject.h>

#if SIZE_MAX==NPY_MAX_UINT32
#define NPY_SIZE_T NPY_UINT32
#elif SIZE_MAX==NPY_MAX_UINT64
#define NPY_SIZE_T NPY_UINT64
#else
#error logic error with SIZE_MAX
#endif

#define TRY PyState *state = (PyState*)raw; try

namespace {

struct PyState {
    PyObject_HEAD
    PyObject *dict, *weak; //  __dict__ and __weakref__
    PyObject *attrs; // lookup name to attribute index (for StateBase)
    StateBase *state;
};

static
int PyState_traverse(PyObject *raw, visitproc visit, void *arg)
{
    PyState *state = (PyState*)raw;
    Py_VISIT(state->attrs);
    Py_VISIT(state->dict);
    return 0;
}

static
int PyState_clear(PyObject *raw)
{
    PyState *state = (PyState*)raw;
    Py_CLEAR(state->dict);
    Py_CLEAR(state->attrs);
    return 0;
}

static
void PyState_free(PyObject *raw)
{
    TRY {
        std::auto_ptr<StateBase> S(state->state);
        state->state = NULL;

        if(state->weak)
            PyObject_ClearWeakRefs(raw);

        PyState_clear(raw);

        Py_TYPE(raw)->tp_free(raw);
    } CATCH2V(std::exception, RuntimeError)
}

static
PyObject *PyState_getattro(PyObject *raw, PyObject *attr)
{
    TRY {
        PyObject *idx = PyDict_GetItem(state->attrs, attr);
        if(!idx) {
            return PyObject_GenericGetAttr(raw, attr);
        }
        int i = PyInt_AsLong(idx);

        StateBase::ArrayInfo info;

        if(!state->state->getArray(i, info))
            return PyErr_Format(PyExc_RuntimeError, "invalid attribute name (sub-class forgot %d)", i);

        if(info.ndim==0) { // Scalar
            switch(info.type) {
            case StateBase::ArrayInfo::Double:
                return PyFloat_FromDouble(*(double*)info.ptr);
            case StateBase::ArrayInfo::Sizet:
                return PyLong_FromSize_t(*(size_t*)info.ptr);
            }
            return PyErr_Format(PyExc_TypeError, "unsupported type code %d", info.type);
        }

        int pytype;
        switch(info.type) {
        case StateBase::ArrayInfo::Double: pytype = NPY_DOUBLE; break;
        case StateBase::ArrayInfo::Sizet: pytype = NPY_SIZE_T; break;
        default:
            return PyErr_Format(PyExc_TypeError, "unsupported type code %d", info.type);
        }

        npy_intp dims[StateBase::ArrayInfo::maxdims];
        std::copy(info.dim,
                  info.dim+StateBase::ArrayInfo::maxdims,
                  dims);

        // Alloc new array and copy in

        PyRef<PyArrayObject> obj(PyArray_SimpleNew(info.ndim, dims, pytype));

        // pull parts from PyArray into ArrayInfo so we can use ArrayInfo::raw() to access
        StateBase::ArrayInfo pyinfo;
        pyinfo.ptr = PyArray_BYTES(obj.py());
        pyinfo.ndim= PyArray_NDIM(obj.get());
        std::copy(PyArray_DIMS(obj.get()),
                  PyArray_DIMS(obj.get())+pyinfo.ndim,
                  pyinfo.dim);
        std::copy(PyArray_STRIDES(obj.get()),
                  PyArray_STRIDES(obj.get())+pyinfo.ndim,
                  pyinfo.stride);

        ndindex_iterate<StateBase::ArrayInfo::maxdims> idxiter(info.ndim, info.dim);

        for(; !idxiter.done; idxiter.next()) {
            void       *dest = pyinfo.raw(idxiter.index);
            const void *src  = info  .raw(idxiter.index);

            switch(info.type) {
            case StateBase::ArrayInfo::Double: *(double*)dest = *(double*)src; break;
            case StateBase::ArrayInfo::Sizet:  *(size_t*)dest = *(size_t*)src; break;
            }
        }

        return obj.releasePy();
    } CATCH()
}

static
int PyState_setattro(PyObject *raw, PyObject *attr, PyObject *val)
{
    TRY {
        PyObject *idx = PyDict_GetItem(state->attrs, attr);
        if(!idx)
            return PyObject_GenericSetAttr(raw, attr, val);
        int i = PyInt_AsLong(idx);

        StateBase::ArrayInfo info;

        if(!state->state->getArray(i, info)) {
            PyErr_Format(PyExc_RuntimeError, "invalid attribute name (sub-class forgot %d)", i);
            return -1;
        }

        if(info.ndim==0) {
            // Scalar (use python primative types)

            switch(info.type) {
            case StateBase::ArrayInfo::Double: {
                double *dest = (double*)info.ptr;
                if(PyFloat_Check(val))
                    *dest = PyFloat_AsDouble(val);
                else if(PyLong_Check(val))
                    *dest = PyLong_AsDouble(val);
                else if(PyInt_Check(val))
                    *dest = PyInt_AsLong(val);
                else
                    PyErr_Format(PyExc_ValueError, "Can't assign to double field");
            }
                break;
            case StateBase::ArrayInfo::Sizet: {
                size_t *dest = (size_t*)info.ptr;
                if(PyFloat_Check(val))
                    *dest = PyFloat_AsDouble(val);
                else if(PyLong_Check(val))
                    *dest = PyLong_AsUnsignedLongLong(val);
                else if(PyInt_Check(val))
                    *dest = PyInt_AsLong(val);
                else
                    PyErr_Format(PyExc_ValueError, "Can't assign to double field");
            }
                break;
            default:
                PyErr_Format(PyExc_TypeError, "unsupported type code %d", info.type);
            }

            return PyErr_Occurred() ? -1 : 0;
        }
        // array (use numpy)

        int pytype;
        switch(info.type) {
        case StateBase::ArrayInfo::Double: pytype = NPY_DOUBLE; break;
        case StateBase::ArrayInfo::Sizet: pytype = NPY_SIZE_T; break;
        default:
            PyErr_Format(PyExc_TypeError, "unsupported type code %d", info.type);
            return -1;
        }

        PyRef<PyArrayObject> arr(PyArray_FromObject(val, pytype, 1, 2));

        if(info.ndim!=(size_t)PyArray_NDIM(arr.py())) {
            PyErr_Format(PyExc_ValueError, "cardinality don't match");
            return -1;
        } else if(!std::equal(info.dim, info.dim+info.ndim,
                                    PyArray_DIMS(arr.py()))) {
            PyErr_Format(PyExc_ValueError, "shape does not match don't match");
            return -1;
        }

        // pull parts from PyArray into ArrayInfo so we can use ArrayInfo::raw() to access
        StateBase::ArrayInfo pyinfo;
        pyinfo.ptr = PyArray_BYTES(arr.py());
        pyinfo.ndim= PyArray_NDIM(arr.get());
        std::copy(PyArray_DIMS(arr.get()),
                  PyArray_DIMS(arr.get())+pyinfo.ndim,
                  pyinfo.dim);
        std::copy(PyArray_STRIDES(arr.get()),
                  PyArray_STRIDES(arr.get())+pyinfo.ndim,
                  pyinfo.stride);

        ndindex_iterate<StateBase::ArrayInfo::maxdims> idxiter(info.ndim, info.dim);

        for(; !idxiter.done; idxiter.next()) {
            const void *src  = pyinfo  .raw(idxiter.index);
            void       *dest = info.raw(idxiter.index);

            switch(info.type) {
            case StateBase::ArrayInfo::Double: *(double*)dest = *(double*)src; break;
            case StateBase::ArrayInfo::Sizet:  *(size_t*)dest = *(size_t*)src; break;
            }
        }

        if(info.ndim==1) {
            for(size_t i=0; i<info.dim[0]; i++) {
                const void *src = PyArray_GETPTR1(arr.py(), i);
                void *dest  = info.raw(&i);
                switch(info.type) {
                case StateBase::ArrayInfo::Double: *(double*)dest = *(double*)src; break;
                case StateBase::ArrayInfo::Sizet:  *(size_t*)dest = *(size_t*)src; break;
                }
            }
        } else if(info.ndim==2) {
            size_t idx[2];
            for(idx[0]=0; idx[0]<info.dim[0]; idx[0]++) {
                for(idx[1]=0; idx[1]<info.dim[1]; idx[1]++) {
                    const void *src = PyArray_GETPTR2(arr.py(), idx[0], idx[1]);
                    void *dest  = info.raw(idx);
                    switch(info.type) {
                    case StateBase::ArrayInfo::Double: *(double*)dest = *(double*)src; break;
                    case StateBase::ArrayInfo::Sizet:  *(size_t*)dest = *(size_t*)src; break;
                    }
                }
            }
        }

        return 0;
    } CATCH3(std::exception, RuntimeError, -1)
}

static
PyObject* PyState_str(PyObject *raw)
{
    TRY {
        std::ostringstream strm;
        state->state->show(strm, 0);
        return PyString_FromString(strm.str().c_str());
    } CATCH()
}

static
PyObject* PyState_iter(PyObject *raw)
{
    TRY {
        return PyObject_GetIter(state->attrs);
    }CATCH()
}

static
Py_ssize_t PyState_len(PyObject *raw)
{
    TRY{
        return PyObject_Length(state->attrs);
    }CATCH1(-1)
}

static PySequenceMethods PyState_seq = {
    &PyState_len
};

static
PyObject* PyState_clone(PyObject *raw, PyObject *unused)
{
    TRY {
        std::auto_ptr<StateBase> newstate(state->state->clone());

        PyObject *ret = wrapstate(newstate.get());
        newstate.release();
        return ret;
    } CATCH()
}

static
PyObject* PyState_show(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY {
        unsigned long level = 1;
        const char *names[] = {"level", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "|k", (char**)names, &level))
            return NULL;

        std::ostringstream strm;
        state->state->show(strm, level);
        return PyString_FromString(strm.str().c_str());
    } CATCH()
}

static PyMethodDef PyState_methods[] = {
    {"clone", (PyCFunction)&PyState_clone, METH_NOARGS,
     "clone()\n\n"
     "Returns a new State instance which is a copy of this one"
    },
    {"show", (PyCFunction)&PyState_show, METH_VARARGS|METH_KEYWORDS,
     "show(level=1)"
    },
    {NULL, NULL, 0, NULL}
};

static PyTypeObject PyStateType = {
#if PY_MAJOR_VERSION >= 3
    PyVarObject_HEAD_INIT(NULL, 0)
#else
    PyObject_HEAD_INIT(NULL)
    0,
#endif
    "flame._internal.State",
    sizeof(PyState),
};

} // namespace

PyObject* wrapstate(StateBase* b)
{
    try {

        PyRef<PyState> state(PyStateType.tp_alloc(&PyStateType, 0));

        state->state = b;
        state->attrs = state->weak = state->dict = 0;

        state->attrs = PyDict_New();
        if(!state->attrs)
            return NULL;

        for(unsigned i=0; true; i++)
        {
            StateBase::ArrayInfo info;

            if(!b->getArray(i, info))
                break;

            bool skip = info.ndim>3;
            switch(info.type) {
            case StateBase::ArrayInfo::Double:
            case StateBase::ArrayInfo::Sizet:
                break;
            default:
                skip = true;
            }

            if(skip) continue;

            PyRef<> name(PyInt_FromLong(i));
            if(PyDict_SetItemString(state->attrs, info.name, name.py()))
                throw std::runtime_error("Failed to insert into Dict");

        }

        return state.releasePy();
    } CATCH()
}

StateBase* unwrapstate(PyObject* raw)
{
    if(!PyObject_TypeCheck(raw, &PyStateType))
        throw std::invalid_argument("Argument is not a State");
    PyState *state = (PyState*)raw;
    return state->state;
}

static const char pymdoc[] =
        "The interface to a sub-class of C++ StateBase.\n"
        "Can't be constructed from python, see Machine.allocState()\n"
        "\n"
        "Provides access to some C++ member variables via the Machine::getArray() interface.\n"
        ;

int registerModState(PyObject *mod)
{
    PyStateType.tp_doc = pymdoc;

    PyStateType.tp_str = &PyState_str;
    PyStateType.tp_repr = &PyState_str;
    PyStateType.tp_dealloc = &PyState_free;

    PyStateType.tp_iter = &PyState_iter;
    PyStateType.tp_as_sequence = &PyState_seq;

    PyStateType.tp_weaklistoffset = offsetof(PyState, weak);
    PyStateType.tp_traverse = &PyState_traverse;
    PyStateType.tp_clear = &PyState_clear;

    PyStateType.tp_dictoffset = offsetof(PyState, dict);
    PyStateType.tp_getattro = &PyState_getattro;
    PyStateType.tp_setattro = &PyState_setattro;

    PyStateType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC;
    PyStateType.tp_methods = PyState_methods;

    if(PyType_Ready(&PyStateType))
        return -1;

    Py_INCREF(&PyStateType);
    if(PyModule_AddObject(mod, "State", (PyObject*)&PyStateType)) {
        Py_DECREF(&PyStateType);
        return -1;
    }

    return 0;
}
<|endoftext|>