<commit_before>/*
   Copyright 2016 Mitchell Young

   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 "UnitTest++/UnitTest++.h"

#include <cmath>
#include <iostream>
#include <limits>

#include "core/geometry/circle.hpp"

using namespace mocc;

TEST(testCircle) {
    std::numeric_limits<real_t> lim;
    Circle c(Point2(0.5, 0.5), 0.75);

    // Check coincident point pointing out. Should be max()
    CHECK_EQUAL(lim.max(), c.distance_to_surface(Point2(-0.25, 0.5),
                                                 Direction(-1.0, 0.0, 0.0)));

    // Check coincident point pointing in and straight across. Should be the
    // diameter
    CHECK_CLOSE(1.5, c.distance_to_surface(Point2(-0.25, 0.5),
                                           Direction(1.0, 0.0, 0.0)),
                GEOM_EPS);

    // Interior point pointing anywhere in the plane
    CHECK_CLOSE(0.75,
                c.distance_to_surface(Point2(0.5, 0.5), Direction(1.0, HPI)),
                GEOM_EPS);

    // Interior point pointing anywhere out of the plane. Should be the
    // radius/sin(theta)
    CHECK_CLOSE(
        0.75 / std::sin(0.5 * HPI),
        c.distance_to_surface(Point2(0.5, 0.5), Direction(1.0, 0.5 * HPI)),
        GEOM_EPS);

    // Exterior glancing, should be max()
    CHECK_EQUAL(lim.max(),
                c.distance_to_surface(Point2(-0.25, 0.0),
                                      Direction(HPI + 0.0000001, HPI)));

    // Exterior good
    CHECK_CLOSE(0.15138781886599732327980531686762,
                c.distance_to_surface(
                    Point2(-0.25, 0.0),
                    Direction(0.5880026035475675, HPI)),
                GEOM_EPS);
}

int main() { return UnitTest::RunAllTests(); }
<commit_msg>Add another assertion to test_Circle<commit_after>/*
   Copyright 2016 Mitchell Young

   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 "UnitTest++/UnitTest++.h"

#include <cmath>
#include <iostream>
#include <limits>

#include "core/geometry/circle.hpp"

using namespace mocc;

TEST(testCircle) {
    std::numeric_limits<real_t> lim;
    Circle c(Point2(0.5, 0.5), 0.75);

    // Check coincident point pointing out. Should be max()
    CHECK_EQUAL(lim.max(), c.distance_to_surface(Point2(-0.25, 0.5),
                                                 Direction(-1.0, 0.0, 0.0)));

    // Check coincident point pointing in and straight across. Should be the
    // diameter
    CHECK_CLOSE(1.5, c.distance_to_surface(Point2(-0.25, 0.5),
                                           Direction(1.0, 0.0, 0.0)),
                GEOM_EPS);

    // Interior point pointing anywhere in the plane
    CHECK_CLOSE(0.75,
                c.distance_to_surface(Point2(0.5, 0.5), Direction(1.0, HPI)),
                GEOM_EPS);

    // Interior point pointing anywhere out of the plane. Should be the
    // radius/sin(theta)
    CHECK_CLOSE(
        0.75 / std::sin(0.5 * HPI),
        c.distance_to_surface(Point2(0.5, 0.5), Direction(1.0, 0.5 * HPI)),
        GEOM_EPS);

    // Exterior glancing, should be max()
    CHECK_EQUAL(lim.max(),
                c.distance_to_surface(Point2(-0.25, 0.0),
                                      Direction(HPI + 0.0000001, HPI)));

    // Exterior good
    CHECK_CLOSE(0.15138781886599732327980531686762,
                c.distance_to_surface(Point2(-0.25, 0.0),
                                      Direction(0.5880026035475675, HPI)),
                GEOM_EPS);

    // Interior, out of the plane. Should be the radius/sin(theta)
    CHECK_CLOSE(
        1.0606601717798212866012665431573,
        c.distance_to_surface(Point2(0.5, 0.5), Direction(0.5, 0.5 * HPI)),
        GEOM_EPS);
}

int main() { return UnitTest::RunAllTests(); }
<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "load_pipe.h"

/**
 * \file pipe_bakery.cxx
 *
 * \brief Implementation of baking a pipeline.
 */

namespace vistk
{

pipeline_t
bake_pipe_blocks(pipe_blocks const& /*blocks*/)
{
  pipeline_t pipeline;

  /// \todo Bake pipe blocks into a pipeline.

  return pipeline;
}

}
<commit_msg>Add skeleton visitor for the pipeline blocks<commit_after>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "load_pipe.h"

#include "pipe_declaration_types.h"

#include <vistk/pipeline/config.h>
#include <vistk/pipeline/process.h>

#include <boost/tuple/tuple.hpp>
#include <boost/variant.hpp>

#include <utility>
#include <vector>

/**
 * \file pipe_bakery.cxx
 *
 * \brief Implementation of baking a pipeline.
 */

namespace vistk
{

class VISTK_PIPELINE_UTIL_NO_EXPORT pipe_bakery
  : public boost::static_visitor<>
{
  public:
    pipe_bakery();
    ~pipe_bakery();

    void operator () (config_pipe_block const& config_block);
    void operator () (process_pipe_block const& process_block);
    void operator () (connect_pipe_block const& connect_block);
    void operator () (group_pipe_block const& group_block);

    /**
     * \note We do *not* want std::map for the groupings. With a map, we may
     * hide errors in the blocks (setting ro values, duplicate process names,
     * etc.)
     */

    typedef std::pair<config_provider_t, config::value_t> provider_request_t;
    typedef boost::variant<config::value_t, provider_request_t> config_reference_t;
    typedef boost::tuple<config_reference_t, bool> config_info_t;
    typedef std::pair<config::key_t, config_info_t> config_decl_t;
    typedef std::vector<config_decl_t> config_decls_t;

    typedef std::pair<process::name_t, process_registry::type_t> process_decl_t;
    typedef std::vector<process_decl_t> process_decls_t;

    typedef std::pair<process::port_addr_t, process::port_addr_t> connection_t;
    typedef std::vector<connection_t> connections_t;

    typedef boost::tuple<process::port_t, process::port_flags_t, process::port_addr_t> mapping_t;
    typedef std::vector<mapping_t> mappings_t;
    typedef std::pair<mappings_t, mappings_t> group_info_t;
    typedef std::pair<process::name_t, group_info_t> group_decl_t;
    typedef std::vector<group_decl_t> group_decls_t;

    static config::key_t flatten_keys(config::keys_t const& keys);
    void register_config_value(config::key_t const& root_key, config_value_t const& value);

    config_decls_t m_configs;
    process_decls_t m_processes;
    connections_t m_connections;
    group_decls_t m_groups;
};

pipeline_t
bake_pipe_blocks(pipe_blocks const& /*blocks*/)
{
  pipeline_t pipeline;

  /// \todo Bake pipe blocks into a pipeline.

  return pipeline;
}

pipe_bakery
::pipe_bakery()
{
}

pipe_bakery
::~pipe_bakery()
{
}

void
pipe_bakery
::operator () (config_pipe_block const& config_block)
{
  /// \todo Implement.
}

void
pipe_bakery
::operator () (process_pipe_block const& process_block)
{
  /// \todo Implement.
}

void
pipe_bakery
::operator () (connect_pipe_block const& connect_block)
{
  /// \todo Implement.
}

void
pipe_bakery
::operator () (group_pipe_block const& group_block)
{
  /// \todo Implement.
}

void
pipe_bakery
::register_config_value(config::key_t const& root_key, config_value_t const& value)
{
  /// \todo Implement.
}

config::key_t
pipe_bakery
::flatten_keys(config::keys_t const& keys)
{
  /// \todo Implement.
}

}
<|endoftext|>


