<commit_before>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file test_main.hxx
 *
 * Include this file into your unittest to define the necessary symbols and
 * main function.
 *
 * @author Balazs Racz
 * @date 3 Nov 2013
 */

#ifdef _UTILS_TEST_MAIN_HXX_
#error Only ever include test_main into the main unittest file.
#else
#define _UTILS_TEST_MAIN_HXX_

#include "nmranet_config.h"

#include <stdio.h>
#include <stdarg.h>
#include <string>
#include "gtest/gtest.h"
#include "gmock/gmock.h"

#include "os/os.h"
#include "utils/pipe.hxx"
#include "nmranet_can.h"

/** Conveninence utility to do a printf directly into a C++ string. */
string StringPrintf(const char* format, ...) {
  static const int kBufSize = 1000;
  char buffer[kBufSize];
  va_list ap;

  va_start(ap, format);
  int n = vsnprintf(buffer, kBufSize, format, ap);
  va_end(ap);
  HASSERT(n >= 0);
  if (n < kBufSize) {
    return string(buffer, n);
  }
  string ret(n + 1, 0);
  va_start(ap, format);
  n = vsnprintf(&ret[0], ret.size(), format, ap);
  va_end(ap);
  HASSERT(n >= 0);
  ret.resize(n);
  return ret;
}

int appl_main(int argc, char* argv[]) {
  testing::InitGoogleMock(&argc, argv);
  return RUN_ALL_TESTS();
}

ThreadExecutor g_executor("async_exec", 0, 2000);
DEFINE_PIPE(can_pipe0, &g_executor, sizeof(struct can_frame));

void WaitForMainExecutor() {
  while (!g_executor.empty()) {
    usleep(100);
  }
}

extern "C" {

const char *nmranet_manufacturer = "Stuart W. Baker";
const char *nmranet_hardware_rev = "N/A";
const char *nmranet_software_rev = "0.1";

const size_t main_stack_size = 2560;
const size_t ALIAS_POOL_SIZE = 2;
const size_t DOWNSTREAM_ALIAS_CACHE_SIZE = 2;
const size_t UPSTREAM_ALIAS_CACHE_SIZE = 2;
const size_t DATAGRAM_POOL_SIZE = 10;
const size_t CAN_RX_BUFFER_SIZE = 1;
const size_t CAN_TX_BUFFER_SIZE = 32;
const size_t SERIAL_RX_BUFFER_SIZE = 16;
const size_t SERIAL_TX_BUFFER_SIZE = 16;
const size_t DATAGRAM_THREAD_STACK_SIZE = 512;
const size_t CAN_IF_READ_THREAD_STACK_SIZE = 1024;
const size_t COMPAT_EVENT_THREAD_STACK_SIZE = 1024;
const size_t WRITE_FLOW_THREAD_STACK_SIZE = 1024;

}

#endif // _UTILS_TEST_MAIN_HXX_
<commit_msg>Moves StringPrintF into the testing namespace.<commit_after>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file test_main.hxx
 *
 * Include this file into your unittest to define the necessary symbols and
 * main function.
 *
 * @author Balazs Racz
 * @date 3 Nov 2013
 */

#ifdef _UTILS_TEST_MAIN_HXX_
#error Only ever include test_main into the main unittest file.
#else
#define _UTILS_TEST_MAIN_HXX_

#include "nmranet_config.h"

#include <stdio.h>
#include <stdarg.h>
#include <string>
#include "gtest/gtest.h"
#include "gmock/gmock.h"

#include "os/os.h"
#include "utils/pipe.hxx"
#include "nmranet_can.h"

namespace testing {
/** Conveninence utility to do a printf directly into a C++ string. */
string StringPrintf(const char* format, ...) {
  static const int kBufSize = 1000;
  char buffer[kBufSize];
  va_list ap;

  va_start(ap, format);
  int n = vsnprintf(buffer, kBufSize, format, ap);
  va_end(ap);
  HASSERT(n >= 0);
  if (n < kBufSize) {
    return string(buffer, n);
  }
  string ret(n + 1, 0);
  va_start(ap, format);
  n = vsnprintf(&ret[0], ret.size(), format, ap);
  va_end(ap);
  HASSERT(n >= 0);
  ret.resize(n);
  return ret;
}
}

using testing::StringPrintf;

int appl_main(int argc, char* argv[]) {
  testing::InitGoogleMock(&argc, argv);
  return RUN_ALL_TESTS();
}

ThreadExecutor g_executor("async_exec", 0, 2000);
DEFINE_PIPE(can_pipe0, &g_executor, sizeof(struct can_frame));

void WaitForMainExecutor() {
  while (!g_executor.empty()) {
    usleep(100);
  }
}

extern "C" {

const char *nmranet_manufacturer = "Stuart W. Baker";
const char *nmranet_hardware_rev = "N/A";
const char *nmranet_software_rev = "0.1";

const size_t main_stack_size = 2560;
const size_t ALIAS_POOL_SIZE = 2;
const size_t DOWNSTREAM_ALIAS_CACHE_SIZE = 2;
const size_t UPSTREAM_ALIAS_CACHE_SIZE = 2;
const size_t DATAGRAM_POOL_SIZE = 10;
const size_t CAN_RX_BUFFER_SIZE = 1;
const size_t CAN_TX_BUFFER_SIZE = 32;
const size_t SERIAL_RX_BUFFER_SIZE = 16;
const size_t SERIAL_TX_BUFFER_SIZE = 16;
const size_t DATAGRAM_THREAD_STACK_SIZE = 512;
const size_t CAN_IF_READ_THREAD_STACK_SIZE = 1024;
const size_t COMPAT_EVENT_THREAD_STACK_SIZE = 1024;
const size_t WRITE_FLOW_THREAD_STACK_SIZE = 1024;

}

#endif // _UTILS_TEST_MAIN_HXX_
<|endoftext|>


<commit_before>/*
 * MouseFlags.h
 *
 * Copyright (C) 2010 by VISUS (Universitaet Stuttgart).
 * Alle Rechte vorbehalten.
 */

#include "stdafx.h"
#include "mmcore/view/MouseFlags.h"

/*
 * megamol::core::view::MOUSEFLAG_BUTTON_LEFT_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_LEFT_DOWN = 0x00000001;

/*
 * megamol::core::view::MOUSEFLAG_BUTTON_RIGHT_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_RIGHT_DOWN = 0x00000002;

/**
 * megamol::core::view::MOUSEFLAG_BUTTON_MIDDLE_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_MIDDLE_DOWN = 0x00000004;

/**
 * megamol::core::view::MOUSEFLAG_BUTTON_LEFT_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_LEFT_CHANGED = 0x00000008;

/**
 * megamol::core::view::MOUSEFLAG_BUTTON_RIGHT_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_RIGHT_CHANGED = 0x00000010;

/**
 * megamol::core::view::MOUSEFLAG_BUTTON_MIDDLE_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_MIDDLE_CHANGED = 0x00000020;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_SHIFT_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_SHIFT_DOWN = 0x00000040;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_CTRL_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_CTRL_DOWN = 0x00000080;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_ALT_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_ALT_DOWN = 0x00000100;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_SHIFT_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_SHIFT_CHANGED = 0x00000200;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_CTRL_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_CTRL_CHANGED = 0x00000400;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_ALT_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_ALT_CHANGED = 0x00000800;

/*
 * megamol::core::view::MouseFlagsResetAllChanged
 */
void MEGAMOLCORE_API megamol::core::view::MouseFlagsResetAllChanged(MouseFlags& flags) {
    flags = flags & (MOUSEFLAG_BUTTON_LEFT_DOWN | MOUSEFLAG_BUTTON_RIGHT_DOWN
        | MOUSEFLAG_BUTTON_MIDDLE_DOWN | MOUSEFLAG_MODKEY_SHIFT_DOWN | MOUSEFLAG_MODKEY_CTRL_DOWN
        | MOUSEFLAG_MODKEY_ALT_DOWN);
}

/*
 * megamol::core::view::MouseFlagsSetFlag
 */
void MEGAMOLCORE_API megamol::core::view::MouseFlagsSetFlag(MouseFlags& flags, MouseFlags flag, bool set) {
    bool changed = false;
    switch (flag) {
        case MOUSEFLAG_BUTTON_LEFT_DOWN:
        case MOUSEFLAG_BUTTON_RIGHT_DOWN:
        case MOUSEFLAG_BUTTON_MIDDLE_DOWN:
        case MOUSEFLAG_MODKEY_SHIFT_DOWN:
        case MOUSEFLAG_MODKEY_CTRL_DOWN:
        case MOUSEFLAG_MODKEY_ALT_DOWN:
            if (((flags & flag) == flag) != set) {
                changed = true;
            }
            if (set) {
                flags |= flag;
            } else {
                flags &= ~flag;
            }
            break;
        default:
            // intentionally empty
            break;
    }
    if (changed) {
        switch (flag) {
            case MOUSEFLAG_BUTTON_LEFT_DOWN:
                flags |= MOUSEFLAG_BUTTON_LEFT_CHANGED;
                break;
            case MOUSEFLAG_BUTTON_RIGHT_DOWN:
                flags |= MOUSEFLAG_BUTTON_LEFT_CHANGED;
                break;
            case MOUSEFLAG_BUTTON_MIDDLE_DOWN:
                flags |= MOUSEFLAG_BUTTON_MIDDLE_CHANGED;
                break;
            case MOUSEFLAG_MODKEY_SHIFT_DOWN:
                flags |= MOUSEFLAG_MODKEY_SHIFT_CHANGED;
                break;
            case MOUSEFLAG_MODKEY_CTRL_DOWN:
                flags |= MOUSEFLAG_MODKEY_CTRL_CHANGED;
                break;
            case MOUSEFLAG_MODKEY_ALT_DOWN:
                flags |= MOUSEFLAG_MODKEY_ALT_CHANGED;
                break;
            default:
                // intentionally empty
                break;
        }
    }
}
<commit_msg>Fixed copy&paste error. MOUSEFLAG_BUTTON_RIGHT_CHANGED was not set correctly.<commit_after>/*
 * MouseFlags.h
 *
 * Copyright (C) 2010 by VISUS (Universitaet Stuttgart).
 * Alle Rechte vorbehalten.
 */

#include "stdafx.h"
#include "mmcore/view/MouseFlags.h"

/*
 * megamol::core::view::MOUSEFLAG_BUTTON_LEFT_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_LEFT_DOWN = 0x00000001;

/*
 * megamol::core::view::MOUSEFLAG_BUTTON_RIGHT_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_RIGHT_DOWN = 0x00000002;

/**
 * megamol::core::view::MOUSEFLAG_BUTTON_MIDDLE_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_MIDDLE_DOWN = 0x00000004;

/**
 * megamol::core::view::MOUSEFLAG_BUTTON_LEFT_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_LEFT_CHANGED = 0x00000008;

/**
 * megamol::core::view::MOUSEFLAG_BUTTON_RIGHT_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_RIGHT_CHANGED = 0x00000010;

/**
 * megamol::core::view::MOUSEFLAG_BUTTON_MIDDLE_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_BUTTON_MIDDLE_CHANGED = 0x00000020;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_SHIFT_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_SHIFT_DOWN = 0x00000040;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_CTRL_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_CTRL_DOWN = 0x00000080;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_ALT_DOWN
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_ALT_DOWN = 0x00000100;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_SHIFT_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_SHIFT_CHANGED = 0x00000200;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_CTRL_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_CTRL_CHANGED = 0x00000400;

/**
 * megamol::core::view::MOUSEFLAG_MODKEY_ALT_CHANGED
 */
const megamol::core::view::MouseFlags
megamol::core::view::MOUSEFLAG_MODKEY_ALT_CHANGED = 0x00000800;

/*
 * megamol::core::view::MouseFlagsResetAllChanged
 */
void MEGAMOLCORE_API megamol::core::view::MouseFlagsResetAllChanged(MouseFlags& flags) {
    flags = flags & (MOUSEFLAG_BUTTON_LEFT_DOWN | MOUSEFLAG_BUTTON_RIGHT_DOWN
        | MOUSEFLAG_BUTTON_MIDDLE_DOWN | MOUSEFLAG_MODKEY_SHIFT_DOWN | MOUSEFLAG_MODKEY_CTRL_DOWN
        | MOUSEFLAG_MODKEY_ALT_DOWN);
}

/*
 * megamol::core::view::MouseFlagsSetFlag
 */
void MEGAMOLCORE_API megamol::core::view::MouseFlagsSetFlag(MouseFlags& flags, MouseFlags flag, bool set) {
    bool changed = false;
    switch (flag) {
        case MOUSEFLAG_BUTTON_LEFT_DOWN:
        case MOUSEFLAG_BUTTON_RIGHT_DOWN:
        case MOUSEFLAG_BUTTON_MIDDLE_DOWN:
        case MOUSEFLAG_MODKEY_SHIFT_DOWN:
        case MOUSEFLAG_MODKEY_CTRL_DOWN:
        case MOUSEFLAG_MODKEY_ALT_DOWN:
            if (((flags & flag) == flag) != set) {
                changed = true;
            }
            if (set) {
                flags |= flag;
            } else {
                flags &= ~flag;
            }
            break;
        default:
            // intentionally empty
            break;
    }
    if (changed) {
        switch (flag) {
            case MOUSEFLAG_BUTTON_LEFT_DOWN:
                flags |= MOUSEFLAG_BUTTON_LEFT_CHANGED;
                break;
            case MOUSEFLAG_BUTTON_RIGHT_DOWN:
                flags |= MOUSEFLAG_BUTTON_RIGHT_CHANGED;
                break;
            case MOUSEFLAG_BUTTON_MIDDLE_DOWN:
                flags |= MOUSEFLAG_BUTTON_MIDDLE_CHANGED;
                break;
            case MOUSEFLAG_MODKEY_SHIFT_DOWN:
                flags |= MOUSEFLAG_MODKEY_SHIFT_CHANGED;
                break;
            case MOUSEFLAG_MODKEY_CTRL_DOWN:
                flags |= MOUSEFLAG_MODKEY_CTRL_CHANGED;
                break;
            case MOUSEFLAG_MODKEY_ALT_DOWN:
                flags |= MOUSEFLAG_MODKEY_ALT_CHANGED;
                break;
            default:
                // intentionally empty
                break;
        }
    }
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <opencv2/opencv.hpp>

int main(void){
    CvCapture* capture = cvCaptureFromAVI("infile.avi");
    //Capturing a frame:
    printf("wow we didn't crash horribly (well not yet anyway)\n");
    IplImage* img = 0;
    if(!cvGrabFrame(capture)){              // capture a frame
        printf("Could not grab a frame\n\7");
        exit(0);
    }

    img=cvRetrieveFrame(capture);// retrieve the captured frame

}
<commit_msg>building works now, we had two executables called test is all<commit_after>#include <stdio.h>
#include <opencv2/opencv.hpp>

int main(void){
    CvCapture* capture = cvCaptureFromAVI("~/not_bouy.avi");
    //Capturing a frame:
    printf("wow we didn't crash horribly (well not yet anyway)\n");
    IplImage* img =0;
    if(!cvGrabFrame(capture)){              // capture a frame
        printf("Could not grab a frame\n\7");
        exit(0);
    }

    img=cvRetrieveFrame(capture);// retrieve the captured frame

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * cclive 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 General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#ifndef HAVE_PTRDIFF_T
#error Cannot compile without ptrdiff_t support
#endif

#include <iostream>
#include <vector>
#include <iterator>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <tr1/memory>
#include <cstring>
#include <cerrno>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif

#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif

#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif

#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif

#include "hosthandler.h"
#include "hostfactory.h"
#include "macros.h"
#include "opts.h"
#include "curl.h"
#include "exec.h"
#include "retry.h"
#include "log.h"
#include "app.h"

#if defined (SIGWINCH) && defined (TIOCGWINSZ)
#define WITH_RESIZE
#endif

#define SHP std::tr1::shared_ptr

// singleton instances
static SHP<OptionsMgr> __optsmgr (new OptionsMgr);
static SHP<CurlMgr>    __curlmgr (new CurlMgr);
static SHP<ExecMgr>    __execmgr (new ExecMgr);
static SHP<RetryMgr>   __retrymgr(new RetryMgr);
static SHP<LogMgr>     __logmgr  (new LogMgr);

extern void handle_sigwinch(int); // src/progress.cpp

App::~App() {
}

void
App::main(const int& argc, char * const *argv) {
    optsmgr.init(argc, argv);
    logmgr.init(); // apply --quiet
    curlmgr.init();
}

static void
printVideo(const VideoProperties& props) {
    logmgr.cout()
        << "file: "
        << props.getFilename()
        << "  "
        << std::setprecision(1)
        << _TOMB(props.getLength())
        << "M  ["
        << props.getContentType()
        << "]"
        << std::endl;
}

static void
printCSV(const VideoProperties& props) {
    std::cout.setf(std::ios::fixed);
    std::cout.unsetf(std::ios::showpoint);
    std::cout
        << "csv:\""
        << props.getFilename()
        << "\",\""
        << std::setprecision(0)
        << props.getLength()
        << "\",\""
        << props.getLink()
        << "\""
        << std::endl;
}

typedef CurlMgr::FetchException FetchError;

static void
fetchPage(SHP<HostHandler> handler,
          const std::string& url,
          const bool& reset=false)
{
    if (reset)
        retrymgr.reset();
    try   { handler->parsePage(url); }
    catch (const FetchError& x) {
        retrymgr.handle(x);
        fetchPage(handler, url);
    }
    logmgr.resetReturnCode();
}

static void
fetchFile(VideoProperties& props, const bool& reset=false) {
    if (reset)
        retrymgr.reset();
    try   { curlmgr.fetchToFile(props); }
    catch (const FetchError& x) {
        retrymgr.setRetryUntilRetrievedFlag();
        retrymgr.handle(x);
        fetchFile(props);
    }
    logmgr.resetReturnCode();
}

static void
queryLength(VideoProperties& props, const bool& reset=false) {
    if (reset)
        retrymgr.reset();
    try   { curlmgr.queryFileLength(props); }
    catch (const FetchError& x) {
        retrymgr.handle(x);
        queryLength(props);
    }
    logmgr.resetReturnCode();
}

static void
processVideo(VideoProperties& props) {
    queryLength(props, true);

    const Options opts =
        optsmgr.getOptions();

    if (opts.no_extract_given)
        printVideo(props);
    else if (opts.emit_csv_given)
        printCSV(props);
    else if (opts.stream_pass_given)
        execmgr.passStream(props);
    else
    {
        if (opts.print_fname_given)
            printVideo(props);

        fetchFile(props, true);
    }
}

static void
reportNotice() {
    static const char report_notice[] =
    ":: A bug? If you think so, and you can reproduce the above,\n"
    ":: consider submitting it to the issue tracker:\n"
    "::     <http://code.google.com/p/cclive/issues/>\n";
    logmgr.cerr() << report_notice << std::endl;
}

typedef HostHandlerFactory::UnsupportedHostException NoSupport;
typedef HostHandler::ParseException                  ParseError;
typedef VideoProperties::NothingToDoException        NothingTodo;

static void
handleURL(const std::string& url) {
    try
    {
        SHP<HostHandler> handler =
            HostHandlerFactory::createHandler(url);

        fetchPage(handler, url, true);

        VideoProperties props =
            handler->getVideoProperties();

        try { processVideo(props); }
        catch (const FileOpenException& x)
            { logmgr.cerr(x, false); }
        catch (const NothingTodo& x)
            { logmgr.cerr(x, false); }

        if (optsmgr.getOptions().exec_run_given)
            execmgr.append(props);
    }
    catch (const NoSupport& x)   { logmgr.cerr(x, false); }
    catch (const FetchError& x)  { /* printed by retrymgr.handle already */ }
    catch (const ParseError& x)  { logmgr.cerr(x, false); reportNotice(); }
}

typedef std::vector<std::string> STRV;

void
App::run() {
    const Options opts = optsmgr.getOptions();

    if (opts.version_given) {
        printVersion();
        return;
    }

    if (opts.hosts_given) {
        HostHandlerFactory::printHosts();
        return;
    }

    if (opts.regexp_given) {
        std::string empty;
        if (!Util::perlMatch(opts.regexp_arg, empty)) {
            throw RuntimeException(CCLIVE_OPTARG,
                "--regexp: expected perl-like\n"
                "error: /pattern/(gi) regular expression");
        }
    }

    if (opts.substitute_given) {
        std::string empty; // Validate regexp only (empty string).
        if (!Util::perlSubstitute(opts.substitute_arg, empty)) {
            throw RuntimeException(CCLIVE_OPTARG,
                "--substitute: expected perl-like\n"
                "error: s/old/new/(gi) substitution");
        }
    }

    execmgr.verifyExecArgument();

#if !defined(HAVE_FORK) || !defined(HAVE_WORKING_FORK)
    if (opts.stream_exec_given) {
        logmgr.cerr()
            << "warn: this system does not have a working fork.\n"
            << "warn: --stream-exec ignored."
            << std::endl;
    }
#endif

    STRV tokens;

    typedef unsigned int _uint;

    if (!opts.inputs_num)
        tokens = parseInput();
    else {
        for (register _uint i=0; i<opts.inputs_num; ++i)
            tokens.push_back(opts.inputs[i]);
    }

    for (STRV::iterator iter=tokens.begin();
        iter != tokens.end();
        ++iter)
    {
        // Convert alternate domain link to youtube.com page link.
        Util::nocookieToYoutube(*iter);

        // Convert any embed type URLs to video page links.
        Util::embedToPage(*iter);

        // Convert last.fm video link to Youtube page link.
        if ((*iter).find("last.fm") != std::string::npos)
            Util::lastfmToYoutube(*iter);
    }

    logmgr.cout().setf(std::ios::fixed);
#ifdef WITH_RESIZE
    signal(SIGWINCH, handle_sigwinch);
#endif
    if (opts.background_given)
        daemonize();

    std::for_each(tokens.begin(), tokens.end(), handleURL);

    if (opts.exec_run_given)
        execmgr.playQueue();
}

STRV
App::parseInput() {
    std::string input;

    char ch;
    while (std::cin.get(ch))
        input += ch;

    std::istringstream iss(input);
    STRV tokens;

    std::copy(
        std::istream_iterator<std::string >(iss),
        std::istream_iterator<std::string >(),
        std::back_inserter<STRV>(tokens)
    );

    return tokens;
}

void
App::printVersion() {
static const char copyr_notice[] =
"Copyright (C) 2009 Toni Gundogdu. "
"License GPLv3+: GNU GPL version 3 or later\n"
"This is free software; see the  source for  copying conditions.  There is NO\n"
"warranty;  not even for MERCHANTABILITY or FITNESS FOR A  PARTICULAR PURPOSE.";

    const curl_version_info_data *c =
        curl_version_info(CURLVERSION_NOW);

    std::cout
        << CMDLINE_PARSER_PACKAGE       << " version "
        << CMDLINE_PARSER_VERSION       << " with libcurl version "
        << c->version                   << "  ["
#ifdef BUILD_DATE
        << BUILD_DATE << "-"
#endif
        << CANONICAL_TARGET             << "]\n"
        << copyr_notice                 << "\n"
        << "\n  Locale/codeset  : "     << optsmgr.getLocale()
        << "\n  Config          : "     << optsmgr.getPath()
        << "\n  Features        : pcre "
#ifdef HAVE_ICONV
        << "iconv "
#endif
#ifdef WITH_RESIZE
        << "sigwinch "
#endif
        << "\n  Home            : "     << "<http://cclive.googlecode.com/>"
        << std::endl;
}

void
App::daemonize() {
#if defined(HAVE_FORK) && defined(HAVE_WORKING_FORK)
#ifdef HAVE_GETCWD
    char path[PATH_MAX];
    path[0] = '\0';
    getcwd(path, sizeof(path));
#endif

    pid_t pid = fork();

    if (pid < 0) {
#ifdef HAVE_STRERROR
        fprintf(stderr, "error: fork: %s\n", strerror(errno));
#else
        perror("fork");
#endif
        exit (CCLIVE_SYSTEM);
    }
    else if (pid != 0) {
        std::cout
            << "Continuing in background, pid "
            << static_cast<long>(pid)
            << ".\nOutput will be written to \""
            << logmgr.getFilename()
            << "\"."
            << std::endl;
        exit (CCLIVE_OK);
    }
    setsid();
#ifdef HAVE_GETCWD
    chdir(path);
#endif
    umask(0);
#else // ifndef HAVE_FORK ...
    logmgr.cerr()
        << "warning: --background ignored: system does not support fork(2)"
        << std::endl;
#endif
}

<commit_msg>add copyright year.<commit_after>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * cclive 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 General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#ifndef HAVE_PTRDIFF_T
#error Cannot compile without ptrdiff_t support
#endif

#include <iostream>
#include <vector>
#include <iterator>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <tr1/memory>
#include <cstring>
#include <cerrno>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif

#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif

#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif

#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif

#include "hosthandler.h"
#include "hostfactory.h"
#include "macros.h"
#include "opts.h"
#include "curl.h"
#include "exec.h"
#include "retry.h"
#include "log.h"
#include "app.h"

#if defined (SIGWINCH) && defined (TIOCGWINSZ)
#define WITH_RESIZE
#endif

#define SHP std::tr1::shared_ptr

// singleton instances
static SHP<OptionsMgr> __optsmgr (new OptionsMgr);
static SHP<CurlMgr>    __curlmgr (new CurlMgr);
static SHP<ExecMgr>    __execmgr (new ExecMgr);
static SHP<RetryMgr>   __retrymgr(new RetryMgr);
static SHP<LogMgr>     __logmgr  (new LogMgr);

extern void handle_sigwinch(int); // src/progress.cpp

App::~App() {
}

void
App::main(const int& argc, char * const *argv) {
    optsmgr.init(argc, argv);
    logmgr.init(); // apply --quiet
    curlmgr.init();
}

static void
printVideo(const VideoProperties& props) {
    logmgr.cout()
        << "file: "
        << props.getFilename()
        << "  "
        << std::setprecision(1)
        << _TOMB(props.getLength())
        << "M  ["
        << props.getContentType()
        << "]"
        << std::endl;
}

static void
printCSV(const VideoProperties& props) {
    std::cout.setf(std::ios::fixed);
    std::cout.unsetf(std::ios::showpoint);
    std::cout
        << "csv:\""
        << props.getFilename()
        << "\",\""
        << std::setprecision(0)
        << props.getLength()
        << "\",\""
        << props.getLink()
        << "\""
        << std::endl;
}

typedef CurlMgr::FetchException FetchError;

static void
fetchPage(SHP<HostHandler> handler,
          const std::string& url,
          const bool& reset=false)
{
    if (reset)
        retrymgr.reset();
    try   { handler->parsePage(url); }
    catch (const FetchError& x) {
        retrymgr.handle(x);
        fetchPage(handler, url);
    }
    logmgr.resetReturnCode();
}

static void
fetchFile(VideoProperties& props, const bool& reset=false) {
    if (reset)
        retrymgr.reset();
    try   { curlmgr.fetchToFile(props); }
    catch (const FetchError& x) {
        retrymgr.setRetryUntilRetrievedFlag();
        retrymgr.handle(x);
        fetchFile(props);
    }
    logmgr.resetReturnCode();
}

static void
queryLength(VideoProperties& props, const bool& reset=false) {
    if (reset)
        retrymgr.reset();
    try   { curlmgr.queryFileLength(props); }
    catch (const FetchError& x) {
        retrymgr.handle(x);
        queryLength(props);
    }
    logmgr.resetReturnCode();
}

static void
processVideo(VideoProperties& props) {
    queryLength(props, true);

    const Options opts =
        optsmgr.getOptions();

    if (opts.no_extract_given)
        printVideo(props);
    else if (opts.emit_csv_given)
        printCSV(props);
    else if (opts.stream_pass_given)
        execmgr.passStream(props);
    else
    {
        if (opts.print_fname_given)
            printVideo(props);

        fetchFile(props, true);
    }
}

static void
reportNotice() {
    static const char report_notice[] =
    ":: A bug? If you think so, and you can reproduce the above,\n"
    ":: consider submitting it to the issue tracker:\n"
    "::     <http://code.google.com/p/cclive/issues/>\n";
    logmgr.cerr() << report_notice << std::endl;
}

typedef HostHandlerFactory::UnsupportedHostException NoSupport;
typedef HostHandler::ParseException                  ParseError;
typedef VideoProperties::NothingToDoException        NothingTodo;

static void
handleURL(const std::string& url) {
    try
    {
        SHP<HostHandler> handler =
            HostHandlerFactory::createHandler(url);

        fetchPage(handler, url, true);

        VideoProperties props =
            handler->getVideoProperties();

        try { processVideo(props); }
        catch (const FileOpenException& x)
            { logmgr.cerr(x, false); }
        catch (const NothingTodo& x)
            { logmgr.cerr(x, false); }

        if (optsmgr.getOptions().exec_run_given)
            execmgr.append(props);
    }
    catch (const NoSupport& x)   { logmgr.cerr(x, false); }
    catch (const FetchError& x)  { /* printed by retrymgr.handle already */ }
    catch (const ParseError& x)  { logmgr.cerr(x, false); reportNotice(); }
}

typedef std::vector<std::string> STRV;

void
App::run() {
    const Options opts = optsmgr.getOptions();

    if (opts.version_given) {
        printVersion();
        return;
    }

    if (opts.hosts_given) {
        HostHandlerFactory::printHosts();
        return;
    }

    if (opts.regexp_given) {
        std::string empty;
        if (!Util::perlMatch(opts.regexp_arg, empty)) {
            throw RuntimeException(CCLIVE_OPTARG,
                "--regexp: expected perl-like\n"
                "error: /pattern/(gi) regular expression");
        }
    }

    if (opts.substitute_given) {
        std::string empty; // Validate regexp only (empty string).
        if (!Util::perlSubstitute(opts.substitute_arg, empty)) {
            throw RuntimeException(CCLIVE_OPTARG,
                "--substitute: expected perl-like\n"
                "error: s/old/new/(gi) substitution");
        }
    }

    execmgr.verifyExecArgument();

#if !defined(HAVE_FORK) || !defined(HAVE_WORKING_FORK)
    if (opts.stream_exec_given) {
        logmgr.cerr()
            << "warn: this system does not have a working fork.\n"
            << "warn: --stream-exec ignored."
            << std::endl;
    }
#endif

    STRV tokens;

    typedef unsigned int _uint;

    if (!opts.inputs_num)
        tokens = parseInput();
    else {
        for (register _uint i=0; i<opts.inputs_num; ++i)
            tokens.push_back(opts.inputs[i]);
    }

    for (STRV::iterator iter=tokens.begin();
        iter != tokens.end();
        ++iter)
    {
        // Convert alternate domain link to youtube.com page link.
        Util::nocookieToYoutube(*iter);

        // Convert any embed type URLs to video page links.
        Util::embedToPage(*iter);

        // Convert last.fm video link to Youtube page link.
        if ((*iter).find("last.fm") != std::string::npos)
            Util::lastfmToYoutube(*iter);
    }

    logmgr.cout().setf(std::ios::fixed);
#ifdef WITH_RESIZE
    signal(SIGWINCH, handle_sigwinch);
#endif
    if (opts.background_given)
        daemonize();

    std::for_each(tokens.begin(), tokens.end(), handleURL);

    if (opts.exec_run_given)
        execmgr.playQueue();
}

STRV
App::parseInput() {
    std::string input;

    char ch;
    while (std::cin.get(ch))
        input += ch;

    std::istringstream iss(input);
    STRV tokens;

    std::copy(
        std::istream_iterator<std::string >(iss),
        std::istream_iterator<std::string >(),
        std::back_inserter<STRV>(tokens)
    );

    return tokens;
}

void
App::printVersion() {
static const char copyr_notice[] =
"Copyright (C) 2009,2010 Toni Gundogdu. "
"License GPLv3+: GNU GPL version 3 or later\n"
"This is free software; see the  source for  copying conditions.  There is NO\n"
"warranty;  not even for MERCHANTABILITY or FITNESS FOR A  PARTICULAR PURPOSE.";

    const curl_version_info_data *c =
        curl_version_info(CURLVERSION_NOW);

    std::cout
        << CMDLINE_PARSER_PACKAGE       << " version "
        << CMDLINE_PARSER_VERSION       << " with libcurl version "
        << c->version                   << "  ["
#ifdef BUILD_DATE
        << BUILD_DATE << "-"
#endif
        << CANONICAL_TARGET             << "]\n"
        << copyr_notice                 << "\n"
        << "\n  Locale/codeset  : "     << optsmgr.getLocale()
        << "\n  Config          : "     << optsmgr.getPath()
        << "\n  Features        : pcre "
#ifdef HAVE_ICONV
        << "iconv "
#endif
#ifdef WITH_RESIZE
        << "sigwinch "
#endif
        << "\n  Home            : "     << "<http://cclive.googlecode.com/>"
        << std::endl;
}

void
App::daemonize() {
#if defined(HAVE_FORK) && defined(HAVE_WORKING_FORK)
#ifdef HAVE_GETCWD
    char path[PATH_MAX];
    path[0] = '\0';
    getcwd(path, sizeof(path));
#endif

    pid_t pid = fork();

    if (pid < 0) {
#ifdef HAVE_STRERROR
        fprintf(stderr, "error: fork: %s\n", strerror(errno));
#else
        perror("fork");
#endif
        exit (CCLIVE_SYSTEM);
    }
    else if (pid != 0) {
        std::cout
            << "Continuing in background, pid "
            << static_cast<long>(pid)
            << ".\nOutput will be written to \""
            << logmgr.getFilename()
            << "\"."
            << std::endl;
        exit (CCLIVE_OK);
    }
    setsid();
#ifdef HAVE_GETCWD
    chdir(path);
#endif
    umask(0);
#else // ifndef HAVE_FORK ...
    logmgr.cerr()
        << "warning: --background ignored: system does not support fork(2)"
        << std::endl;
#endif
}

<|endoftext|>


<commit_before>/* Copyright (c) 2014, Vsevolod Stakhov
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *       * Redistributions of source code must retain the above copyright
 *         notice, this list of conditions and the following disclaimer.
 *       * Redistributions in binary form must reproduce the above copyright
 *         notice, this list of conditions and the following disclaimer in the
 *         documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <openssl/evp.h>

#include <chacha.h>
#include <poly1305.h>
#include <cstring>
#include "aead.h"
#include "util.h"

namespace hpenc
{

// Basic class for aead alorithms
class AeadCipher
{
protected:
	std::shared_ptr<SessionKey> key;
public:
	AeadCipher() {}
	virtual ~AeadCipher() {}

	virtual bool hasKey() const { return !!key; }
	virtual void setKey(std::shared_ptr<SessionKey> const &_key) { key = _key; }

	virtual std::unique_ptr<MacTag> encrypt(const byte *aad, size_t aadlen,
			const byte *nonce, size_t nlen, const byte *in, size_t inlen,
			byte *out) = 0;
	virtual bool decrypt(const byte *aad, size_t aadlen, const byte *nonce,
			size_t nlen, const byte *in, size_t inlen, byte *out,
			const MacTag *tag) = 0;
	virtual size_t taglen() const
	{
		return 0;
	}
	virtual size_t keylen() const
	{
		return 0;
	}
	virtual size_t noncelen() const
	{
		return 0;
	}
};

class OpenSSLAeadCipher: public AeadCipher
{
private:
	std::unique_ptr<EVP_CIPHER_CTX> ctx_enc;
	std::unique_ptr<EVP_CIPHER_CTX> ctx_dec;
	const EVP_CIPHER *alg;
	AeadAlgorithm alg_num;
public:
	OpenSSLAeadCipher(AeadAlgorithm _alg) : AeadCipher()
	{
		ctx_enc.reset(EVP_CIPHER_CTX_new());
		ctx_dec.reset(EVP_CIPHER_CTX_new());

		switch(_alg) {
		case AeadAlgorithm::AES_GCM_128:
			alg = EVP_aes_128_gcm();
			break;
		case AeadAlgorithm::AES_GCM_256:
			alg = EVP_aes_256_gcm();
			break;
		default:
			alg = nullptr;
			break;
		}
		EVP_EncryptInit_ex(ctx_enc.get(), alg, NULL, NULL, NULL);
		EVP_DecryptInit_ex(ctx_dec.get(), alg, NULL, NULL, NULL);

		alg_num = _alg;
	}

	virtual std::unique_ptr<MacTag> encrypt(const byte *aad, size_t aadlen,
			const byte *nonce, size_t nlen, const byte *in, size_t inlen,
			byte *out) override
	{
		int howmany = 0;
		auto ctx_ptr = ctx_enc.get();

		// Set nonce length
		EVP_CIPHER_CTX_ctrl(ctx_ptr, EVP_CTRL_GCM_SET_IVLEN, nlen, NULL);
		EVP_EncryptInit_ex(ctx_ptr, NULL, NULL, key->data(),
				(const unsigned char*) nonce);
		if (aadlen > 0) {
			// Add unencrypted data
			EVP_EncryptUpdate(ctx_ptr, NULL, &howmany,
					(const unsigned char*) aad, aadlen);
		}
		// Encrypt
		EVP_EncryptUpdate(ctx_ptr,(unsigned char *) out, &howmany,
				(const unsigned char *) in, inlen);
		EVP_EncryptFinal_ex(ctx_ptr, (unsigned char *) out, &howmany);
		// Get tag
		auto tag = util::make_unique < MacTag >(taglen());
		EVP_CIPHER_CTX_ctrl(ctx_ptr, EVP_CTRL_GCM_GET_TAG, 16, tag->data);

		return tag;
	}

	virtual bool decrypt(const byte *aad, size_t aadlen, const byte *nonce,
			size_t nlen, const byte *in, size_t inlen, byte *out,
			const MacTag *tag) override
	{
		int howmany = 0;
		auto ctx_ptr = ctx_enc.get();
		// Set nonce and key
		EVP_CIPHER_CTX_ctrl(ctx_ptr, EVP_CTRL_GCM_SET_IVLEN, nlen, NULL);
		EVP_DecryptInit_ex(ctx_ptr, NULL, NULL, key->data(),
				(const unsigned char*) nonce);

		if (aadlen > 0) {
			EVP_DecryptUpdate(ctx_ptr, NULL, &howmany,
					(const unsigned char*) aad, aadlen);
		}
		EVP_DecryptUpdate(ctx_ptr,(unsigned char *) out, &howmany,
				(const unsigned char *) in, inlen);
		// Set tag
		EVP_CIPHER_CTX_ctrl(ctx_ptr, EVP_CTRL_GCM_SET_TAG, tag->datalen,
				(void *) tag->data);
		auto res = EVP_DecryptFinal_ex(ctx_ptr,(unsigned char *) out,
				&howmany);

		return res > 0;
	}

	virtual size_t taglen() const override
	{
		return 16;
	}

	virtual size_t keylen() const override
	{
		switch(alg_num) {
		case AeadAlgorithm::AES_GCM_128:
			return 128 / 8;
		case AeadAlgorithm::AES_GCM_256:
			return 256 / 8;
		default:
			return 0;
		}
	}

	virtual size_t noncelen() const override
	{
		return 12;
	}
};

class Chacha20Poly1305AeadCipher: public AeadCipher
{
private:
	chacha_state enc;
	poly1305_state mac;

	static inline void _u64_le_from_ull(unsigned char out[8U],
			unsigned long long x)
	{
		out[0] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[1] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[2] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[3] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[4] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[5] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[6] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[7] = (unsigned char) (x & 0xff);
	}
public:
	Chacha20Poly1305AeadCipher(AeadAlgorithm _alg) :
			AeadCipher()
	{
	}

	virtual std::unique_ptr<MacTag> encrypt(const byte *aad, size_t aadlen,
			const byte *nonce, size_t nlen, const byte *in, size_t inlen,
			byte *out) override
	{

		byte block0[64];
		auto tag = util::make_unique < MacTag >(taglen());
		//byte slen[8];

		::memset(block0, 0, sizeof(block0));
		chacha_init(&enc, (const chacha_key *)key->data(),
				(const chacha_iv *)nonce, 20);
		// Set poly1305 key
		chacha_update(&enc, block0, block0, sizeof(block0));
		poly1305_init(&mac, (const poly1305_key *)block0);

		if (aadlen > 0) {
			// Add unencrypted data
			poly1305_update(&mac, aad, aadlen);
			// We don't care about endiannes here for speed
			//_u64_le_from_ull(slen, aadlen);
			poly1305_update(&mac, (byte *)&aadlen, sizeof(aadlen));
		}
		// Encrypt
		auto encrypted = chacha_update(&enc, in, out, inlen);
		chacha_final(&enc, out + encrypted);
		// Final tag
		poly1305_update(&mac, out, inlen);
		//_u64_le_from_ull(slen, inlen);
		poly1305_update(&mac, (byte *)&inlen, sizeof(inlen));
		poly1305_finish(&mac, tag->data);

		return tag;
	}

	int verify_16(const unsigned char *x,const unsigned char *y)
	{
	  unsigned int differentbits = 0;
	#define F(i) differentbits |= x[i] ^ y[i];
	  F(0)
	  F(1)
	  F(2)
	  F(3)
	  F(4)
	  F(5)
	  F(6)
	  F(7)
	  F(8)
	  F(9)
	  F(10)
	  F(11)
	  F(12)
	  F(13)
	  F(14)
	  F(15)
	  return (1 & ((differentbits - 1) >> 8)) - 1;
	}

	virtual bool decrypt(const byte *aad, size_t aadlen, const byte *nonce,
			size_t nlen, const byte *in, size_t inlen, byte *out,
			const MacTag *tag) override
	{
		byte block0[64];
		//byte slen[8];
		auto test_tag = util::make_unique < MacTag >(taglen());

		::memset(block0, 0, sizeof(block0));
		chacha_init(&enc, (const chacha_key *)key->data(),
				(const chacha_iv *)nonce, 20);
		// Set poly1305 key
		chacha_update(&enc, block0, block0, sizeof(block0));
		poly1305_init(&mac, (const poly1305_key *)block0);

		if (aadlen > 0) {
			// Add unencrypted data
			poly1305_update(&mac, aad, aadlen);
			// We don't care about endiannes here for speed
			//_u64_le_from_ull(slen, aadlen);
			poly1305_update(&mac, (byte *)&aadlen, sizeof(aadlen));
		}
		// Final tag
		poly1305_update(&mac, out, inlen);
		//_u64_le_from_ull(slen, inlen);
		poly1305_update(&mac, (byte *)&inlen, sizeof(inlen));
		poly1305_finish(&mac, test_tag->data);

		auto ret = verify_16(test_tag->data, tag->data);
		if (ret != 0) {
			memset(out, 0, inlen);
			return false;
		}

		auto decrypted = chacha_update(&enc, in, out, inlen);
		chacha_final(&enc, out + decrypted);

		return true;
	}

	virtual size_t taglen() const override
	{
		return 16;
	}
	virtual size_t keylen() const override
	{
		return sizeof(chacha_key);
	}

	virtual size_t noncelen() const override
	{
		return sizeof(chacha_iv);
	}
};

class HPencAead::impl
{
public:
	std::unique_ptr<AeadCipher> cipher;

	impl(AeadAlgorithm alg)
	{
		if (alg == AeadAlgorithm::AES_GCM_128
				|| alg == AeadAlgorithm::AES_GCM_256) {
			cipher.reset(new OpenSSLAeadCipher(alg));
		}
		else if (alg == AeadAlgorithm::CHACHA20_POLY_1305) {
			cipher.reset(new Chacha20Poly1305AeadCipher(alg));
		}
	}

	virtual ~impl()
	{
	}
};

HPencAead::HPencAead(AeadAlgorithm alg) :
		pimpl(new impl(alg))
{
}

HPencAead::~HPencAead()
{
}

void HPencAead::setKey(std::shared_ptr<SessionKey> const &sk)
{
	if (pimpl->cipher) {
		pimpl->cipher->setKey(sk);
	}
}

std::unique_ptr<MacTag> HPencAead::encrypt(const byte *aad, size_t aadlen,
		const byte *nonce, size_t nlen, const byte *in, size_t inlen, byte *out)
{
	if (!pimpl->cipher || !pimpl->cipher->hasKey()) {
		return nullptr;
	}

	return pimpl->cipher->encrypt(aad, aadlen, nonce, nlen, in, inlen, out);

}
bool HPencAead::decrypt(const byte *aad, size_t aadlen, const byte *nonce,
		size_t nlen, const byte *in, size_t inlen, const MacTag *tag, byte *out)
{
	if (!pimpl->cipher || !pimpl->cipher->hasKey()) {
		return false;
	}

	return pimpl->cipher->decrypt(aad, aadlen, nonce, nlen, in, inlen, out,
			tag);
}

size_t HPencAead::taglen() const
{
	if (!pimpl->cipher) {
		return 0;
	}

	return pimpl->cipher->taglen();
}

size_t HPencAead::keylen() const
{
	if (!pimpl->cipher) {
		return 0;
	}

	return pimpl->cipher->keylen();
}

size_t HPencAead::noncelen() const
{
	if (!pimpl->cipher) {
		return 0;
	}

	return pimpl->cipher->noncelen();
}

} /* namespace shush */
<commit_msg>Align block for SSE ops.<commit_after>/* Copyright (c) 2014, Vsevolod Stakhov
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *       * Redistributions of source code must retain the above copyright
 *         notice, this list of conditions and the following disclaimer.
 *       * Redistributions in binary form must reproduce the above copyright
 *         notice, this list of conditions and the following disclaimer in the
 *         documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <openssl/evp.h>

#include <chacha.h>
#include <poly1305.h>
#include <cstring>
#include "aead.h"
#include "util.h"

namespace hpenc
{

// Basic class for aead alorithms
class AeadCipher
{
protected:
	std::shared_ptr<SessionKey> key;
public:
	AeadCipher() {}
	virtual ~AeadCipher() {}

	virtual bool hasKey() const { return !!key; }
	virtual void setKey(std::shared_ptr<SessionKey> const &_key) { key = _key; }

	virtual std::unique_ptr<MacTag> encrypt(const byte *aad, size_t aadlen,
			const byte *nonce, size_t nlen, const byte *in, size_t inlen,
			byte *out) = 0;
	virtual bool decrypt(const byte *aad, size_t aadlen, const byte *nonce,
			size_t nlen, const byte *in, size_t inlen, byte *out,
			const MacTag *tag) = 0;
	virtual size_t taglen() const
	{
		return 0;
	}
	virtual size_t keylen() const
	{
		return 0;
	}
	virtual size_t noncelen() const
	{
		return 0;
	}
};

class OpenSSLAeadCipher: public AeadCipher
{
private:
	std::unique_ptr<EVP_CIPHER_CTX> ctx_enc;
	std::unique_ptr<EVP_CIPHER_CTX> ctx_dec;
	const EVP_CIPHER *alg;
	AeadAlgorithm alg_num;
public:
	OpenSSLAeadCipher(AeadAlgorithm _alg) : AeadCipher()
	{
		ctx_enc.reset(EVP_CIPHER_CTX_new());
		ctx_dec.reset(EVP_CIPHER_CTX_new());

		switch(_alg) {
		case AeadAlgorithm::AES_GCM_128:
			alg = EVP_aes_128_gcm();
			break;
		case AeadAlgorithm::AES_GCM_256:
			alg = EVP_aes_256_gcm();
			break;
		default:
			alg = nullptr;
			break;
		}
		EVP_EncryptInit_ex(ctx_enc.get(), alg, NULL, NULL, NULL);
		EVP_DecryptInit_ex(ctx_dec.get(), alg, NULL, NULL, NULL);

		alg_num = _alg;
	}

	virtual std::unique_ptr<MacTag> encrypt(const byte *aad, size_t aadlen,
			const byte *nonce, size_t nlen, const byte *in, size_t inlen,
			byte *out) override
	{
		int howmany = 0;
		auto ctx_ptr = ctx_enc.get();

		// Set nonce length
		EVP_CIPHER_CTX_ctrl(ctx_ptr, EVP_CTRL_GCM_SET_IVLEN, nlen, NULL);
		EVP_EncryptInit_ex(ctx_ptr, NULL, NULL, key->data(),
				(const unsigned char*) nonce);
		if (aadlen > 0) {
			// Add unencrypted data
			EVP_EncryptUpdate(ctx_ptr, NULL, &howmany,
					(const unsigned char*) aad, aadlen);
		}
		// Encrypt
		EVP_EncryptUpdate(ctx_ptr,(unsigned char *) out, &howmany,
				(const unsigned char *) in, inlen);
		EVP_EncryptFinal_ex(ctx_ptr, (unsigned char *) out, &howmany);
		// Get tag
		auto tag = util::make_unique < MacTag >(taglen());
		EVP_CIPHER_CTX_ctrl(ctx_ptr, EVP_CTRL_GCM_GET_TAG, 16, tag->data);

		return tag;
	}

	virtual bool decrypt(const byte *aad, size_t aadlen, const byte *nonce,
			size_t nlen, const byte *in, size_t inlen, byte *out,
			const MacTag *tag) override
	{
		int howmany = 0;
		auto ctx_ptr = ctx_enc.get();
		// Set nonce and key
		EVP_CIPHER_CTX_ctrl(ctx_ptr, EVP_CTRL_GCM_SET_IVLEN, nlen, NULL);
		EVP_DecryptInit_ex(ctx_ptr, NULL, NULL, key->data(),
				(const unsigned char*) nonce);

		if (aadlen > 0) {
			EVP_DecryptUpdate(ctx_ptr, NULL, &howmany,
					(const unsigned char*) aad, aadlen);
		}
		EVP_DecryptUpdate(ctx_ptr,(unsigned char *) out, &howmany,
				(const unsigned char *) in, inlen);
		// Set tag
		EVP_CIPHER_CTX_ctrl(ctx_ptr, EVP_CTRL_GCM_SET_TAG, tag->datalen,
				(void *) tag->data);
		auto res = EVP_DecryptFinal_ex(ctx_ptr,(unsigned char *) out,
				&howmany);

		return res > 0;
	}

	virtual size_t taglen() const override
	{
		return 16;
	}

	virtual size_t keylen() const override
	{
		switch(alg_num) {
		case AeadAlgorithm::AES_GCM_128:
			return 128 / 8;
		case AeadAlgorithm::AES_GCM_256:
			return 256 / 8;
		default:
			return 0;
		}
	}

	virtual size_t noncelen() const override
	{
		return 12;
	}
};

class Chacha20Poly1305AeadCipher: public AeadCipher
{
private:
	chacha_state enc;
	poly1305_state mac;

	static inline void _u64_le_from_ull(unsigned char out[8U],
			unsigned long long x)
	{
		out[0] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[1] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[2] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[3] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[4] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[5] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[6] = (unsigned char) (x & 0xff);
		x >>= 8;
		out[7] = (unsigned char) (x & 0xff);
	}
public:
	Chacha20Poly1305AeadCipher(AeadAlgorithm _alg) :
			AeadCipher()
	{
	}

	virtual std::unique_ptr<MacTag> encrypt(const byte *aad, size_t aadlen,
			const byte *nonce, size_t nlen, const byte *in, size_t inlen,
			byte *out) override
	{

		alignas(64) byte block0[64];
		auto tag = util::make_unique < MacTag >(taglen());
		//byte slen[8];

		::memset(block0, 0, sizeof(block0));
		chacha_init(&enc, (const chacha_key *)key->data(),
				(const chacha_iv *)nonce, 20);
		// Set poly1305 key
		chacha_update(&enc, block0, block0, sizeof(block0));
		poly1305_init(&mac, (const poly1305_key *)block0);

		if (aadlen > 0) {
			// Add unencrypted data
			poly1305_update(&mac, aad, aadlen);
			// We don't care about endiannes here for speed
			//_u64_le_from_ull(slen, aadlen);
			poly1305_update(&mac, (byte *)&aadlen, sizeof(aadlen));
		}
		// Encrypt
		auto encrypted = chacha_update(&enc, in, out, inlen);
		chacha_final(&enc, out + encrypted);
		// Final tag
		poly1305_update(&mac, out, inlen);
		//_u64_le_from_ull(slen, inlen);
		poly1305_update(&mac, (byte *)&inlen, sizeof(inlen));
		poly1305_finish(&mac, tag->data);

		return tag;
	}

	int verify_16(const unsigned char *x,const unsigned char *y)
	{
	  unsigned int differentbits = 0;
	#define F(i) differentbits |= x[i] ^ y[i];
	  F(0)
	  F(1)
	  F(2)
	  F(3)
	  F(4)
	  F(5)
	  F(6)
	  F(7)
	  F(8)
	  F(9)
	  F(10)
	  F(11)
	  F(12)
	  F(13)
	  F(14)
	  F(15)
	  return (1 & ((differentbits - 1) >> 8)) - 1;
	}

	virtual bool decrypt(const byte *aad, size_t aadlen, const byte *nonce,
			size_t nlen, const byte *in, size_t inlen, byte *out,
			const MacTag *tag) override
	{
		alignas(64) byte block0[64];
		//byte slen[8];
		auto test_tag = util::make_unique < MacTag >(taglen());

		::memset(block0, 0, sizeof(block0));
		chacha_init(&enc, (const chacha_key *)key->data(),
				(const chacha_iv *)nonce, 20);
		// Set poly1305 key
		chacha_update(&enc, block0, block0, sizeof(block0));
		poly1305_init(&mac, (const poly1305_key *)block0);

		if (aadlen > 0) {
			// Add unencrypted data
			poly1305_update(&mac, aad, aadlen);
			// We don't care about endiannes here for speed
			//_u64_le_from_ull(slen, aadlen);
			poly1305_update(&mac, (byte *)&aadlen, sizeof(aadlen));
		}
		// Final tag
		poly1305_update(&mac, out, inlen);
		//_u64_le_from_ull(slen, inlen);
		poly1305_update(&mac, (byte *)&inlen, sizeof(inlen));
		poly1305_finish(&mac, test_tag->data);

		auto ret = verify_16(test_tag->data, tag->data);
		if (ret != 0) {
			memset(out, 0, inlen);
			return false;
		}

		auto decrypted = chacha_update(&enc, in, out, inlen);
		chacha_final(&enc, out + decrypted);

		return true;
	}

	virtual size_t taglen() const override
	{
		return 16;
	}
	virtual size_t keylen() const override
	{
		return sizeof(chacha_key);
	}

	virtual size_t noncelen() const override
	{
		return sizeof(chacha_iv);
	}
};

class HPencAead::impl
{
public:
	std::unique_ptr<AeadCipher> cipher;

	impl(AeadAlgorithm alg)
	{
		if (alg == AeadAlgorithm::AES_GCM_128
				|| alg == AeadAlgorithm::AES_GCM_256) {
			cipher.reset(new OpenSSLAeadCipher(alg));
		}
		else if (alg == AeadAlgorithm::CHACHA20_POLY_1305) {
			cipher.reset(new Chacha20Poly1305AeadCipher(alg));
		}
	}

	virtual ~impl()
	{
	}
};

HPencAead::HPencAead(AeadAlgorithm alg) :
		pimpl(new impl(alg))
{
}

HPencAead::~HPencAead()
{
}

void HPencAead::setKey(std::shared_ptr<SessionKey> const &sk)
{
	if (pimpl->cipher) {
		pimpl->cipher->setKey(sk);
	}
}

std::unique_ptr<MacTag> HPencAead::encrypt(const byte *aad, size_t aadlen,
		const byte *nonce, size_t nlen, const byte *in, size_t inlen, byte *out)
{
	if (!pimpl->cipher || !pimpl->cipher->hasKey()) {
		return nullptr;
	}

	return pimpl->cipher->encrypt(aad, aadlen, nonce, nlen, in, inlen, out);

}
bool HPencAead::decrypt(const byte *aad, size_t aadlen, const byte *nonce,
		size_t nlen, const byte *in, size_t inlen, const MacTag *tag, byte *out)
{
	if (!pimpl->cipher || !pimpl->cipher->hasKey()) {
		return false;
	}

	return pimpl->cipher->decrypt(aad, aadlen, nonce, nlen, in, inlen, out,
			tag);
}

size_t HPencAead::taglen() const
{
	if (!pimpl->cipher) {
		return 0;
	}

	return pimpl->cipher->taglen();
}

size_t HPencAead::keylen() const
{
	if (!pimpl->cipher) {
		return 0;
	}

	return pimpl->cipher->keylen();
}

size_t HPencAead::noncelen() const
{
	if (!pimpl->cipher) {
		return 0;
	}

	return pimpl->cipher->noncelen();
}

} /* namespace shush */
<|endoftext|>


<commit_before>// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// 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 "fastrtps/subscriber/Subscriber.h"

#include "rmw/error_handling.h"
#include "rmw/rmw.h"

#include "rmw_fastrtps_cpp/custom_client_info.hpp"
#include "rmw_fastrtps_cpp/custom_service_info.hpp"
#include "rmw_fastrtps_cpp/custom_subscriber_info.hpp"
#include "types/custom_waitset_info.hpp"
#include "types/guard_condition.hpp"

// helper function for wait
bool
check_waitset_for_data(
  const rmw_subscriptions_t * subscriptions,
  const rmw_guard_conditions_t * guard_conditions,
  const rmw_services_t * services,
  const rmw_clients_t * clients)
{
  for (size_t i = 0; i < subscriptions->subscriber_count; ++i) {
    void * data = subscriptions->subscribers[i];
    CustomSubscriberInfo * custom_subscriber_info = static_cast<CustomSubscriberInfo *>(data);
    // Short circuiting out of this function is possible
    if (custom_subscriber_info && custom_subscriber_info->listener_->hasData()) {
      return true;
    }
  }

  for (size_t i = 0; i < clients->client_count; ++i) {
    void * data = clients->clients[i];
    CustomClientInfo * custom_client_info = static_cast<CustomClientInfo *>(data);
    if (custom_client_info && custom_client_info->listener_->hasData()) {
      return true;
    }
  }

  for (size_t i = 0; i < services->service_count; ++i) {
    void * data = services->services[i];
    CustomServiceInfo * custom_service_info = static_cast<CustomServiceInfo *>(data);
    if (custom_service_info && custom_service_info->listener_->hasData()) {
      return true;
    }
  }

  if (guard_conditions) {
    for (size_t i = 0; i < guard_conditions->guard_condition_count; ++i) {
      void * data = guard_conditions->guard_conditions[i];
      GuardCondition * guard_condition = static_cast<GuardCondition *>(data);
      if (guard_condition && guard_condition->hasTriggered()) {
        return true;
      }
    }
  }
  return false;
}

extern "C"
{
rmw_ret_t
rmw_wait(
  rmw_subscriptions_t * subscriptions,
  rmw_guard_conditions_t * guard_conditions,
  rmw_services_t * services,
  rmw_clients_t * clients,
  rmw_waitset_t * waitset,
  const rmw_time_t * wait_timeout)
{
  if (!waitset) {
    RMW_SET_ERROR_MSG("Waitset handle is null");
    return RMW_RET_ERROR;
  }
  CustomWaitsetInfo * waitset_info = static_cast<CustomWaitsetInfo *>(waitset->data);
  if (!waitset_info) {
    RMW_SET_ERROR_MSG("Waitset info struct is null");
    return RMW_RET_ERROR;
  }
  std::mutex * conditionMutex = &waitset_info->condition_mutex;
  std::condition_variable * conditionVariable = &waitset_info->condition;
  if (!conditionMutex) {
    RMW_SET_ERROR_MSG("Mutex for waitset was null");
    return RMW_RET_ERROR;
  }
  if (!conditionVariable) {
    RMW_SET_ERROR_MSG("Condition variable for waitset was null");
    return RMW_RET_ERROR;
  }

  for (size_t i = 0; i < subscriptions->subscriber_count; ++i) {
    void * data = subscriptions->subscribers[i];
    CustomSubscriberInfo * custom_subscriber_info = static_cast<CustomSubscriberInfo *>(data);
    custom_subscriber_info->listener_->attachCondition(conditionMutex, conditionVariable);
  }

  for (size_t i = 0; i < clients->client_count; ++i) {
    void * data = clients->clients[i];
    CustomClientInfo * custom_client_info = static_cast<CustomClientInfo *>(data);
    custom_client_info->listener_->attachCondition(conditionMutex, conditionVariable);
  }

  for (size_t i = 0; i < services->service_count; ++i) {
    void * data = services->services[i];
    CustomServiceInfo * custom_service_info = static_cast<CustomServiceInfo *>(data);
    custom_service_info->listener_->attachCondition(conditionMutex, conditionVariable);
  }

  if (guard_conditions) {
    for (size_t i = 0; i < guard_conditions->guard_condition_count; ++i) {
      void * data = guard_conditions->guard_conditions[i];
      GuardCondition * guard_condition = static_cast<GuardCondition *>(data);
      guard_condition->attachCondition(conditionMutex, conditionVariable);
    }
  }

  // This mutex prevents any of the listeners
  // to change the internal state and notify the condition
  // between the call to hasData() / hasTriggered() and wait()
  // otherwise the decision to wait might be incorrect
  std::unique_lock<std::mutex> lock(*conditionMutex);

  // First check variables.
  // If wait_timeout is null, wait indefinitely (so we have to wait)
  // If wait_timeout is not null and either of its fields are nonzero, we have to wait
  bool hasToWait = (wait_timeout && (wait_timeout->sec > 0 || wait_timeout->nsec > 0)) ||
    !wait_timeout;

  for (size_t i = 0; hasToWait && i < subscriptions->subscriber_count; ++i) {
    void * data = subscriptions->subscribers[i];
    CustomSubscriberInfo * custom_subscriber_info = static_cast<CustomSubscriberInfo *>(data);
    if (custom_subscriber_info->listener_->hasData()) {
      hasToWait = false;
    }
  }

  for (size_t i = 0; hasToWait && i < clients->client_count; ++i) {
    void * data = clients->clients[i];
    CustomClientInfo * custom_client_info = static_cast<CustomClientInfo *>(data);
    if (custom_client_info->listener_->hasData()) {
      hasToWait = false;
    }
  }

  for (size_t i = 0; hasToWait && i < services->service_count; ++i) {
    void * data = services->services[i];
    CustomServiceInfo * custom_service_info = static_cast<CustomServiceInfo *>(data);
    if (custom_service_info->listener_->hasData()) {
      hasToWait = false;
    }
  }

  if (guard_conditions) {
    for (size_t i = 0; hasToWait && i < guard_conditions->guard_condition_count; ++i) {
      void * data = guard_conditions->guard_conditions[i];
      GuardCondition * guard_condition = static_cast<GuardCondition *>(data);
      if (guard_condition->hasTriggered()) {
        hasToWait = false;
      }
    }
  }

  bool timeout = false;

  if (hasToWait) {
    if (!wait_timeout) {
      conditionVariable->wait(lock);
    } else {
      auto predicate = [subscriptions, guard_conditions, services, clients]() {
          return check_waitset_for_data(subscriptions, guard_conditions, services, clients);
        };
      auto n = std::chrono::duration_cast<std::chrono::nanoseconds>(
        std::chrono::seconds(wait_timeout->sec));
      n += std::chrono::nanoseconds(wait_timeout->nsec);
      timeout = !conditionVariable->wait_for(lock, n, predicate);
    }
  }

  // Unlock the condition variable mutex to prevent deadlocks that can occur if
  // a listener triggers while the condition variable is being detached.
  // Listeners will no longer be prevented from changing their internal state,
  // but that should not cause issues (if a listener has data / has triggered
  // after we check, it will be caught on the next call to this function).
  lock.unlock();

  // Even if this was a non-blocking wait, signal a timeout if there's no data.
  // This makes the return behavior consistent with rcl expectations for zero timeout value.
  // Do this before detaching the listeners because the data gets cleared for guard conditions.
  bool hasData = check_waitset_for_data(subscriptions, guard_conditions, services, clients);
  if (!hasData && wait_timeout && wait_timeout->sec == 0 && wait_timeout->nsec == 0) {
    timeout = true;
  }

  for (size_t i = 0; i < subscriptions->subscriber_count; ++i) {
    void * data = subscriptions->subscribers[i];
    CustomSubscriberInfo * custom_subscriber_info = static_cast<CustomSubscriberInfo *>(data);
    custom_subscriber_info->listener_->detachCondition();
    if (!custom_subscriber_info->listener_->hasData()) {
      subscriptions->subscribers[i] = 0;
    }
  }

  for (size_t i = 0; i < clients->client_count; ++i) {
    void * data = clients->clients[i];
    CustomClientInfo * custom_client_info = static_cast<CustomClientInfo *>(data);
    custom_client_info->listener_->detachCondition();
    if (!custom_client_info->listener_->hasData()) {
      clients->clients[i] = 0;
    }
  }

  for (size_t i = 0; i < services->service_count; ++i) {
    void * data = services->services[i];
    CustomServiceInfo * custom_service_info = static_cast<CustomServiceInfo *>(data);
    custom_service_info->listener_->detachCondition();
    if (!custom_service_info->listener_->hasData()) {
      services->services[i] = 0;
    }
  }

  if (guard_conditions) {
    for (size_t i = 0; i < guard_conditions->guard_condition_count; ++i) {
      void * data = guard_conditions->guard_conditions[i];
      GuardCondition * guard_condition = static_cast<GuardCondition *>(data);
      guard_condition->detachCondition();
      if (!guard_condition->getHasTriggered()) {
        guard_conditions->guard_conditions[i] = 0;
      }
    }
  }

  return timeout ? RMW_RET_TIMEOUT : RMW_RET_OK;
}
}  // extern "C"
<commit_msg>pointers are checked for null<commit_after>// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// 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 "fastrtps/subscriber/Subscriber.h"

#include "rmw/error_handling.h"
#include "rmw/rmw.h"

#include "rmw_fastrtps_cpp/custom_client_info.hpp"
#include "rmw_fastrtps_cpp/custom_service_info.hpp"
#include "rmw_fastrtps_cpp/custom_subscriber_info.hpp"
#include "types/custom_waitset_info.hpp"
#include "types/guard_condition.hpp"

// helper function for wait
bool
check_waitset_for_data(
  const rmw_subscriptions_t * subscriptions,
  const rmw_guard_conditions_t * guard_conditions,
  const rmw_services_t * services,
  const rmw_clients_t * clients)
{
  if (subscriptions) {
    for (size_t i = 0; i < subscriptions->subscriber_count; ++i) {
      void * data = subscriptions->subscribers[i];
      CustomSubscriberInfo * custom_subscriber_info = static_cast<CustomSubscriberInfo *>(data);
      // Short circuiting out of this function is possible
      if (custom_subscriber_info && custom_subscriber_info->listener_->hasData()) {
        return true;
      }
    }
  }

  if (clients) {
    for (size_t i = 0; i < clients->client_count; ++i) {
      void * data = clients->clients[i];
      CustomClientInfo * custom_client_info = static_cast<CustomClientInfo *>(data);
      if (custom_client_info && custom_client_info->listener_->hasData()) {
        return true;
      }
    }
  }

  if (services) {
    for (size_t i = 0; i < services->service_count; ++i) {
      void * data = services->services[i];
      CustomServiceInfo * custom_service_info = static_cast<CustomServiceInfo *>(data);
      if (custom_service_info && custom_service_info->listener_->hasData()) {
        return true;
      }
    }
  }

  if (guard_conditions) {
    for (size_t i = 0; i < guard_conditions->guard_condition_count; ++i) {
      void * data = guard_conditions->guard_conditions[i];
      GuardCondition * guard_condition = static_cast<GuardCondition *>(data);
      if (guard_condition && guard_condition->hasTriggered()) {
        return true;
      }
    }
  }
  return false;
}

extern "C"
{
rmw_ret_t
rmw_wait(
  rmw_subscriptions_t * subscriptions,
  rmw_guard_conditions_t * guard_conditions,
  rmw_services_t * services,
  rmw_clients_t * clients,
  rmw_waitset_t * waitset,
  const rmw_time_t * wait_timeout)
{
  if (!waitset) {
    RMW_SET_ERROR_MSG("Waitset handle is null");
    return RMW_RET_ERROR;
  }
  CustomWaitsetInfo * waitset_info = static_cast<CustomWaitsetInfo *>(waitset->data);
  if (!waitset_info) {
    RMW_SET_ERROR_MSG("Waitset info struct is null");
    return RMW_RET_ERROR;
  }
  std::mutex * conditionMutex = &waitset_info->condition_mutex;
  std::condition_variable * conditionVariable = &waitset_info->condition;
  if (!conditionMutex) {
    RMW_SET_ERROR_MSG("Mutex for waitset was null");
    return RMW_RET_ERROR;
  }
  if (!conditionVariable) {
    RMW_SET_ERROR_MSG("Condition variable for waitset was null");
    return RMW_RET_ERROR;
  }

  if (subscriptions) {
    for (size_t i = 0; i < subscriptions->subscriber_count; ++i) {
      void * data = subscriptions->subscribers[i];
      CustomSubscriberInfo * custom_subscriber_info = static_cast<CustomSubscriberInfo *>(data);
      custom_subscriber_info->listener_->attachCondition(conditionMutex, conditionVariable);
    }
  }

  if (clients) {
    for (size_t i = 0; i < clients->client_count; ++i) {
      void * data = clients->clients[i];
      CustomClientInfo * custom_client_info = static_cast<CustomClientInfo *>(data);
      custom_client_info->listener_->attachCondition(conditionMutex, conditionVariable);
    }
  }

  if (services) {
    for (size_t i = 0; i < services->service_count; ++i) {
      void * data = services->services[i];
      CustomServiceInfo * custom_service_info = static_cast<CustomServiceInfo *>(data);
      custom_service_info->listener_->attachCondition(conditionMutex, conditionVariable);
    }
  }

  if (guard_conditions) {
    for (size_t i = 0; i < guard_conditions->guard_condition_count; ++i) {
      void * data = guard_conditions->guard_conditions[i];
      GuardCondition * guard_condition = static_cast<GuardCondition *>(data);
      guard_condition->attachCondition(conditionMutex, conditionVariable);
    }
  }

  // This mutex prevents any of the listeners
  // to change the internal state and notify the condition
  // between the call to hasData() / hasTriggered() and wait()
  // otherwise the decision to wait might be incorrect
  std::unique_lock<std::mutex> lock(*conditionMutex);

  // First check variables.
  // If wait_timeout is null, wait indefinitely (so we have to wait)
  // If wait_timeout is not null and either of its fields are nonzero, we have to wait
  bool hasToWait = (wait_timeout && (wait_timeout->sec > 0 || wait_timeout->nsec > 0)) ||
    !wait_timeout;

  if (subscriptions) {
    for (size_t i = 0; hasToWait && i < subscriptions->subscriber_count; ++i) {
      void * data = subscriptions->subscribers[i];
      CustomSubscriberInfo * custom_subscriber_info = static_cast<CustomSubscriberInfo *>(data);
      if (custom_subscriber_info->listener_->hasData()) {
        hasToWait = false;
      }
    }
  }

  if (clients) {
    for (size_t i = 0; hasToWait && i < clients->client_count; ++i) {
      void * data = clients->clients[i];
      CustomClientInfo * custom_client_info = static_cast<CustomClientInfo *>(data);
      if (custom_client_info->listener_->hasData()) {
        hasToWait = false;
      }
    }
  }

  if (services) {
    for (size_t i = 0; hasToWait && i < services->service_count; ++i) {
      void * data = services->services[i];
      CustomServiceInfo * custom_service_info = static_cast<CustomServiceInfo *>(data);
      if (custom_service_info->listener_->hasData()) {
        hasToWait = false;
      }
    }
  }

  if (guard_conditions) {
    for (size_t i = 0; hasToWait && i < guard_conditions->guard_condition_count; ++i) {
      void * data = guard_conditions->guard_conditions[i];
      GuardCondition * guard_condition = static_cast<GuardCondition *>(data);
      if (guard_condition->hasTriggered()) {
        hasToWait = false;
      }
    }
  }

  bool timeout = false;

  if (hasToWait) {
    if (!wait_timeout) {
      conditionVariable->wait(lock);
    } else {
      auto predicate = [subscriptions, guard_conditions, services, clients]() {
          return check_waitset_for_data(subscriptions, guard_conditions, services, clients);
        };
      auto n = std::chrono::duration_cast<std::chrono::nanoseconds>(
        std::chrono::seconds(wait_timeout->sec));
      n += std::chrono::nanoseconds(wait_timeout->nsec);
      timeout = !conditionVariable->wait_for(lock, n, predicate);
    }
  }

  // Unlock the condition variable mutex to prevent deadlocks that can occur if
  // a listener triggers while the condition variable is being detached.
  // Listeners will no longer be prevented from changing their internal state,
  // but that should not cause issues (if a listener has data / has triggered
  // after we check, it will be caught on the next call to this function).
  lock.unlock();

  // Even if this was a non-blocking wait, signal a timeout if there's no data.
  // This makes the return behavior consistent with rcl expectations for zero timeout value.
  // Do this before detaching the listeners because the data gets cleared for guard conditions.
  bool hasData = check_waitset_for_data(subscriptions, guard_conditions, services, clients);
  if (!hasData && wait_timeout && wait_timeout->sec == 0 && wait_timeout->nsec == 0) {
    timeout = true;
  }

  if (subscriptions) {
    for (size_t i = 0; i < subscriptions->subscriber_count; ++i) {
      void * data = subscriptions->subscribers[i];
      CustomSubscriberInfo * custom_subscriber_info = static_cast<CustomSubscriberInfo *>(data);
      custom_subscriber_info->listener_->detachCondition();
      if (!custom_subscriber_info->listener_->hasData()) {
        subscriptions->subscribers[i] = 0;
      }
    }
  }

  if (clients) {
    for (size_t i = 0; i < clients->client_count; ++i) {
      void * data = clients->clients[i];
      CustomClientInfo * custom_client_info = static_cast<CustomClientInfo *>(data);
      custom_client_info->listener_->detachCondition();
      if (!custom_client_info->listener_->hasData()) {
        clients->clients[i] = 0;
      }
    }
  }

  if (services) {
    for (size_t i = 0; i < services->service_count; ++i) {
      void * data = services->services[i];
      CustomServiceInfo * custom_service_info = static_cast<CustomServiceInfo *>(data);
      custom_service_info->listener_->detachCondition();
      if (!custom_service_info->listener_->hasData()) {
        services->services[i] = 0;
      }
    }
  }

  if (guard_conditions) {
    for (size_t i = 0; i < guard_conditions->guard_condition_count; ++i) {
      void * data = guard_conditions->guard_conditions[i];
      GuardCondition * guard_condition = static_cast<GuardCondition *>(data);
      guard_condition->detachCondition();
      if (!guard_condition->getHasTriggered()) {
        guard_conditions->guard_conditions[i] = 0;
      }
    }
  }

  return timeout ? RMW_RET_TIMEOUT : RMW_RET_OK;
}
}  // extern "C"
<|endoftext|>


<commit_before>#include "Console.hpp"

#include <utility>
#include <sstream>
#include <regex>

using namespace warbler;

Console::Console()
{
}

Console::Console(Console& rhs)
{
    _commandHandlerMap = rhs._commandHandlerMap;
}

Console::~Console()
{
}

void Console::registerCommand(const std::wstring &name, t_commandHandler handler, t_consoleArgTypes_ptr argTypes)
{
    // pre-conditions
    if (name.length() == 0) { throw std::exception(); }
    if (handler == nullptr) { throw std::exception(); }

	auto handlers = _getOrCreateHandlerVector(name);
	_validateHandlerIsUnique(handlers, argTypes->size());
    handlers->push_back(ConsoleCommand(handler, argTypes));
}

t_commandHandlers_ptr Console::_getOrCreateHandlerVector(const std::wstring &name)
{
	t_commandHandlers_ptr handlers;
	if (_commandHandlerMap.count(name) != 0)
	{
		handlers = _commandHandlerMap.find(name)->second;
	}
	else
	{
		handlers = std::make_shared<t_commandHandlers>();
		_commandHandlerMap.insert(std::make_pair(name, handlers));
	}
	return handlers;
}

void Console::_validateHandlerIsUnique(t_commandHandlers_ptr handlers, int argCount)
{
    for (auto it = handlers->begin(); it != handlers->end(); ++it)
    {
        if (it->argTypes->size() == argCount) {
            throw std::exception();
        }
    }
}

void Console::executeCommand(const std::wstring input) const
{
    if (input.length() == 0) { throw std::exception(); }

    auto signature = _getCommandSignature(input);
    ConsoleCommand command = _getConsoleCommand(signature);
    t_consoleArgs_ptr args = _getConsoleArgs(input, command);
    command.handler(args);
}

t_commandHandlers_ptr Console::_getHandlersByName(const std::wstring &name) const
{
    if (_commandHandlerMap.count(name) == 0) { throw std::exception(); }
    return _commandHandlerMap.find(name)->second;
}

ConsoleCommandSignature Console::_getCommandSignature(const std::wstring &input) const
{
    ConsoleCommandSignature signature;
    std::wstringstream commandStream(input);

    commandStream >> signature.name;

    // count arguments
    std::wstring arg;
    while (!commandStream.eof())
    {
        signature.argCount++;
        commandStream >> arg;
    }

    return signature;
}

ConsoleCommand Console::_getConsoleCommand(const ConsoleCommandSignature &signature) const
{
    ConsoleCommand command;
    t_commandHandlers_ptr handlers = _getHandlersByName(signature.name);
    t_consoleArgTypes_ptr argTypes;
    for (auto it = handlers->begin(); it != handlers->end(); ++it)
    {
        if (it->argTypes->size() == signature.argCount)
        {
            command = *it;
        }
    }

    if (command.handler == nullptr || command.argTypes == nullptr)
    {
        throw std::exception();
    }

    return command;
}

t_consoleArgs_ptr Console::_getConsoleArgs(const std::wstring &input, const ConsoleCommand command) const
{
	t_consoleArgs_ptr args = std::make_shared<t_consoleArgs>();
    std::wstringstream argStream(input);
    std::wstring arg;
    argStream >> arg; // skip command name
    auto argTypeIt = command.argTypes->begin();
    while (!argStream.eof())
    {
        if (command.argTypes->end() == argTypeIt)
        {
            throw std::exception();
        }

        ConsoleArg consoleArg;
        consoleArg.type = *argTypeIt;
        argStream >> consoleArg.stringValue;
        if (consoleArg.type == ConsoleArgType::FLOAT)
        {
            consoleArg.floatValue = std::stod(consoleArg.stringValue);
            if (consoleArg.floatValue == 0.0 && consoleArg.stringValue[0] != '0')
            {
                throw std::exception();
            }
        }
        else if (consoleArg.type == ConsoleArgType::INT)
        {
            consoleArg.intValue = std::stoi(consoleArg.stringValue);
            if (consoleArg.intValue == 0 && consoleArg.stringValue[0] != '0')
            {
                throw std::exception();
            }
        }
        args->push_back(static_cast<void*>(consoleArg));
        ++argTypeIt;
    }
    return args;
}
<commit_msg>Update Console.cpp<commit_after>#include "Console.hpp"

#include <utility>
#include <sstream>
#include <regex>

using namespace warbler;

Console::Console()
{
}

Console::Console(Console& rhs)
{
    _commandHandlerMap = rhs._commandHandlerMap;
}

Console::~Console()
{
}

void Console::registerCommand(const std::wstring &name, t_commandHandler handler, t_consoleArgTypes_ptr argTypes)
{
    // pre-conditions
    if (name.length() == 0) { throw std::exception(); }
    if (handler == nullptr) { throw std::exception(); }

	auto handlers = _getOrCreateHandlerVector(name);
	_validateHandlerIsUnique(handlers, argTypes->size());
    handlers->push_back(ConsoleCommand(handler, argTypes));
}

t_commandHandlers_ptr Console::_getOrCreateHandlerVector(const std::wstring &name)
{
	t_commandHandlers_ptr handlers;
	if (_commandHandlerMap.count(name) != 0)
	{
		handlers = _commandHandlerMap.find(name)->second;
	}
	else
	{
		handlers = std::make_shared<t_commandHandlers>();
		_commandHandlerMap.insert(std::make_pair(name, handlers));
	}
	return handlers;
}

void Console::_validateHandlerIsUnique(t_commandHandlers_ptr handlers, int argCount)
{
    for (auto it = handlers->begin(); it != handlers->end(); ++it)
    {
        if (it->argTypes->size() == argCount) {
            throw std::exception();
        }
    }
}

void Console::executeCommand(const std::wstring input) const
{
    if (input.length() == 0) { throw std::exception(); }

    auto signature = _getCommandSignature(input);
    ConsoleCommand command = _getConsoleCommand(signature);
    t_consoleArgs_ptr args = _getConsoleArgs(input, command);
    command.handler(args);
}

t_commandHandlers_ptr Console::_getHandlersByName(const std::wstring &name) const
{
    if (_commandHandlerMap.count(name) == 0) { throw std::exception(); }
    return _commandHandlerMap.find(name)->second;
}

ConsoleCommandSignature Console::_getCommandSignature(const std::wstring &input) const
{
    ConsoleCommandSignature signature;
    std::wstringstream commandStream(input);

    commandStream >> signature.name;

    // count arguments
    std::wstring arg;
    while (!commandStream.eof())
    {
        signature.argCount++;
        commandStream >> arg;
    }

    return signature;
}

ConsoleCommand Console::_getConsoleCommand(const ConsoleCommandSignature &signature) const
{
    ConsoleCommand command;
    t_commandHandlers_ptr handlers = _getHandlersByName(signature.name);
    t_consoleArgTypes_ptr argTypes;
    for (auto it = handlers->begin(); it != handlers->end(); ++it)
    {
        if (it->argTypes->size() == signature.argCount)
        {
            command = *it;
        }
    }

    if (command.handler == nullptr || command.argTypes == nullptr)
    {
        throw std::exception();
    }

    return command;
}

t_consoleArgs_ptr Console::_getConsoleArgs(const std::wstring &input, const ConsoleCommand command) const
{
	t_consoleArgs_ptr args = std::make_shared<t_consoleArgs>();
    std::wstringstream argStream(input);
    std::wstring arg;
    argStream >> arg; // skip command name
    auto argTypeIt = command.argTypes->begin();
    while (!argStream.eof())
    {
        if (command.argTypes->end() == argTypeIt)
        {
            throw std::exception();
        }

        ConsoleArg consoleArg;
        consoleArg.type = *argTypeIt;
        argStream >> consoleArg.stringValue;
        if (consoleArg.type == ConsoleArgType::FLOAT)
        {
            consoleArg.floatValue = std::stod(consoleArg.stringValue);
            if (consoleArg.floatValue == 0.0 && consoleArg.stringValue[0] != '0')
            {
                throw std::exception();
            }
        }
        else if (consoleArg.type == ConsoleArgType::INT)
        {
            consoleArg.intValue = std::stoi(consoleArg.stringValue);
            if (consoleArg.intValue == 0 && consoleArg.stringValue[0] != '0')
            {
                throw std::exception();
            }
        }
        args->push_back(consoleArg);
        ++argTypeIt;
    }
    return args;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <votca/tools/globals.h>

namespace votca { namespace tools {

	bool globals::verbose = false;
	std::string globals::url = "http://www.votca.org";
	std::string globals::email = "devs@votca.org";

        std::string globals::man::option(".TP\n\\fB%1%\\fR\n%2%\n");

        std::string globals::man::header(".TH \"%1%\" 1 \"\" \"Version: %2%\"\n\n");

        std::string globals::man::name(".SH NAME\n"
                           "\n.P\n"
                           "%1% \\- Part of the VOTCA package\n"
                           "\n.P\n"
                           "For more info please visit %2%\n\n"
        );

        std::string globals::man::authors("\n.SH AUTHORS\n"
                            "\n.P\n"
                            "Written and maintained by the VOTCA Development Team <%1%>\n");

        std::string globals::man::copyright("\n.SH COPYRIGHT\n"
                              "\n.P\n\n"
                              "Copyright 2009\\-2013 The VOTCA Development Team (%1%).\n"
                              "\n.P\n"
                              "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"
                              "\n.P\n"
                              "http://www.apache.org/licenses/LICENSE\\-2.0\n"
                              "\n.P\n"
                              "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.");

        std::string globals::man::synopsis ("\n.SH SYNOPSIS\n"
                                "\n.P\n\\fB%1%\\fR [\\fIOPTION\\fR] [\\fIARGUMENT\\fR]\n");

        std::string globals::man::description ("\n.SH DESCRIPTION\n"
                                "\n.P\n%1%\n");

        std::string globals::man::options ("\n.SH OPTIONS\n");

        std::string globals::tex::section("\n\\subsection{%1%}");
        std::string globals::tex::label("\n\\label{prog:%1%}");
        std::string globals::tex::description("\n%1%");
        std::string globals::tex::option("\n\\item[ ] \\texttt{%1%} %2%");
        std::string globals::tex::options("\n\\begin{compactitem}%1%\n\\end{compactitem}\n");

}}
<commit_msg>indentation?<commit_after>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <votca/tools/globals.h>

namespace votca { namespace tools {

        bool globals::verbose = false;
        std::string globals::url = "http://www.votca.org";
        std::string globals::email = "devs@votca.org";

        std::string globals::man::option(".TP\n\\fB%1%\\fR\n%2%\n");

        std::string globals::man::header(".TH \"%1%\" 1 \"\" \"Version: %2%\"\n\n");

        std::string globals::man::name
        (
                ".SH NAME\n"
                "\n.P\n"
                "%1% \\- Part of the VOTCA package\n"
                "\n.P\n"
                "For more info please visit %2%\n\n"
        );

        std::string globals::man::authors
        (
                "\n.SH AUTHORS\n"
                "\n.P\n"
                "Written and maintained by the VOTCA Development Team <%1%>\n"
        );

        std::string globals::man::copyright
        (
                "\n.SH COPYRIGHT\n"
                "\n.P\n\n"
                "Copyright 2009\\-2013 The VOTCA Development Team (%1%).\n"
                "\n.P\n"
                "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"
                "\n.P\n"
                "http://www.apache.org/licenses/LICENSE\\-2.0\n"
                "\n.P\n"
                "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."
        );

        std::string globals::man::synopsis
        (
                "\n.SH SYNOPSIS\n"
                "\n.P\n\\fB%1%\\fR [\\fIOPTION\\fR] [\\fIARGUMENT\\fR]\n"
        );

        std::string globals::man::description
        (
                "\n.SH DESCRIPTION\n"
                "\n.P\n%1%\n"
        );

        std::string globals::man::options("\n.SH OPTIONS\n");

        std::string globals::tex::section("\n\\subsection{%1%}");
        std::string globals::tex::label("\n\\label{prog:%1%}");
        std::string globals::tex::description("\n%1%");
        std::string globals::tex::option("\n\\item[ ] \\texttt{%1%} %2%");
        std::string globals::tex::options("\n\\begin{compactitem}%1%\n\\end{compactitem}\n");

}}
<|endoftext|>


<commit_before>/*
 *            Copyright 2009-2019 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      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 "votca/xtp/threecenter.h"
#include <votca/xtp/aomatrix.h>
#include <votca/xtp/rpa.h>

namespace votca {
namespace xtp {

void RPA::UpdateRPAInputEnergies(const Eigen::VectorXd& dftenergies,
                                 const Eigen::VectorXd& gwaenergies,
                                 int qpmin) {
  int rpatotal = _rpamax - _rpamin + 1;
  _energies = dftenergies.segment(_rpamin, rpatotal);
  int gwsize = gwaenergies.size();
  int lumo = _homo + 1;

  int qpmax = qpmin + gwsize - 1;
  _energies.segment(qpmin - _rpamin, gwsize) = gwaenergies;
  double DFTgap = dftenergies(lumo) - dftenergies(_homo);
  double QPgap = gwaenergies(lumo - qpmin) - gwaenergies(_homo - qpmin);
  double shift = QPgap - DFTgap;
  int levelaboveqpmax = _rpamax - qpmax;
  _energies.segment(qpmax + 1 - _rpamin, levelaboveqpmax).array() += shift;
}

template <bool imag>
Eigen::MatrixXd RPA::calculate_epsilon(double frequency) const {
  const int size = _Mmn.auxsize();
  std::vector<Eigen::MatrixXd> thread_result = std::vector<Eigen::MatrixXd>(
      OPENMP::getMaxThreads(), Eigen::MatrixXd::Zero(size, size));
  const int lumo = _homo + 1;
  const int n_occ = lumo - _rpamin;
  const int n_unocc = _rpamax - lumo + 1;
  const double freq2 = frequency * frequency;
  const double eta2 = _eta * _eta;
#pragma omp parallel for
  for (int m_level = 0; m_level < n_occ; m_level++) {
    const double qp_energy_m = _energies(m_level);

    const Eigen::MatrixXd Mmn_RPA =
        _Mmn[m_level].block(n_occ, 0, n_unocc, size);

    const Eigen::ArrayXd deltaE =
        _energies.segment(n_occ, n_unocc).array() - qp_energy_m;
    Eigen::VectorXd denom;
    if (imag) {
      denom = 4 * deltaE / (deltaE.square() + freq2);
    } else {
      Eigen::ArrayXd deltEf = deltaE - frequency;
      Eigen::ArrayXd sum = deltEf / (deltEf.square() + eta2);
      deltEf = deltaE + frequency;
      sum += deltEf / (deltEf.square() + eta2);
      denom = 2 * sum;
    }
    auto temp = Mmn_RPA.transpose() * denom.asDiagonal();
    Eigen::MatrixXd tempresult = temp * Mmn_RPA;
    thread_result[OPENMP::getThreadId()] += tempresult;
  }
  Eigen::MatrixXd result = Eigen::MatrixXd::Identity(size, size);
  for (const auto& mat : thread_result) {
    result += mat;
  }
  return result;
}

template Eigen::MatrixXd RPA::calculate_epsilon<true>(double frequency) const;
template Eigen::MatrixXd RPA::calculate_epsilon<false>(double frequency) const;

}  // namespace xtp
}  // namespace votca
<commit_msg>refactored rpa a little<commit_after>/*
 *            Copyright 2009-2019 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      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 "votca/xtp/threecenter.h"
#include <votca/xtp/aomatrix.h>
#include <votca/xtp/rpa.h>

namespace votca {
namespace xtp {

void RPA::UpdateRPAInputEnergies(const Eigen::VectorXd& dftenergies,
                                 const Eigen::VectorXd& gwaenergies,
                                 int qpmin) {
  int rpatotal = _rpamax - _rpamin + 1;
  _energies = dftenergies.segment(_rpamin, rpatotal);
  int gwsize = gwaenergies.size();
  int lumo = _homo + 1;

  int qpmax = qpmin + gwsize - 1;
  _energies.segment(qpmin - _rpamin, gwsize) = gwaenergies;
  double DFTgap = dftenergies(lumo) - dftenergies(_homo);
  double QPgap = gwaenergies(lumo - qpmin) - gwaenergies(_homo - qpmin);
  double shift = QPgap - DFTgap;
  int levelaboveqpmax = _rpamax - qpmax;
  _energies.segment(qpmax + 1 - _rpamin, levelaboveqpmax).array() += shift;
}

template <bool imag>
Eigen::MatrixXd RPA::calculate_epsilon(double frequency) const {
  const int size = _Mmn.auxsize();
  std::vector<Eigen::MatrixXd> thread_result = std::vector<Eigen::MatrixXd>(
      OPENMP::getMaxThreads(), Eigen::MatrixXd::Zero(size, size));
  const int lumo = _homo + 1;
  const int n_occ = lumo - _rpamin;
  const int n_unocc = _rpamax - lumo + 1;
  const double freq2 = frequency * frequency;
  const double eta2 = _eta * _eta;
#pragma omp parallel for
  for (int m_level = 0; m_level < n_occ; m_level++) {
    const double qp_energy_m = _energies(m_level);

    const Eigen::MatrixXd Mmn_RPA = _Mmn[m_level].bottomRows(n_unocc);

    const Eigen::ArrayXd deltaE = _energies.tail(n_unocc).array() - qp_energy_m;
    Eigen::VectorXd denom;
    if (imag) {
      denom = 4 * deltaE / (deltaE.square() + freq2);
    } else {
      Eigen::ArrayXd deltEf = deltaE - frequency;
      Eigen::ArrayXd sum = deltEf / (deltEf.square() + eta2);
      deltEf = deltaE + frequency;
      sum += deltEf / (deltEf.square() + eta2);
      denom = 2 * sum;
    }
    thread_result[OPENMP::getThreadId()] +=
        Mmn_RPA.transpose() * denom.asDiagonal() * Mmn_RPA;
  }
  Eigen::MatrixXd result = Eigen::MatrixXd::Identity(size, size);
  for (const auto& mat : thread_result) {
    result += mat;
  }
  return result;
}

template Eigen::MatrixXd RPA::calculate_epsilon<true>(double frequency) const;
template Eigen::MatrixXd RPA::calculate_epsilon<false>(double frequency) const;

}  // namespace xtp
}  // namespace votca
<|endoftext|>