<commit_before>/*
 * Funambol is a mobile platform developed by Funambol, Inc.
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 *
 * This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

#include "base/Log.h"
#include "base/util/utils.h"
#include "base/globalsdef.h"

BEGIN_NAMESPACE

bool saveFile(const char *filename, const char *buffer, size_t len, bool binary)
{
    FILE *f = fopen(filename, "w");

    if(!f)
        return false;

    if (fwrite(buffer, sizeof(char), len, f) != len) {
        fclose(f);
        return false;
    }
    fclose(f);

    return true;
}

bool readFile(const char* path, char **message, size_t *len, bool binary)
{
    FILE *f = NULL;
    size_t msglen=0;
    char *msg=0;
    const char *mode = binary ? "rb" : "r" ;
    struct stat buf;
    bool res = false;

    f = fopen(path, mode);
    if ( !f ) {
        goto done;
    }
    if ( fstat(fileno(f), &buf) ) {
        goto done;
    }

    msglen = buf.st_size;
    msg = new char[msglen+1];
    msg[msglen] = 0;

    *len=fread(msg, sizeof(char), msglen, f);
    if ( ferror(f) || *len < msglen ){
        goto done;
    }

    // Set return parameters
    *message=msg;
    msg = 0;
    res = true;

  done:
    if (f) {
        fclose(f);
    }
    if (msg) {
        delete [] msg;
    }

    return res;
}

char** readDir(char* name, int *count, bool onlyCount) {
    char **entries = NULL;
    *count = 0;

    // count entries
    int total = 0;
    DIR *dir = opendir(name);
    if (dir) {
        struct dirent *entry = readdir(dir);
        while (entry) {
            if (strcmp(entry->d_name, ".") &&
                strcmp(entry->d_name, "..")) {
                total++;
            }
            entry = readdir(dir);
        }

        if (!onlyCount && total) {
            entries = new char *[total];

            rewinddir(dir);
            entry = readdir(dir);
            while (entry && *count < total) {
                if (strcmp(entry->d_name, ".") &&
                    strcmp(entry->d_name, "..")) {
                    entries[*count] = stringdup(entry->d_name);
                    ++*count;
                }
                entry = readdir(dir);
            }
        }
        closedir(dir);
    }

    return entries;
}

unsigned long getFileModTime(const char* name)
{
    struct stat buf;

    return stat(name, &buf) ? 0 :
        buf.st_ctime > buf.st_mtime ? buf.st_ctime :
        buf.st_mtime;
}

bool removeFileInDir(const char* d, const char* fname) {

    char toFind    [512];
    bool ret = false;
    char** totalFiles = NULL;
    int numFiles = 0;

    if (fname) {
        sprintf(toFind, "%s/%s", d, fname);
        if (remove(toFind) != 0) {
            LOG.error("Error deleting the %s file", toFind); ret = true;
        } else {
            LOG.debug("File %s deleted succesfully", toFind);
        }
    }
    else {
        totalFiles = readDir((char*)d, &numFiles, false);
        if (totalFiles && numFiles > 0) {
            for (int i = 0; i < numFiles; i++) {
                sprintf(toFind, "%s/%s", d, totalFiles[i]);
                remove(toFind);
            }
        }
        ret = true;
    }
    if (totalFiles) {
        for (int i = 0; i < numFiles; i++) {
            delete [] totalFiles[i];
        }
        delete [] totalFiles; totalFiles = NULL;
    }

    return ret;
}

/**
 * Creates a folder. TODO: move it to SDK utils
 * @return 0 on success, -1 otherwise.
 */
int createFolder(const char *path) {
    DIR* d = opendir(path);
    int res = 0;
    if (!d) {
        res = mkdir(path, 0777);
    } else {
        closedir(d);
    }
    return res;
}

// TODO: convert to the specified encoding, assuming wc is UTF-8
char* toMultibyte(const WCHAR *wc, const char *encoding)
{
#ifdef USE_WCHAR
    size_t length = wcstombs(NULL, wc, 0) + 1;
    if(length == -1) {
        LOG.error("toMultibyte: invalid string.");
        return strdup("");
    }
    char* ret = new char[length];
    wcstombs(ret, wc, length);

    return ret;
#else
    return stringdup(wc);
#endif
}

// TODO: convert to UTF-8 from the specified encoding
WCHAR* toWideChar(const char *mb, const char *encoding)
{
#ifdef USE_WCHAR
    size_t length = mbstowcs(NULL, mb, 0) + 1;
    if(length == -1) {
        LOG.error("toWideChar: invalid string.");
        return wstrdup(TEXT(""));
    }
    WCHAR* ret = new WCHAR[length];
    mbstowcs(ret, mb, length);

    return ret;
#else
    return stringdup(mb);
#endif
}

#ifdef USE_WCHAR
// FIXME-----------------------------------------------------------------------
//Overloading thread-safe version of wcstok (defined in Linux) to make it
//work like the non-thread safe version available on Windows (same as strtok).
// FIXME: adjust VOCL code to NOT use this but String::split and remove it!!
//-----------------------------------------------------------------------------
WCHAR *wcstok(WCHAR *s, const WCHAR *delim)
{
    static WCHAR *state = 0;
    return ::wcstok(s, delim, &state);
}
#endif

// Implemented using mkstemp() with a template hard-coded
// to /tmp. Because the API of mkTempFileName() cannot return
// an open file, the file has to be closed. This exposes
// the possibility for an attacker to replace the file
// before it is opened again if /tmp has incorrect permissions.
char *mkTempFileName(const char *name)
{
    char *filename = new char[strlen("/tmp/") + strlen(name) + strlen(".XXXXXX") + 1];
    int fd;

    sprintf(filename, "/tmp/%s.XXXXXX", name );
    fd = mkstemp(filename);
    if (fd == -1) {
        delete [] filename;
        return NULL;
    } else {
        close(fd);
        return filename;
    }
}

// check the presence of a file
bool fileExists(const char *pathname) {
    if (pathname) {
        struct stat st;

        memset(&st, 0, sizeof(struct stat));

        if (stat(pathname, &st) < 0) {
            return false;
        }

        return true;
    }

    return false;
}
END_NAMESPACE

<commit_msg>fix wrong return value<commit_after>/*
 * Funambol is a mobile platform developed by Funambol, Inc.
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 *
 * This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

#include "base/Log.h"
#include "base/util/utils.h"
#include "base/globalsdef.h"

BEGIN_NAMESPACE

bool saveFile(const char *filename, const char *buffer, size_t len, bool binary)
{
    FILE *f = fopen(filename, "w");

    if(!f)
        return false;

    if (fwrite(buffer, sizeof(char), len, f) != len) {
        fclose(f);
        return false;
    }
    fclose(f);

    return true;
}

bool readFile(const char* path, char **message, size_t *len, bool binary)
{
    FILE *f = NULL;
    size_t msglen=0;
    char *msg=0;
    const char *mode = binary ? "rb" : "r" ;
    struct stat buf;
    bool res = false;

    f = fopen(path, mode);
    if ( !f ) {
        goto done;
    }
    if ( fstat(fileno(f), &buf) ) {
        goto done;
    }

    msglen = buf.st_size;
    msg = new char[msglen+1];
    msg[msglen] = 0;

    *len=fread(msg, sizeof(char), msglen, f);
    if ( ferror(f) || *len < msglen ){
        goto done;
    }

    // Set return parameters
    *message=msg;
    msg = 0;
    res = true;

  done:
    if (f) {
        fclose(f);
    }
    if (msg) {
        delete [] msg;
    }

    return res;
}

char** readDir(char* name, int *count, bool onlyCount) {
    char **entries = NULL;
    *count = 0;

    // count entries
    int total = 0;
    DIR *dir = opendir(name);
    if (dir) {
        struct dirent *entry = readdir(dir);
        while (entry) {
            if (strcmp(entry->d_name, ".") &&
                strcmp(entry->d_name, "..")) {
                total++;
            }
            entry = readdir(dir);
        }

        if (!onlyCount && total) {
            entries = new char *[total];

            rewinddir(dir);
            entry = readdir(dir);
            while (entry && *count < total) {
                if (strcmp(entry->d_name, ".") &&
                    strcmp(entry->d_name, "..")) {
                    entries[*count] = stringdup(entry->d_name);
                    ++*count;
                }
                entry = readdir(dir);
            }
        }
        closedir(dir);
    }

    return entries;
}

unsigned long getFileModTime(const char* name)
{
    struct stat buf;

    return stat(name, &buf) ? 0 :
        buf.st_ctime > buf.st_mtime ? buf.st_ctime :
        buf.st_mtime;
}

bool removeFileInDir(const char* d, const char* fname) {

    char toFind    [512];
    bool ret = false;
    char** totalFiles = NULL;
    int numFiles = 0;

    if (fname) {
        sprintf(toFind, "%s/%s", d, fname);
        if (remove(toFind) != 0) {
            LOG.error("Error deleting the %s file", toFind);
        } else {
            LOG.debug("File %s deleted succesfully", toFind);
            ret = true;
        }
    }
    else {
        totalFiles = readDir((char*)d, &numFiles, false);
        if (totalFiles && numFiles > 0) {
            for (int i = 0; i < numFiles; i++) {
                sprintf(toFind, "%s/%s", d, totalFiles[i]);
                remove(toFind);
            }
        }
        ret = true;
    }
    if (totalFiles) {
        for (int i = 0; i < numFiles; i++) {
            delete [] totalFiles[i];
        }
        delete [] totalFiles; totalFiles = NULL;
    }

    return ret;
}

/**
 * Creates a folder. TODO: move it to SDK utils
 * @return 0 on success, -1 otherwise.
 */
int createFolder(const char *path) {
    DIR* d = opendir(path);
    int res = 0;
    if (!d) {
        res = mkdir(path, 0777);
    } else {
        closedir(d);
    }
    return res;
}

// TODO: convert to the specified encoding, assuming wc is UTF-8
char* toMultibyte(const WCHAR *wc, const char *encoding)
{
#ifdef USE_WCHAR
    size_t length = wcstombs(NULL, wc, 0) + 1;
    if(length == -1) {
        LOG.error("toMultibyte: invalid string.");
        return strdup("");
    }
    char* ret = new char[length];
    wcstombs(ret, wc, length);

    return ret;
#else
    return stringdup(wc);
#endif
}

// TODO: convert to UTF-8 from the specified encoding
WCHAR* toWideChar(const char *mb, const char *encoding)
{
#ifdef USE_WCHAR
    size_t length = mbstowcs(NULL, mb, 0) + 1;
    if(length == -1) {
        LOG.error("toWideChar: invalid string.");
        return wstrdup(TEXT(""));
    }
    WCHAR* ret = new WCHAR[length];
    mbstowcs(ret, mb, length);

    return ret;
#else
    return stringdup(mb);
#endif
}

#ifdef USE_WCHAR
// FIXME-----------------------------------------------------------------------
//Overloading thread-safe version of wcstok (defined in Linux) to make it
//work like the non-thread safe version available on Windows (same as strtok).
// FIXME: adjust VOCL code to NOT use this but String::split and remove it!!
//-----------------------------------------------------------------------------
WCHAR *wcstok(WCHAR *s, const WCHAR *delim)
{
    static WCHAR *state = 0;
    return ::wcstok(s, delim, &state);
}
#endif

// Implemented using mkstemp() with a template hard-coded
// to /tmp. Because the API of mkTempFileName() cannot return
// an open file, the file has to be closed. This exposes
// the possibility for an attacker to replace the file
// before it is opened again if /tmp has incorrect permissions.
char *mkTempFileName(const char *name)
{
    char *filename = new char[strlen("/tmp/") + strlen(name) + strlen(".XXXXXX") + 1];
    int fd;

    sprintf(filename, "/tmp/%s.XXXXXX", name );
    fd = mkstemp(filename);
    if (fd == -1) {
        delete [] filename;
        return NULL;
    } else {
        close(fd);
        return filename;
    }
}

// check the presence of a file
bool fileExists(const char *pathname) {
    if (pathname) {
        struct stat st;

        memset(&st, 0, sizeof(struct stat));

        if (stat(pathname, &st) < 0) {
            return false;
        }

        return true;
    }

    return false;
}
END_NAMESPACE

<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2015-2019, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once

#include <fg/defines.h>
#include <fg/exception.h>
#include <err_common.hpp>

#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtx/string_cast.hpp>

#include <vector>

static const float BLACK[]   = {0.0f    , 0.0f    , 0.0f    , 1.0f};
static const float GRAY[]    = {0.85f   , 0.85f   , 0.85f   , 1.0f};
static const float WHITE[]   = {1.0f    , 1.0f    , 1.0f    , 1.0f};
static const float AF_BLUE[] = {0.0588f , 0.1137f , 0.2745f , 1.0f};

/* clamp the float to [0-1] range
 *
 * @pValue is the value to be clamped
 */
float clampTo01(const float pValue);

/* Convert forge type enum to OpenGL enum for GL_* type
 *
 * @pValue is the forge type enum
 *
 * @return GL_* typedef for data type
 */
GLenum dtype2gl(const fg::dtype pValue);

/* Convert forge channel format enum to OpenGL enum to indicate color component layout
 *
 * @pValue is the forge type enum
 *
 * @return OpenGL enum indicating color component layout
 */
GLenum ctype2gl(const fg::ChannelFormat pMode);

/* Convert forge channel format enum to OpenGL enum to indicate color component layout
 *
 * This function is used to group color component layout formats based
 * on number of components.
 *
 * @pValue is the forge type enum
 *
 * @return OpenGL enum indicating color component layout
 */
GLenum ictype2gl(const fg::ChannelFormat pMode);

/* Compile OpenGL GLSL vertex and fragment shader sources
 *
 * @pVertShaderSrc is the vertex shader source code string
 * @pFragShaderSrc is the vertex shader source code string
 * @pGeomShaderSrc is the vertex shader source code string
 *
 * @return GLSL program unique identifier for given shader duo
 */
GLuint initShaders(const char* pVertShaderSrc, const char* pFragShaderSrc, const char* pGeomShaderSrc=NULL);

/* Create OpenGL buffer object
 *
 * @pTarget should be either GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER
 * @pSize is the size of the data in bytes
 * @pPtr is the pointer to host data. This can be NULL
 * @pUsage should be either GL_STATIC_DRAW or GL_DYNAMIC_DRAW
 *
 * @return OpenGL buffer object identifier
 */
template<typename T>
GLuint createBuffer(GLenum pTarget, size_t pSize, const T* pPtr, GLenum pUsage)
{
    GLuint retVal = 0;
    glGenBuffers(1, &retVal);
    glBindBuffer(pTarget, retVal);
    glBufferData(pTarget, pSize*sizeof(T), pPtr, pUsage);
    glBindBuffer(pTarget, 0);
    return retVal;
}

#ifdef OS_WIN
/* Get the paths to font files in Windows system directory
 *
 * @pFiles is the output vector to which font file paths are appended to.
 * @pDir is the directory from which font files are looked up
 * @pExt is the target font file extension we are looking for.
 */
void getFontFilePaths(std::vector<std::string>& pFiles,
                      const std::string& pDir,
                      const std::string& pExt);
#endif

/* Convert float value to string with given precision
 *
 * @pVal is the float value whose string representation is requested.
 * @pPrecision is the precision of the float used while converting to string.
 *
 * @return is the string representation of input float value.
 */
std::string toString(const float pVal, const int pPrecision = 2);

/* Get a vertex buffer object for quad that spans the screen
 */
GLuint screenQuadVBO(const int pWindowId);

/* Get a vertex array object that uses screenQuadVBO
 *
 * This vertex array object when bound and rendered, basically
 * draws a rectangle over the entire screen with standard
 * texture coordinates. Use of this vao would be as follows
 *
 *     `glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);`
 */
GLuint screenQuadVAO(const int pWindowId);

/* Print glm::mat4 to std::cout stream */
std::ostream& operator<<(std::ostream&, const glm::mat4&);

/* get the point of the surface of track ball */
glm::vec3 trackballPoint(const float pX, const float pY,
                         const float pWidth, const float pHeight);

namespace opengl
{

typedef unsigned int    uint;
typedef unsigned short  ushort;
typedef unsigned char   uchar;

/* Basic renderable class
 *
 * Any object that is renderable to a window should inherit from this
 * class.
 */
class AbstractRenderable {
    protected:
        /* OpenGL buffer objects */
        GLuint      mVBO;
        GLuint      mCBO;
        GLuint      mABO;
        size_t      mVBOSize;
        size_t      mCBOSize;
        size_t      mABOSize;
        GLfloat     mColor[4];
        GLfloat     mRange[6];
        std::string mLegend;
        bool        mIsPVCOn;
        bool        mIsPVAOn;

    public:
        /* Getter functions for OpenGL buffer objects
         * identifiers and their size in bytes
         *
         *  vbo is for vertices
         *  cbo is for colors of those vertices
         *  abo is for alpha values for those vertices
         */
        GLuint vbo() const { return mVBO; }
        GLuint cbo() { mIsPVCOn = true; return mCBO; }
        GLuint abo() { mIsPVAOn = true; return mABO; }
        size_t vboSize() const { return mVBOSize; }
        size_t cboSize() const { return mCBOSize; }
        size_t aboSize() const { return mABOSize; }

        /* Set color for rendering
         */
        void setColor(const float pRed, const float pGreen,
                      const float pBlue, const float pAlpha) {
            mColor[0] = clampTo01(pRed);
            mColor[1] = clampTo01(pGreen);
            mColor[2] = clampTo01(pBlue);
            mColor[3] = clampTo01(pAlpha);
        }

        /* Get renderable solid color
         */
        void getColor(float& pRed, float& pGreen, float& pBlue, float& pAlpha) {
            pRed    = mColor[0];
            pGreen  = mColor[1];
            pBlue   = mColor[2];
            pAlpha  = mColor[3];
        }

        /* Set legend for rendering
         */
        void setLegend(const char* pLegend) {
            mLegend = std::string(pLegend);
        }

        /* Get legend string
         */
        const std::string& legend() const {
            return mLegend;
        }

        /* Set 3d world coordinate ranges
         *
         * This method is mostly used for charts and related renderables
         */
        void setRanges(const float pMinX, const float pMaxX,
                       const float pMinY, const float pMaxY,
                       const float pMinZ, const float pMaxZ) {
            mRange[0] = pMinX; mRange[1] = pMaxX;
            mRange[2] = pMinY; mRange[3] = pMaxY;
            mRange[4] = pMinZ; mRange[5] = pMaxZ;
        }

        /* virtual function to set colormap, a derviced class might
         * use it or ignore it if it doesnt have a need for color maps.
         */
        virtual void setColorMapUBOParams(const GLuint pUBO, const GLuint pSize) {
        }

        /* render is a pure virtual function.
         *
         * @pWindowId is the window identifier
         * @pX is the X coordinate at which the currently bound viewport begins.
         * @pX is the Y coordinate at which the currently bound viewport begins.
         * @pViewPortWidth is the width of the currently bound viewport.
         * @pViewPortHeight is the height of the currently bound viewport.
         *
         * Any concrete class that inherits AbstractRenderable class needs to
         * implement this method to render their OpenGL objects to
         * the currently bound viewport of the Window bearing identifier pWindowId.
         *
         * @return nothing.
         */
        virtual void render(const int pWindowId,
                            const int pX, const int pY, const int pVPW, const int pVPH,
                            const glm::mat4 &pTransform) = 0;
};

}
<commit_msg>BUGFIX: std::back_inserter needs iterator header in VS2015<commit_after>/*******************************************************
 * Copyright (c) 2015-2019, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once

#include <fg/defines.h>
#include <fg/exception.h>
#include <err_common.hpp>

#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtx/string_cast.hpp>

#include <vector>
#include <iterator>

static const float BLACK[]   = {0.0f    , 0.0f    , 0.0f    , 1.0f};
static const float GRAY[]    = {0.85f   , 0.85f   , 0.85f   , 1.0f};
static const float WHITE[]   = {1.0f    , 1.0f    , 1.0f    , 1.0f};
static const float AF_BLUE[] = {0.0588f , 0.1137f , 0.2745f , 1.0f};

/* clamp the float to [0-1] range
 *
 * @pValue is the value to be clamped
 */
float clampTo01(const float pValue);

/* Convert forge type enum to OpenGL enum for GL_* type
 *
 * @pValue is the forge type enum
 *
 * @return GL_* typedef for data type
 */
GLenum dtype2gl(const fg::dtype pValue);

/* Convert forge channel format enum to OpenGL enum to indicate color component layout
 *
 * @pValue is the forge type enum
 *
 * @return OpenGL enum indicating color component layout
 */
GLenum ctype2gl(const fg::ChannelFormat pMode);

/* Convert forge channel format enum to OpenGL enum to indicate color component layout
 *
 * This function is used to group color component layout formats based
 * on number of components.
 *
 * @pValue is the forge type enum
 *
 * @return OpenGL enum indicating color component layout
 */
GLenum ictype2gl(const fg::ChannelFormat pMode);

/* Compile OpenGL GLSL vertex and fragment shader sources
 *
 * @pVertShaderSrc is the vertex shader source code string
 * @pFragShaderSrc is the vertex shader source code string
 * @pGeomShaderSrc is the vertex shader source code string
 *
 * @return GLSL program unique identifier for given shader duo
 */
GLuint initShaders(const char* pVertShaderSrc, const char* pFragShaderSrc, const char* pGeomShaderSrc=NULL);

/* Create OpenGL buffer object
 *
 * @pTarget should be either GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER
 * @pSize is the size of the data in bytes
 * @pPtr is the pointer to host data. This can be NULL
 * @pUsage should be either GL_STATIC_DRAW or GL_DYNAMIC_DRAW
 *
 * @return OpenGL buffer object identifier
 */
template<typename T>
GLuint createBuffer(GLenum pTarget, size_t pSize, const T* pPtr, GLenum pUsage)
{
    GLuint retVal = 0;
    glGenBuffers(1, &retVal);
    glBindBuffer(pTarget, retVal);
    glBufferData(pTarget, pSize*sizeof(T), pPtr, pUsage);
    glBindBuffer(pTarget, 0);
    return retVal;
}

#ifdef OS_WIN
/* Get the paths to font files in Windows system directory
 *
 * @pFiles is the output vector to which font file paths are appended to.
 * @pDir is the directory from which font files are looked up
 * @pExt is the target font file extension we are looking for.
 */
void getFontFilePaths(std::vector<std::string>& pFiles,
                      const std::string& pDir,
                      const std::string& pExt);
#endif

/* Convert float value to string with given precision
 *
 * @pVal is the float value whose string representation is requested.
 * @pPrecision is the precision of the float used while converting to string.
 *
 * @return is the string representation of input float value.
 */
std::string toString(const float pVal, const int pPrecision = 2);

/* Get a vertex buffer object for quad that spans the screen
 */
GLuint screenQuadVBO(const int pWindowId);

/* Get a vertex array object that uses screenQuadVBO
 *
 * This vertex array object when bound and rendered, basically
 * draws a rectangle over the entire screen with standard
 * texture coordinates. Use of this vao would be as follows
 *
 *     `glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);`
 */
GLuint screenQuadVAO(const int pWindowId);

/* Print glm::mat4 to std::cout stream */
std::ostream& operator<<(std::ostream&, const glm::mat4&);

/* get the point of the surface of track ball */
glm::vec3 trackballPoint(const float pX, const float pY,
                         const float pWidth, const float pHeight);

namespace opengl
{

typedef unsigned int    uint;
typedef unsigned short  ushort;
typedef unsigned char   uchar;

/* Basic renderable class
 *
 * Any object that is renderable to a window should inherit from this
 * class.
 */
class AbstractRenderable {
    protected:
        /* OpenGL buffer objects */
        GLuint      mVBO;
        GLuint      mCBO;
        GLuint      mABO;
        size_t      mVBOSize;
        size_t      mCBOSize;
        size_t      mABOSize;
        GLfloat     mColor[4];
        GLfloat     mRange[6];
        std::string mLegend;
        bool        mIsPVCOn;
        bool        mIsPVAOn;

    public:
        /* Getter functions for OpenGL buffer objects
         * identifiers and their size in bytes
         *
         *  vbo is for vertices
         *  cbo is for colors of those vertices
         *  abo is for alpha values for those vertices
         */
        GLuint vbo() const { return mVBO; }
        GLuint cbo() { mIsPVCOn = true; return mCBO; }
        GLuint abo() { mIsPVAOn = true; return mABO; }
        size_t vboSize() const { return mVBOSize; }
        size_t cboSize() const { return mCBOSize; }
        size_t aboSize() const { return mABOSize; }

        /* Set color for rendering
         */
        void setColor(const float pRed, const float pGreen,
                      const float pBlue, const float pAlpha) {
            mColor[0] = clampTo01(pRed);
            mColor[1] = clampTo01(pGreen);
            mColor[2] = clampTo01(pBlue);
            mColor[3] = clampTo01(pAlpha);
        }

        /* Get renderable solid color
         */
        void getColor(float& pRed, float& pGreen, float& pBlue, float& pAlpha) {
            pRed    = mColor[0];
            pGreen  = mColor[1];
            pBlue   = mColor[2];
            pAlpha  = mColor[3];
        }

        /* Set legend for rendering
         */
        void setLegend(const char* pLegend) {
            mLegend = std::string(pLegend);
        }

        /* Get legend string
         */
        const std::string& legend() const {
            return mLegend;
        }

        /* Set 3d world coordinate ranges
         *
         * This method is mostly used for charts and related renderables
         */
        void setRanges(const float pMinX, const float pMaxX,
                       const float pMinY, const float pMaxY,
                       const float pMinZ, const float pMaxZ) {
            mRange[0] = pMinX; mRange[1] = pMaxX;
            mRange[2] = pMinY; mRange[3] = pMaxY;
            mRange[4] = pMinZ; mRange[5] = pMaxZ;
        }

        /* virtual function to set colormap, a derviced class might
         * use it or ignore it if it doesnt have a need for color maps.
         */
        virtual void setColorMapUBOParams(const GLuint pUBO, const GLuint pSize) {
        }

        /* render is a pure virtual function.
         *
         * @pWindowId is the window identifier
         * @pX is the X coordinate at which the currently bound viewport begins.
         * @pX is the Y coordinate at which the currently bound viewport begins.
         * @pViewPortWidth is the width of the currently bound viewport.
         * @pViewPortHeight is the height of the currently bound viewport.
         *
         * Any concrete class that inherits AbstractRenderable class needs to
         * implement this method to render their OpenGL objects to
         * the currently bound viewport of the Window bearing identifier pWindowId.
         *
         * @return nothing.
         */
        virtual void render(const int pWindowId,
                            const int pX, const int pY, const int pVPW, const int pVPH,
                            const glm::mat4 &pTransform) = 0;
};

}
<|endoftext|>


<commit_before>/*
 * SessionFind.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionFind.hpp"

#include <algorithm>

#include <boost/algorithm/string.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>

#include <core/Exec.hpp>
#include <core/StringUtils.hpp>
#include <core/system/Environment.hpp>
#include <core/system/Process.hpp>
#include <core/system/ShellUtils.hpp>

#include <r/RUtil.hpp>

#include <session/SessionModuleContext.hpp>
#include <session/SessionUserSettings.hpp>
#include <session/projects/SessionProjects.hpp>

using namespace core;

namespace session {
namespace modules {
namespace find {

namespace {

// This must be the same as MAX_COUNT in FindOutputPane.java
const size_t MAX_COUNT = 1000;

// Reflects the current set of Find results that are being
// displayed, in case they need to be re-fetched (i.e. browser
// refresh)
class FindInFilesState : public boost::noncopyable
{
public:

   explicit FindInFilesState() : running_(false)
   {
   }

   std::string handle() const
   {
      return handle_;
   }

   size_t resultCount() const
   {
      return files_.size();
   }

   bool isRunning() const
   {
      return running_;
   }

   bool addResult(const std::string& handle,
                  const json::Array& files,
                  const json::Array& lineNums,
                  const json::Array& contents,
                  const json::Array& matchOns,
                  const json::Array& matchOffs)
   {
      if (handle_.empty())
         handle_ = handle;
      else if (handle_ != handle)
         return false;

      std::copy(files.begin(), files.end(), std::back_inserter(files_));
      std::copy(lineNums.begin(), lineNums.end(), std::back_inserter(lineNums_));
      std::copy(contents.begin(), contents.end(), std::back_inserter(contents_));
      std::copy(matchOns.begin(), matchOns.end(), std::back_inserter(matchOns_));
      std::copy(matchOffs.begin(), matchOffs.end(), std::back_inserter(matchOffs_));
      return true;
   }

   void onFindBegin(const std::string& handle,
                    const std::string& input,
                    const std::string& path,
                    bool asRegex)
   {
      handle_ = handle;
      input_ = input;
      path_ = path;
      regex_ = asRegex;
      running_ = true;
   }

   void onFindEnd(const std::string& handle)
   {
      if (handle_ == handle)
         running_ = false;
   }

   void clear()
   {
      handle_ = std::string();
      files_.clear();
      lineNums_.clear();
      contents_.clear();
      matchOns_.clear();
      matchOffs_.clear();
   }

   Error readFromJson(const json::Object& asJson)
   {
      json::Object results;
      Error error = json::readObject(asJson,
                                     "handle", &handle_,
                                     "input", &input_,
                                     "path", &path_,
                                     "regex", &regex_,
                                     "results", &results,
                                     "running", &running_);
      if (error)
         return error;

      error = json::readObject(results,
                               "file", &files_,
                               "line", &lineNums_,
                               "lineValue", &contents_,
                               "matchOn", &matchOns_,
                               "matchOff", &matchOffs_);
      if (error)
         return error;

      if (files_.size() != lineNums_.size() || files_.size() != contents_.size())
      {
         files_.clear();
         lineNums_.clear();
         contents_.clear();
      }

      return Success();
   }

   json::Object asJson()
   {
      json::Object obj;
      obj["handle"] = handle_;
      obj["input"] = input_;
      obj["path"] = path_;
      obj["regex"] = regex_;

      json::Object results;
      results["file"] = files_;
      results["line"] = lineNums_;
      results["lineValue"] = contents_;
      results["matchOn"] = matchOns_;
      results["matchOff"] = matchOffs_;
      obj["results"] = results;

      obj["running"] = running_;

      return obj;
   }

private:
   std::string handle_;
   std::string input_;
   std::string path_;
   bool regex_;
   json::Array files_;
   json::Array lineNums_;
   json::Array contents_;
   json::Array matchOns_;
   json::Array matchOffs_;
   bool running_;
};

FindInFilesState& findResults()
{
   static FindInFilesState s_findResults;
   return s_findResults;
}

class GrepOperation : public boost::enable_shared_from_this<GrepOperation>
{
public:
   static boost::shared_ptr<GrepOperation> create(const std::string& encoding,
                                                  const FilePath& tempFile)
   {
      return boost::shared_ptr<GrepOperation>(new GrepOperation(encoding,
                                                                tempFile));
   }

private:
   GrepOperation(const std::string& encoding,
                 const FilePath& tempFile)
      : firstDecodeError_(true), encoding_(encoding), tempFile_(tempFile)
   {
      handle_ = core::system::generateUuid(false);
   }

public:
   std::string handle() const
   {
      return handle_;
   }

   core::system::ProcessCallbacks createProcessCallbacks()
   {
      core::system::ProcessCallbacks callbacks;
      callbacks.onContinue = boost::bind(&GrepOperation::onContinue,
                                         shared_from_this(),
                                         _1);
      callbacks.onStdout = boost::bind(&GrepOperation::onStdout,
                                       shared_from_this(),
                                       _1, _2);
      callbacks.onStderr = boost::bind(&GrepOperation::onStderr,
                                       shared_from_this(),
                                       _1, _2);
      callbacks.onExit = boost::bind(&GrepOperation::onExit,
                                     shared_from_this(),
                                     _1);
      return callbacks;
   }

private:
   bool onContinue(const core::system::ProcessOperations& ops) const
   {
      return findResults().isRunning() && findResults().handle() == handle();
   }

   std::string decode(const std::string& encoded)
   {
      if (encoded.empty())
         return encoded;

      std::string decoded;
      Error error = r::util::iconvstr(encoded, encoding_, "UTF-8", true,
                                      &decoded);

      // Log error, but only once per grep operation
      if (error && firstDecodeError_)
      {
         firstDecodeError_ = false;
         LOG_ERROR(error);
      }

      return decoded;
   }

   void processContents(std::string* pContent,
                        json::Array* pMatchOn,
                        json::Array* pMatchOff)
   {
      using namespace boost;

      std::string decodedLine;

      std::string::iterator inputPos = pContent->begin();

      smatch match;
      while (regex_search(std::string(inputPos, pContent->end()), match,
                          regex("\x1B\\[(\\d\\d)?m")))
      {
         std::string match1 = match[1];

         decodedLine.append(decode(
               std::string(inputPos, inputPos + match.position())));

         inputPos += match.position() + match.length();

         size_t charSize;
         Error error = string_utils::utf8Distance(decodedLine.begin(),
                                                  decodedLine.end(),
                                                  &charSize);
         if (error)
            charSize = decodedLine.size();

         if (match1 == "01")
            pMatchOn->push_back(static_cast<int>(charSize));
         else
            pMatchOff->push_back(static_cast<int>(charSize));
      }
      if (inputPos != pContent->end())
         decodedLine.append(decode(std::string(inputPos, pContent->end())));

      if (decodedLine.size() > 300)
      {
         decodedLine = decodedLine.erase(300);
         decodedLine.append("...");
      }

      *pContent = decodedLine;
   }

   void onStdout(const core::system::ProcessOperations& ops, const std::string& data)
   {
      json::Array files;
      json::Array lineNums;
      json::Array contents;
      json::Array matchOns;
      json::Array matchOffs;

      size_t recordsToProcess = MAX_COUNT + 1 - findResults().resultCount();
      if (recordsToProcess < 0)
         recordsToProcess = 0;

      stdOutBuf_.append(data);
      size_t nextLineStart = 0;
      size_t pos = -1;
      while (recordsToProcess &&
             std::string::npos != (pos = stdOutBuf_.find('\n', pos + 1)))
      {
         std::string line = stdOutBuf_.substr(nextLineStart, pos - nextLineStart);
         nextLineStart = pos + 1;

         boost::smatch match;
         if (boost::regex_match(line, match, boost::regex("^((?:[a-zA-Z]:)?[^:]+):(\\d+):(.*)")))
         {
            std::string file = module_context::createAliasedPath(
                  FilePath(string_utils::systemToUtf8(match[1])));

            if (file.find("/.Rproj.user/") != std::string::npos)
               continue;
            if (file.find("/.git/") != std::string::npos)
               continue;
            if (file.find("/.svn/") != std::string::npos)
               continue;

            int lineNum = safe_convert::stringTo<int>(std::string(match[2]), -1);
            std::string lineContents = match[3];
            boost::algorithm::trim(lineContents);
            json::Array matchOn, matchOff;
            processContents(&lineContents, &matchOn, &matchOff);

            files.push_back(file);
            lineNums.push_back(lineNum);
            contents.push_back(lineContents);
            matchOns.push_back(matchOn);
            matchOffs.push_back(matchOff);

            recordsToProcess--;
         }
      }

      if (nextLineStart)
      {
         stdOutBuf_.erase(0, nextLineStart);
      }

      if (files.size() > 0)
      {
         json::Object result;
         result["handle"] = handle();
         json::Object results;
         results["file"] = files;
         results["line"] = lineNums;
         results["lineValue"] = contents;
         results["matchOn"] = matchOns;
         results["matchOff"] = matchOffs;
         result["results"] = results;

         findResults().addResult(handle(),
                                 files,
                                 lineNums,
                                 contents,
                                 matchOns,
                                 matchOffs);

         module_context::enqueClientEvent(
                  ClientEvent(client_events::kFindResult, result));
      }

      if (recordsToProcess <= 0)
         findResults().onFindEnd(handle());
   }

   void onStderr(const core::system::ProcessOperations& ops, const std::string& data)
   {
      LOG_ERROR_MESSAGE("grep: " + data);
   }

   void onExit(int exitCode)
   {
      findResults().onFindEnd(handle());
      module_context::enqueClientEvent(
            ClientEvent(client_events::kFindOperationEnded, handle()));
      if (!tempFile_.empty())
         tempFile_.removeIfExists();
   }

   bool firstDecodeError_;
   std::string encoding_;
   FilePath tempFile_;
   std::string stdOutBuf_;
   std::string handle_;
};

} // namespace

core::Error beginFind(const json::JsonRpcRequest& request,
                      json::JsonRpcResponse* pResponse)
{
   std::string searchString;
   bool asRegex, ignoreCase;
   std::string directory;
   json::Array filePatterns;

   Error error = json::readParams(request.params,
                                  &searchString,
                                  &asRegex,
                                  &ignoreCase,
                                  &directory,
                                  &filePatterns);
   if (error)
      return error;

   core::system::ProcessOptions options;

   core::system::Options childEnv;
   core::system::environment(&childEnv);
   core::system::setenv(&childEnv, "GREP_COLOR", "01");
   core::system::setenv(&childEnv, "GREP_COLORS", "ne:fn=:ln=:se=:mt=01");
#ifdef _WIN32
   core::system::addToPath(
            &childEnv,
            string_utils::utf8ToSystem(
               session::options().gnugrepPath().absolutePath()));
#endif
   options.environment = childEnv;

   // Put the grep pattern in a file
   FilePath tempFile = module_context::tempFile("rs_grep", "txt");
   boost::shared_ptr<std::ostream> pStream;
   error = tempFile.open_w(&pStream);
   if (error)
      return error;
   std::string encoding = projects::projectContext().hasProject() ?
                          projects::projectContext().defaultEncoding() :
                          userSettings().defaultEncoding();
   std::string encodedString;
   error = r::util::iconvstr(searchString,
                             "UTF-8",
                             encoding,
                             false,
                             &encodedString);
   if (error)
   {
      LOG_ERROR(error);
      encodedString = searchString;
   }

   *pStream << encodedString << std::endl;
   pStream.reset(); // release file handle

   boost::shared_ptr<GrepOperation> ptrGrepOp = GrepOperation::create(encoding,
                                                                      tempFile);
   core::system::ProcessCallbacks callbacks =
                                       ptrGrepOp->createProcessCallbacks();

   shell_utils::ShellCommand cmd("grep");
   cmd << "-rHn" << "--binary-files=without-match" << "--color=always";
#ifndef _WIN32
   cmd << "--devices=skip";
#endif

   if (ignoreCase)
      cmd << "-i";

   // Use -f to pass pattern via file, so we don't have to worry about
   // escaping double quotes, etc.
   cmd << "-f";
   cmd << tempFile;
   if (!asRegex)
      cmd << "-F";

   BOOST_FOREACH(json::Value filePattern, filePatterns)
   {
      cmd << "--include=" + filePattern.get_str();
   }

   cmd << shell_utils::EscapeFilesOnly << "--" << shell_utils::EscapeAll;
   cmd << module_context::resolveAliasedPath(directory);

   // Clear existing results
   findResults().clear();

   error = module_context::processSupervisor().runCommand(cmd,
                                                          options,
                                                          callbacks);
   if (error)
      return error;

   findResults().onFindBegin(ptrGrepOp->handle(),
                             searchString,
                             directory,
                             asRegex);
   pResponse->setResult(ptrGrepOp->handle());

   return Success();
}

core::Error stopFind(const json::JsonRpcRequest& request,
                     json::JsonRpcResponse* pResponse)
{
   std::string handle;
   Error error = json::readParams(request.params, &handle);
   if (error)
      return error;

   findResults().onFindEnd(handle);

   return Success();
}

core::Error clearFindResults(const json::JsonRpcRequest& request,
                             json::JsonRpcResponse* pResponse)
{
   findResults().clear();
   return Success();
}

void onSuspend(core::Settings* pSettings)
{
   std::ostringstream os;
   json::write(findResults().asJson(), os);
   pSettings->set("find-in-files-state", os.str());
}

void onResume(const core::Settings& settings)
{
   std::string state = settings.get("find-in-files-state");
   if (!state.empty())
   {
      json::Value stateJson;
      if (!json::parse(state, &stateJson))
      {
         LOG_WARNING_MESSAGE("invalid find results state json");
         return;
      }

      Error error = findResults().readFromJson(stateJson.get_obj());
      if (error)
         LOG_ERROR(error);
   }
}

json::Object findInFilesStateAsJson()
{
   return findResults().asJson();
}

core::Error initialize()
{
   using namespace session::module_context;

   // register suspend handler
   addSuspendHandler(SuspendHandler(onSuspend, onResume));

   // install handlers
   using boost::bind;
   ExecBlock initBlock ;
   initBlock.addFunctions()
      (bind(registerRpcMethod, "begin_find", beginFind))
      (bind(registerRpcMethod, "stop_find", stopFind))
      (bind(registerRpcMethod, "clear_find_results", clearFindResults));
   return initBlock.execute();
}

} // namespace find
} // namespace modules
} // namespace session
<commit_msg>2949: mountain lion grep problem<commit_after>/*
 * SessionFind.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionFind.hpp"

#include <algorithm>

#include <boost/algorithm/string.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>

#include <core/Exec.hpp>
#include <core/StringUtils.hpp>
#include <core/system/Environment.hpp>
#include <core/system/Process.hpp>
#include <core/system/ShellUtils.hpp>

#include <r/RUtil.hpp>

#include <session/SessionModuleContext.hpp>
#include <session/SessionUserSettings.hpp>
#include <session/projects/SessionProjects.hpp>

using namespace core;

namespace session {
namespace modules {
namespace find {

namespace {

// This must be the same as MAX_COUNT in FindOutputPane.java
const size_t MAX_COUNT = 1000;

// Reflects the current set of Find results that are being
// displayed, in case they need to be re-fetched (i.e. browser
// refresh)
class FindInFilesState : public boost::noncopyable
{
public:

   explicit FindInFilesState() : running_(false)
   {
   }

   std::string handle() const
   {
      return handle_;
   }

   size_t resultCount() const
   {
      return files_.size();
   }

   bool isRunning() const
   {
      return running_;
   }

   bool addResult(const std::string& handle,
                  const json::Array& files,
                  const json::Array& lineNums,
                  const json::Array& contents,
                  const json::Array& matchOns,
                  const json::Array& matchOffs)
   {
      if (handle_.empty())
         handle_ = handle;
      else if (handle_ != handle)
         return false;

      std::copy(files.begin(), files.end(), std::back_inserter(files_));
      std::copy(lineNums.begin(), lineNums.end(), std::back_inserter(lineNums_));
      std::copy(contents.begin(), contents.end(), std::back_inserter(contents_));
      std::copy(matchOns.begin(), matchOns.end(), std::back_inserter(matchOns_));
      std::copy(matchOffs.begin(), matchOffs.end(), std::back_inserter(matchOffs_));
      return true;
   }

   void onFindBegin(const std::string& handle,
                    const std::string& input,
                    const std::string& path,
                    bool asRegex)
   {
      handle_ = handle;
      input_ = input;
      path_ = path;
      regex_ = asRegex;
      running_ = true;
   }

   void onFindEnd(const std::string& handle)
   {
      if (handle_ == handle)
         running_ = false;
   }

   void clear()
   {
      handle_ = std::string();
      files_.clear();
      lineNums_.clear();
      contents_.clear();
      matchOns_.clear();
      matchOffs_.clear();
   }

   Error readFromJson(const json::Object& asJson)
   {
      json::Object results;
      Error error = json::readObject(asJson,
                                     "handle", &handle_,
                                     "input", &input_,
                                     "path", &path_,
                                     "regex", &regex_,
                                     "results", &results,
                                     "running", &running_);
      if (error)
         return error;

      error = json::readObject(results,
                               "file", &files_,
                               "line", &lineNums_,
                               "lineValue", &contents_,
                               "matchOn", &matchOns_,
                               "matchOff", &matchOffs_);
      if (error)
         return error;

      if (files_.size() != lineNums_.size() || files_.size() != contents_.size())
      {
         files_.clear();
         lineNums_.clear();
         contents_.clear();
      }

      return Success();
   }

   json::Object asJson()
   {
      json::Object obj;
      obj["handle"] = handle_;
      obj["input"] = input_;
      obj["path"] = path_;
      obj["regex"] = regex_;

      json::Object results;
      results["file"] = files_;
      results["line"] = lineNums_;
      results["lineValue"] = contents_;
      results["matchOn"] = matchOns_;
      results["matchOff"] = matchOffs_;
      obj["results"] = results;

      obj["running"] = running_;

      return obj;
   }

private:
   std::string handle_;
   std::string input_;
   std::string path_;
   bool regex_;
   json::Array files_;
   json::Array lineNums_;
   json::Array contents_;
   json::Array matchOns_;
   json::Array matchOffs_;
   bool running_;
};

FindInFilesState& findResults()
{
   static FindInFilesState s_findResults;
   return s_findResults;
}

class GrepOperation : public boost::enable_shared_from_this<GrepOperation>
{
public:
   static boost::shared_ptr<GrepOperation> create(const std::string& encoding,
                                                  const FilePath& tempFile)
   {
      return boost::shared_ptr<GrepOperation>(new GrepOperation(encoding,
                                                                tempFile));
   }

private:
   GrepOperation(const std::string& encoding,
                 const FilePath& tempFile)
      : firstDecodeError_(true), encoding_(encoding), tempFile_(tempFile)
   {
      handle_ = core::system::generateUuid(false);
   }

public:
   std::string handle() const
   {
      return handle_;
   }

   core::system::ProcessCallbacks createProcessCallbacks()
   {
      core::system::ProcessCallbacks callbacks;
      callbacks.onContinue = boost::bind(&GrepOperation::onContinue,
                                         shared_from_this(),
                                         _1);
      callbacks.onStdout = boost::bind(&GrepOperation::onStdout,
                                       shared_from_this(),
                                       _1, _2);
      callbacks.onStderr = boost::bind(&GrepOperation::onStderr,
                                       shared_from_this(),
                                       _1, _2);
      callbacks.onExit = boost::bind(&GrepOperation::onExit,
                                     shared_from_this(),
                                     _1);
      return callbacks;
   }

private:
   bool onContinue(const core::system::ProcessOperations& ops) const
   {
      return findResults().isRunning() && findResults().handle() == handle();
   }

   std::string decode(const std::string& encoded)
   {
      if (encoded.empty())
         return encoded;

      std::string decoded;
      Error error = r::util::iconvstr(encoded, encoding_, "UTF-8", true,
                                      &decoded);

      // Log error, but only once per grep operation
      if (error && firstDecodeError_)
      {
         firstDecodeError_ = false;
         LOG_ERROR(error);
      }

      return decoded;
   }

   void processContents(std::string* pContent,
                        json::Array* pMatchOn,
                        json::Array* pMatchOff)
   {
      using namespace boost;

      std::string decodedLine;

      std::string::iterator inputPos = pContent->begin();

      smatch match;
      while (regex_search(std::string(inputPos, pContent->end()), match,
                          regex("\x1B\\[(\\d\\d)?m(\x1B\\[K)?")))
      {
         std::string match1 = match[1];

         decodedLine.append(decode(
               std::string(inputPos, inputPos + match.position())));

         inputPos += match.position() + match.length();

         size_t charSize;
         Error error = string_utils::utf8Distance(decodedLine.begin(),
                                                  decodedLine.end(),
                                                  &charSize);
         if (error)
            charSize = decodedLine.size();

         if (match1 == "01")
            pMatchOn->push_back(static_cast<int>(charSize));
         else
            pMatchOff->push_back(static_cast<int>(charSize));
      }
      if (inputPos != pContent->end())
         decodedLine.append(decode(std::string(inputPos, pContent->end())));

      if (decodedLine.size() > 300)
      {
         decodedLine = decodedLine.erase(300);
         decodedLine.append("...");
      }

      *pContent = decodedLine;
   }

   void onStdout(const core::system::ProcessOperations& ops, const std::string& data)
   {
      json::Array files;
      json::Array lineNums;
      json::Array contents;
      json::Array matchOns;
      json::Array matchOffs;

      size_t recordsToProcess = MAX_COUNT + 1 - findResults().resultCount();
      if (recordsToProcess < 0)
         recordsToProcess = 0;

      stdOutBuf_.append(data);
      size_t nextLineStart = 0;
      size_t pos = -1;
      while (recordsToProcess &&
             std::string::npos != (pos = stdOutBuf_.find('\n', pos + 1)))
      {
         std::string line = stdOutBuf_.substr(nextLineStart, pos - nextLineStart);
         nextLineStart = pos + 1;

         boost::smatch match;
         if (boost::regex_match(line, match, boost::regex("^((?:[a-zA-Z]:)?[^:]+):(\\d+):(.*)")))
         {
            std::string file = module_context::createAliasedPath(
                  FilePath(string_utils::systemToUtf8(match[1])));

            if (file.find("/.Rproj.user/") != std::string::npos)
               continue;
            if (file.find("/.git/") != std::string::npos)
               continue;
            if (file.find("/.svn/") != std::string::npos)
               continue;

            int lineNum = safe_convert::stringTo<int>(std::string(match[2]), -1);
            std::string lineContents = match[3];
            boost::algorithm::trim(lineContents);
            json::Array matchOn, matchOff;
            processContents(&lineContents, &matchOn, &matchOff);

            files.push_back(file);
            lineNums.push_back(lineNum);
            contents.push_back(lineContents);
            matchOns.push_back(matchOn);
            matchOffs.push_back(matchOff);

            recordsToProcess--;
         }
      }

      if (nextLineStart)
      {
         stdOutBuf_.erase(0, nextLineStart);
      }

      if (files.size() > 0)
      {
         json::Object result;
         result["handle"] = handle();
         json::Object results;
         results["file"] = files;
         results["line"] = lineNums;
         results["lineValue"] = contents;
         results["matchOn"] = matchOns;
         results["matchOff"] = matchOffs;
         result["results"] = results;

         findResults().addResult(handle(),
                                 files,
                                 lineNums,
                                 contents,
                                 matchOns,
                                 matchOffs);

         module_context::enqueClientEvent(
                  ClientEvent(client_events::kFindResult, result));
      }

      if (recordsToProcess <= 0)
         findResults().onFindEnd(handle());
   }

   void onStderr(const core::system::ProcessOperations& ops, const std::string& data)
   {
      LOG_ERROR_MESSAGE("grep: " + data);
   }

   void onExit(int exitCode)
   {
      findResults().onFindEnd(handle());
      module_context::enqueClientEvent(
            ClientEvent(client_events::kFindOperationEnded, handle()));
      if (!tempFile_.empty())
         tempFile_.removeIfExists();
   }

   bool firstDecodeError_;
   std::string encoding_;
   FilePath tempFile_;
   std::string stdOutBuf_;
   std::string handle_;
};

} // namespace

core::Error beginFind(const json::JsonRpcRequest& request,
                      json::JsonRpcResponse* pResponse)
{
   std::string searchString;
   bool asRegex, ignoreCase;
   std::string directory;
   json::Array filePatterns;

   Error error = json::readParams(request.params,
                                  &searchString,
                                  &asRegex,
                                  &ignoreCase,
                                  &directory,
                                  &filePatterns);
   if (error)
      return error;

   core::system::ProcessOptions options;

   core::system::Options childEnv;
   core::system::environment(&childEnv);
   core::system::setenv(&childEnv, "GREP_COLOR", "01");
   core::system::setenv(&childEnv, "GREP_COLORS", "ne:fn=:ln=:se=:mt=01");
#ifdef _WIN32
   core::system::addToPath(
            &childEnv,
            string_utils::utf8ToSystem(
               session::options().gnugrepPath().absolutePath()));
#endif
   options.environment = childEnv;

   // Put the grep pattern in a file
   FilePath tempFile = module_context::tempFile("rs_grep", "txt");
   boost::shared_ptr<std::ostream> pStream;
   error = tempFile.open_w(&pStream);
   if (error)
      return error;
   std::string encoding = projects::projectContext().hasProject() ?
                          projects::projectContext().defaultEncoding() :
                          userSettings().defaultEncoding();
   std::string encodedString;
   error = r::util::iconvstr(searchString,
                             "UTF-8",
                             encoding,
                             false,
                             &encodedString);
   if (error)
   {
      LOG_ERROR(error);
      encodedString = searchString;
   }

   *pStream << encodedString << std::endl;
   pStream.reset(); // release file handle

   boost::shared_ptr<GrepOperation> ptrGrepOp = GrepOperation::create(encoding,
                                                                      tempFile);
   core::system::ProcessCallbacks callbacks =
                                       ptrGrepOp->createProcessCallbacks();

   shell_utils::ShellCommand cmd("grep");
   cmd << "-rHn" << "--binary-files=without-match" << "--color=always";
#ifndef _WIN32
   cmd << "--devices=skip";
#endif

   if (ignoreCase)
      cmd << "-i";

   // Use -f to pass pattern via file, so we don't have to worry about
   // escaping double quotes, etc.
   cmd << "-f";
   cmd << tempFile;
   if (!asRegex)
      cmd << "-F";

   BOOST_FOREACH(json::Value filePattern, filePatterns)
   {
      cmd << "--include=" + filePattern.get_str();
   }

   cmd << shell_utils::EscapeFilesOnly << "--" << shell_utils::EscapeAll;
   cmd << module_context::resolveAliasedPath(directory);

   // Clear existing results
   findResults().clear();

   error = module_context::processSupervisor().runCommand(cmd,
                                                          options,
                                                          callbacks);
   if (error)
      return error;

   findResults().onFindBegin(ptrGrepOp->handle(),
                             searchString,
                             directory,
                             asRegex);
   pResponse->setResult(ptrGrepOp->handle());

   return Success();
}

core::Error stopFind(const json::JsonRpcRequest& request,
                     json::JsonRpcResponse* pResponse)
{
   std::string handle;
   Error error = json::readParams(request.params, &handle);
   if (error)
      return error;

   findResults().onFindEnd(handle);

   return Success();
}

core::Error clearFindResults(const json::JsonRpcRequest& request,
                             json::JsonRpcResponse* pResponse)
{
   findResults().clear();
   return Success();
}

void onSuspend(core::Settings* pSettings)
{
   std::ostringstream os;
   json::write(findResults().asJson(), os);
   pSettings->set("find-in-files-state", os.str());
}

void onResume(const core::Settings& settings)
{
   std::string state = settings.get("find-in-files-state");
   if (!state.empty())
   {
      json::Value stateJson;
      if (!json::parse(state, &stateJson))
      {
         LOG_WARNING_MESSAGE("invalid find results state json");
         return;
      }

      Error error = findResults().readFromJson(stateJson.get_obj());
      if (error)
         LOG_ERROR(error);
   }
}

json::Object findInFilesStateAsJson()
{
   return findResults().asJson();
}

core::Error initialize()
{
   using namespace session::module_context;

   // register suspend handler
   addSuspendHandler(SuspendHandler(onSuspend, onResume));

   // install handlers
   using boost::bind;
   ExecBlock initBlock ;
   initBlock.addFunctions()
      (bind(registerRpcMethod, "begin_find", beginFind))
      (bind(registerRpcMethod, "stop_find", stopFind))
      (bind(registerRpcMethod, "clear_find_results", clearFindResults));
   return initBlock.execute();
}

} // namespace find
} // namespace modules
} // namespace session
<|endoftext|>


<commit_before>#include <iostream>

int main()
{
    return 0;
}
<commit_msg>Update BindCPU<commit_after>#include <unistd.h>
#ifndef __USE_GNU
#define __USE_GNU   // 为了使用SET_SET()等宏定义，但unistd.h里面好像已经定义了
#endif
#include <sched.h>
#include <stdio.h>

unsigned int systemCpuNum()
{
    return sysconf(_SC_NPROCESSORS_CONF);
}

int main()
{
    unsigned int cpuNum = systemCpuNum();
    printf("Current system has %u CPU(s)\n", cpuNum);

    cpu_set_t cpuSet;
    CPU_ZERO(&cpuSet);

    return 0;
}
<|endoftext|>


<commit_before>/*******************************************************************************/
/* Bela Csound Rendering functions                                             */
/*                                                                           */
/*******************************************************************************/

#include <Bela.h>
#include <csound/csound.hpp>
#include <vector>
#include <sstream>

static int OpenMidiInDevice(CSOUND *csound, void **userData, const char *dev);
static int CloseMidiInDevice(CSOUND *csound, void *userData);
static int ReadMidiData(CSOUND *csound, void *userData, unsigned char *mbuf,
			int nbytes);

struct csChan {
  std::vector<MYFLT> data;
  std::stringstream name;
};

struct csData{
  Csound *csound;
  int blocksize;
  int res;
  int count;
  csChan channel[8];
};

struct CsMIDI {
  Midi midi;
}

csData* gCsData;

bool setup(BelaContext *context, void *userData)
{
  Csound *csound = new Csound();
  const char *csdfile = "my.csd"; /* CSD name */
  int numArgs = 8;
  char *args[] = { "csound", csdfile, "-iadc", "-odac", "-+rtaudio=null",
		   "--realtime", "--daemon", "-Mhw:1,0,0"};

  gCsData  = new csData;
  csound->SetHostImplementedAudioIO(1,0);
  csound>SetHostImplementedMIDIIO(1);
  csound->SetExternalMidiInOpenCallback(OpenMidiInDevice);
  csound->SetExternalMidiReadCallback(ReadMidiData);
  csound->SetExternalMidiInCloseCallback(CloseMidiInDevice);
  gCsData->res = csound->Compile(numArgs, args);
  gCsData->csound = csound;
  gCsData->blocksize =
    csound->GetKsmps()*userData->csound->GetNchnls();
  gCsData->count = 0;

  /* set up the channels */
  for(int i; i < context->analogInChannels; i++) {
    gCsData.channel[i].data.resize(csound->GetKsmps());
    gCsData.channel[i].name << "analogue" << i+1;
  }

  if(gCsData->res != 0) return false;
  else return true;
}

void render(BelaContext *context, void *Data)
{
  csData *userData = gCsData;
  if(gCsData->res == 0) {
    int n,i,k,count, frmcount,blocksize,res;
    MYFLT scal = userData->csound->Get0dBFS();
    MYFLT* audioIn = userData->csound->GetSpin();
    MYFLT* audioOut = userData->csound->GetSpout();
    int nchnls = userData->csound->GetNchnls();
    int chns = nchnls;
    int an_chns = context->analogInChannels;
    CsChan *channel = userData->channel;
    float frm = 0, incr = ((float) context->analogFrames)/context->audioFrames;
    int an_chans = context->analogInChannels;
    count = userData->count;
    blocksize = userData->blocksize;

    /* this is called when Csound is not running */
    if(count < 0) {
      for(n = 0; n < context->audioFrames; n++){
	for(i = 0; i < context->audioOutChannels; i++){
	  audioWrite(context,n,i,0);
	}
      }
      return;
    }

    if(chns > context->audioOutChannels)
      chns = context->audioOutChannels;

    /* this is where Csound is called */
    for(n = 0; n < context->audioFrames; n++, frm+=incr, count+=nchnls){
      if(count == blocksize) {
	/* set the channels */
	for(i = 0; i < an_chns; i++) {
          csound->SetChannel(channel[i].name.str().c_str(),
			     &(channel[i].data[0]));
	}
	/* run csound */
	if((res = userData->csound->PerformKsmps()) == 0) count = 0;
	else {
	  count = -1;
	  break;
	}
      }
      /* read/write audio data */
      for(i = 0; i < chns; i++){
	audioIn[count+i] = audioRead(context,n,i);
	audioWrite(context,n,i,audioOut[count+i]/scal);
      }

      /* read analogue data
         analogue frame pos gets incremented according to the
         ratio analogFrames/audioFrames.
      */
      frmcount = count/nchnls;
      for(i = 0; i < an_chns; i++) {
	k = (int) frm;
        channel[i].data[frmcount] = analogRead(context,k,i);
      }
    }
    gCsData->res = res;
    userData->count = count;
  }
}

void cleanup(BelaContext *context, void *Data)
{
  csData *userData = gCsData;
  delete userData->csound;
  delete userData;
}

/** MIDI Input functions
 */
int OpenMidiInDevice(CSOUND *csound, void **userData, const char *dev) {
  CsMIDI *midiData = new CsMIDI;
  Midi &midi = midiData->midi;
  midi.readFrom(dev);
  midi.enableParser(false);
  *userData = (void *) midiData;
}

int CloseMidiInDevice(CSOUND *csound, void *userData) {
  CsMIDI *midiData = (CsMIDI *) userData;
  delete midiData;
}

int ReadMidiData(CSOUND *csound, void *userData,
                         unsigned char *mbuf, int nbytes) {
  int n = 0;
  CsMIDI *midiData = (CsMIDI *) userData;
  Midi &midi = midiData->midi;

  while((byte = midi.getInput()) >= 0) {
    *mbuf++ = (unsigned char) byte;
    if(++n == nbytes) break;
  }

  return n;
}
<commit_msg>semicolon<commit_after>/*******************************************************************************/
/* Bela Csound Rendering functions                                             */
/*                                                                           */
/*******************************************************************************/

#include <Bela.h>
#include <csound/csound.hpp>
#include <vector>
#include <sstream>

static int OpenMidiInDevice(CSOUND *csound, void **userData, const char *dev);
static int CloseMidiInDevice(CSOUND *csound, void *userData);
static int ReadMidiData(CSOUND *csound, void *userData, unsigned char *mbuf,
			int nbytes);

struct csChan {
  std::vector<MYFLT> data;
  std::stringstream name;
};

struct csData{
  Csound *csound;
  int blocksize;
  int res;
  int count;
  csChan channel[8];
};

struct CsMIDI {
  Midi midi;
};

csData* gCsData;

bool setup(BelaContext *context, void *userData)
{
  Csound *csound = new Csound();
  const char *csdfile = "my.csd"; /* CSD name */
  int numArgs = 8;
  char *args[] = { "csound", csdfile, "-iadc", "-odac", "-+rtaudio=null",
		   "--realtime", "--daemon", "-Mhw:1,0,0"};

  gCsData  = new csData;
  csound->SetHostImplementedAudioIO(1,0);
  csound>SetHostImplementedMIDIIO(1);
  csound->SetExternalMidiInOpenCallback(OpenMidiInDevice);
  csound->SetExternalMidiReadCallback(ReadMidiData);
  csound->SetExternalMidiInCloseCallback(CloseMidiInDevice);
  gCsData->res = csound->Compile(numArgs, args);
  gCsData->csound = csound;
  gCsData->blocksize =
    csound->GetKsmps()*userData->csound->GetNchnls();
  gCsData->count = 0;

  /* set up the channels */
  for(int i; i < context->analogInChannels; i++) {
    gCsData.channel[i].data.resize(csound->GetKsmps());
    gCsData.channel[i].name << "analogue" << i+1;
  }

  if(gCsData->res != 0) return false;
  else return true;
}

void render(BelaContext *context, void *Data)
{
  csData *userData = gCsData;
  if(gCsData->res == 0) {
    int n,i,k,count, frmcount,blocksize,res;
    MYFLT scal = userData->csound->Get0dBFS();
    MYFLT* audioIn = userData->csound->GetSpin();
    MYFLT* audioOut = userData->csound->GetSpout();
    int nchnls = userData->csound->GetNchnls();
    int chns = nchnls;
    int an_chns = context->analogInChannels;
    CsChan *channel = userData->channel;
    float frm = 0, incr = ((float) context->analogFrames)/context->audioFrames;
    int an_chans = context->analogInChannels;
    count = userData->count;
    blocksize = userData->blocksize;

    /* this is called when Csound is not running */
    if(count < 0) {
      for(n = 0; n < context->audioFrames; n++){
	for(i = 0; i < context->audioOutChannels; i++){
	  audioWrite(context,n,i,0);
	}
      }
      return;
    }

    if(chns > context->audioOutChannels)
      chns = context->audioOutChannels;

    /* this is where Csound is called */
    for(n = 0; n < context->audioFrames; n++, frm+=incr, count+=nchnls){
      if(count == blocksize) {
	/* set the channels */
	for(i = 0; i < an_chns; i++) {
          csound->SetChannel(channel[i].name.str().c_str(),
			     &(channel[i].data[0]));
	}
	/* run csound */
	if((res = userData->csound->PerformKsmps()) == 0) count = 0;
	else {
	  count = -1;
	  break;
	}
      }
      /* read/write audio data */
      for(i = 0; i < chns; i++){
	audioIn[count+i] = audioRead(context,n,i);
	audioWrite(context,n,i,audioOut[count+i]/scal);
      }

      /* read analogue data
         analogue frame pos gets incremented according to the
         ratio analogFrames/audioFrames.
      */
      frmcount = count/nchnls;
      for(i = 0; i < an_chns; i++) {
	k = (int) frm;
        channel[i].data[frmcount] = analogRead(context,k,i);
      }
    }
    gCsData->res = res;
    userData->count = count;
  }
}

void cleanup(BelaContext *context, void *Data)
{
  csData *userData = gCsData;
  delete userData->csound;
  delete userData;
}

/** MIDI Input functions
 */
int OpenMidiInDevice(CSOUND *csound, void **userData, const char *dev) {
  CsMIDI *midiData = new CsMIDI;
  Midi &midi = midiData->midi;
  midi.readFrom(dev);
  midi.enableParser(false);
  *userData = (void *) midiData;
}

int CloseMidiInDevice(CSOUND *csound, void *userData) {
  CsMIDI *midiData = (CsMIDI *) userData;
  delete midiData;
}

int ReadMidiData(CSOUND *csound, void *userData,
                         unsigned char *mbuf, int nbytes) {
  int n = 0;
  CsMIDI *midiData = (CsMIDI *) userData;
  Midi &midi = midiData->midi;

  while((byte = midi.getInput()) >= 0) {
    *mbuf++ = (unsigned char) byte;
    if(++n == nbytes) break;
  }

  return n;
}
<|endoftext|>