<commit_before>#include <chrono>
#include "fss-common.h"
#include "fss-server.h"
#include "fss-client.h"

int main()
{
    // Set up variables
    uint64_t a = 3;
    uint64_t b = 2;
    Fss fClient, fServer;
    ServerKeyEq k0;
    ServerKeyEq k1;

    // Initialize client, use 10 bits in domain as example
    initializeClient(&fClient, 10, 2);

    // Equality FSS test
    generateTreeEq(&fClient, &k0, &k1, a, b);

    // Initialize server
    initializeServer(&fServer, &fClient);
    mpz_class ans0, ans1, fin;

    ans0 = evaluateEq(&fServer, &k0, a);
    ans1 = evaluateEq(&fServer, &k1, a);
    fin = ans0 - ans1;
    cout << "FSS Eq Match (should be non-zero): " << fin << endl;

    ans0 = evaluateEq(&fServer, &k0, (a-1));
    ans1 = evaluateEq(&fServer, &k1, (a-1));
    fin = ans0 - ans1;
    cout << "FSS Eq No Match (should be 0): " << fin << endl;

    // Less than FSS test
    ServerKeyLt lt_k0;
    ServerKeyLt lt_k1;

    initializeClient(&fClient, 10, 2);
    generateTreeLt(&fClient, &lt_k0, &lt_k1, a, b);

    initializeServer(&fServer, &fClient);
    uint64_t lt_ans0, lt_ans1, lt_fin;

    lt_ans0 = evaluateLt(&fServer, &lt_k0, (a-1));
    lt_ans1 = evaluateLt(&fServer, &lt_k1, (a-1));
    lt_fin = lt_ans0 - lt_ans1;
    cout << "FSS Lt Match (should be non-zero): " << lt_fin << endl;

    lt_ans0 = evaluateLt(&fServer, &lt_k0, a);
    lt_ans1 = evaluateLt(&fServer, &lt_k1, a);
    lt_fin = lt_ans0 - lt_ans1;
    cout << "FSS Lt No Match (should be 0): " << lt_fin << endl;

    // Equality FSS test for multi-parties
    MPKey mp_keys[3];
    initializeClient(&fClient, 10, 3);
    generateTreeEqMParty(&fClient, a, b, mp_keys);

    initializeServer(&fServer, &fClient);
    uint32_t mp_ans0 = evaluateEqMParty(&fServer, &mp_keys[0], a);
    uint32_t mp_ans1 = evaluateEqMParty(&fServer, &mp_keys[1], a);
    uint32_t mp_ans2 = evaluateEqMParty(&fServer, &mp_keys[2], a);
    uint32_t xor_mp = mp_ans0 ^ mp_ans1 ^ mp_ans2;
    cout << "FSS Eq Multi-Party Match (should be non-zero): " << xor_mp << endl;

    mp_ans0 = evaluateEqMParty(&fServer, &mp_keys[0], (a+1));
    mp_ans1 = evaluateEqMParty(&fServer, &mp_keys[1], (a+1));
    mp_ans2 = evaluateEqMParty(&fServer, &mp_keys[2], (a+1));
    xor_mp = mp_ans0 ^ mp_ans1 ^ mp_ans2;
    cout << "FSS Eq Multi-Party No Match (should be 0): " << xor_mp << endl;

    size_t rounds = 100000;
    auto t_begin = std::chrono::high_resolution_clock::now();
    for(size_t i=0; i<rounds; i++) {
        volatile auto x = evaluateEq(&fServer, &k0, i);
    }
    for(size_t i=0; i<rounds; i++) {
        volatile auto x = evaluateLt(&fServer, &lt_k0, i);
    }
    auto t_end = std::chrono::high_resolution_clock::now();
    std::cout << "Benchmark result: " <<
     std::chrono::duration<double, std::milli>(t_end - t_begin).count()
     << " ms" << endl;
    return 1;
}
<commit_msg>Add benchmark for muli-party evaluation.<commit_after>#include <chrono>
#include "fss-common.h"
#include "fss-server.h"
#include "fss-client.h"

int main()
{
    // Set up variables
    uint64_t a = 3;
    uint64_t b = 2;
    Fss fClient, fServer;
    ServerKeyEq k0;
    ServerKeyEq k1;

    // Initialize client, use 10 bits in domain as example
    initializeClient(&fClient, 10, 2);

    // Equality FSS test
    generateTreeEq(&fClient, &k0, &k1, a, b);

    // Initialize server
    initializeServer(&fServer, &fClient);
    mpz_class ans0, ans1, fin;

    ans0 = evaluateEq(&fServer, &k0, a);
    ans1 = evaluateEq(&fServer, &k1, a);
    fin = ans0 - ans1;
    cout << "FSS Eq Match (should be non-zero): " << fin << endl;

    ans0 = evaluateEq(&fServer, &k0, (a-1));
    ans1 = evaluateEq(&fServer, &k1, (a-1));
    fin = ans0 - ans1;
    cout << "FSS Eq No Match (should be 0): " << fin << endl;

    // Less than FSS test
    ServerKeyLt lt_k0;
    ServerKeyLt lt_k1;

    initializeClient(&fClient, 10, 2);
    generateTreeLt(&fClient, &lt_k0, &lt_k1, a, b);

    initializeServer(&fServer, &fClient);
    uint64_t lt_ans0, lt_ans1, lt_fin;

    lt_ans0 = evaluateLt(&fServer, &lt_k0, (a-1));
    lt_ans1 = evaluateLt(&fServer, &lt_k1, (a-1));
    lt_fin = lt_ans0 - lt_ans1;
    cout << "FSS Lt Match (should be non-zero): " << lt_fin << endl;

    lt_ans0 = evaluateLt(&fServer, &lt_k0, a);
    lt_ans1 = evaluateLt(&fServer, &lt_k1, a);
    lt_fin = lt_ans0 - lt_ans1;
    cout << "FSS Lt No Match (should be 0): " << lt_fin << endl;

    // Equality FSS test for multi-parties
    MPKey mp_keys[3];
    initializeClient(&fClient, 10, 3);
    generateTreeEqMParty(&fClient, a, b, mp_keys);

    initializeServer(&fServer, &fClient);
    uint32_t mp_ans0 = evaluateEqMParty(&fServer, &mp_keys[0], a);
    uint32_t mp_ans1 = evaluateEqMParty(&fServer, &mp_keys[1], a);
    uint32_t mp_ans2 = evaluateEqMParty(&fServer, &mp_keys[2], a);
    uint32_t xor_mp = mp_ans0 ^ mp_ans1 ^ mp_ans2;
    cout << "FSS Eq Multi-Party Match (should be non-zero): " << xor_mp << endl;

    mp_ans0 = evaluateEqMParty(&fServer, &mp_keys[0], (a+1));
    mp_ans1 = evaluateEqMParty(&fServer, &mp_keys[1], (a+1));
    mp_ans2 = evaluateEqMParty(&fServer, &mp_keys[2], (a+1));
    xor_mp = mp_ans0 ^ mp_ans1 ^ mp_ans2;
    cout << "FSS Eq Multi-Party No Match (should be 0): " << xor_mp << endl;

    size_t rounds = 100000;
    auto t_begin = std::chrono::high_resolution_clock::now();
    for(size_t i=0; i<rounds; i++) {
        volatile auto x = evaluateEq(&fServer, &k0, i);
    }
    for(size_t i=0; i<rounds; i++) {
        volatile auto x = evaluateLt(&fServer, &lt_k0, i);
    }
    for(size_t i=0; i<rounds; i++) {
        volatile auto x = evaluateEqMParty(&fServer, &mp_keys[1], a);
    }
    auto t_end = std::chrono::high_resolution_clock::now();
    std::cout << "Benchmark result: " <<
     std::chrono::duration<double, std::milli>(t_end - t_begin).count()
     << " ms" << endl;
    return 1;
}
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2010-2011 Arjen Hiemstra <ahiemstra@heimr.nl>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "mainwindow.h"

#include <unistd.h>

#include <QtGui/QSplashScreen>

#include <KDE/KApplication>
#include <KDE/KAboutData>
#include <KDE/KCmdLineArgs>
#include <KDE/KStandardDirs>

#include <core/gluon_global.h>

#include "aboutdata.h"

int main( int argc, char** argv )
{
    KAboutData aboutData = GluonCreator::aboutData();

    KCmdLineArgs::init( argc, argv, &aboutData );
    KCmdLineOptions options;
    options.add( "+project", ki18n( "Project to open" ) );
    KCmdLineArgs::addCmdLineOptions( options );

    KApplication app;
    KCmdLineArgs* args = KCmdLineArgs::parsedArgs();

    //Create and show a splashscreen
    QPixmap splashImage( KGlobal::dirs()->locate( "appdata", "gluon-creator-splash.png" ) );
    QSplashScreen splash( splashImage );
    splash.show();
    app.processEvents();

    //Create the main window
    GluonCreator::MainWindow* window;
    if( args->count() )
    {
        window = new GluonCreator::MainWindow( args->arg( 0 ) );
    }
    else
    {
        window = new GluonCreator::MainWindow();
    }

    //Dirty hack to make the splashscreen at least visible.
    sleep( 1 );

    window->show();
    splash.finish( window );

    app.exec();
}
<commit_msg>Creator: Cleanup main a bit more.<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2010-2011 Arjen Hiemstra <ahiemstra@heimr.nl>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "mainwindow.h"

#include <unistd.h>

#include <KDE/KSplashScreen>
#include <KDE/KApplication>
#include <KDE/KAboutData>
#include <KDE/KCmdLineArgs>
#include <KDE/KStandardDirs>

#include <core/gluon_global.h>

#include "aboutdata.h"

int main( int argc, char** argv )
{
    KAboutData aboutData = GluonCreator::aboutData();

    KCmdLineArgs::init( argc, argv, &aboutData );
    KCmdLineOptions options;
    options.add( "+project", ki18n( "Project to open" ) );
    KCmdLineArgs::addCmdLineOptions( options );

    KApplication app;
    KCmdLineArgs* args = KCmdLineArgs::parsedArgs();

    //Create and show a splashscreen
    KSplashScreen splash( QPixmap( KGlobal::dirs()->locate( "appdata", "gluon-creator-splash.png" ) ) );
    splash.show();
    app.processEvents();

    //Create the main window
    GluonCreator::MainWindow* window = new GluonCreator::MainWindow( args->count() > 0 ? args->arg( 0 ) : QString() );

    //Dirty hack to make the splashscreen at least visible.
    sleep( 1 );

    window->show();
    splash.finish( window );

    app.exec();
}
<|endoftext|>


<commit_before>/*
* This source file is part of ArkGameFrame
* For the latest info, see https://github.com/ArkGame
*
* Copyright (c) 2013-2018 ArkGame authors.
*
* 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 "AFCLogModule.h"
#include "SDK/Interface/AFIPluginManager.h"
#include "spdlog/contrib/sinks/date_and_hour_file_sink.h"

AFCLogModule::AFCLogModule(AFIPluginManager* p)
{
    pPluginManager = p;

    //Create spdlog
    try
    {
        CreateLogger();
    }
    catch (std::system_error& error)
    {
        CONSOLE_LOG_NO_FILE << "Create logger failed, error = " << error.what() << std::endl;
        ARK_ASSERT_NO_EFFECT(0);
    }
}

bool AFCLogModule::Shut()
{
    spdlog::drop_all();
    return true;
}

const std::shared_ptr<spdlog::async_logger>& AFCLogModule::GetLogger()
{
    return mxLogger;
}

void AFCLogModule::CreateLogger()
{
    std::vector<spdlog::sink_ptr> sinks_vec;
    std::string log_name;
#if ARK_PLATFORM == PLATFORM_WIN
    log_name = ARK_FORMAT("..\\log\\{}.log", pPluginManager->AppName());
#else
    log_name = ARK_FORMAT("../log/{}.log", pPluginManager->AppName());
#endif

    auto date_and_hour_sink = std::make_shared<spdlog::sinks::date_and_hour_file_sink_mt>(log_name);
#if ARK_RUN_MODE == ARK_RUN_MODE_DEBUG
#if ARK_PLATFORM == PLATFORM_WIN
    auto color_sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>();
#else
    auto color_sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
#endif

    sinks_vec.push_back(color_sink);
#endif
    sinks_vec.push_back(date_and_hour_sink);

    mxLogger = std::make_shared<spdlog::async_logger>(pPluginManager->AppName(), std::begin(sinks_vec), std::end(sinks_vec), 8 * 1024, spdlog::async_overflow_policy::block_retry, nullptr, std::chrono::seconds(5));

#if ARK_RUN_MODE == ARK_RUN_MODE_DEBUG
    mxLogger->set_level(spdlog::level::level_enum::trace);
    mxLogger->set_pattern("%^[%Y%m%d %H:%M:%S.%e][%l]%v%$");
#else
    mxLogger->set_pattern("[%Y%m%d %H:%M:%S.%e][%l]%v");
#endif

    spdlog::register_logger(mxLogger);
}

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

AFCDynamicLogModule::AFCDynamicLogModule(AFIPluginManager* p)
{
    pPluginManager = p;
}

bool AFCDynamicLogModule::Shut()
{
    spdlog::drop_all();
    return true;
}

const std::shared_ptr<spdlog::async_logger>& AFCDynamicLogModule::GetLogger(const int id, const char* name)
{
    auto iter = _dynamic_loggers.find(std::make_pair(id, name));

    if (iter != _dynamic_loggers.end())
    {
        return iter->second;
    }
    else
    {
        //Create spdlog
        try
        {
            CreateLogger(id, name);
        }
        catch (std::system_error& error)
        {
            CONSOLE_LOG_NO_FILE << "Create logger failed, error = " << error.what() << std::endl;
            ARK_ASSERT_NO_EFFECT(0);
        }

        //find twice
        iter = _dynamic_loggers.find(std::make_pair(id, name));

        if (iter != _dynamic_loggers.end())
        {
            return iter->second;
        }
        else
        {
            return _null_logger;
        }
    }
}

void AFCDynamicLogModule::CreateLogger(const int id, const char* name)
{
    std::vector<spdlog::sink_ptr> sinks_vec;
    std::string log_name;
#if ARK_PLATFORM == PLATFORM_WIN
    log_name = fmt::format("..\\log\\{}\\{}.log", id, name);
#else
    log_name = fmt::format("../log/{}/{}.log", id, name);
#endif

    auto date_and_hour_sink = std::make_shared<spdlog::sinks::date_and_hour_file_sink_mt>(log_name);
#if ARK_RUN_MODE == ARK_RUN_MODE_DEBUG
#if ARK_PLATFORM == PLATFORM_WIN
    auto color_sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>();
#else
    auto color_sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
#endif

    sinks_vec.push_back(color_sink);
#endif
    sinks_vec.push_back(date_and_hour_sink);

    auto dynamic_logger = std::make_shared<spdlog::async_logger>(name, std::begin(sinks_vec), std::end(sinks_vec), 8 * 1024, spdlog::async_overflow_policy::block_retry, nullptr, std::chrono::seconds(5));

#if ARK_RUN_MODE == ARK_RUN_MODE_DEBUG
    dynamic_logger->set_level(spdlog::level::level_enum::trace);
    dynamic_logger->set_pattern("%^[%Y%m%d %H:%M:%S.%e][%l]%v%$");
#else
    dynamic_logger->set_pattern("[%Y%m%d %H:%M:%S.%e][%l]%v");
#endif

    spdlog::register_logger(dynamic_logger);
    _dynamic_loggers.insert(std::make_pair(std::make_pair(id, name), dynamic_logger));
}<commit_msg>set log flush immediately when log err+ level<commit_after>/*
* This source file is part of ArkGameFrame
* For the latest info, see https://github.com/ArkGame
*
* Copyright (c) 2013-2018 ArkGame authors.
*
* 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 "AFCLogModule.h"
#include "SDK/Interface/AFIPluginManager.h"
#include "spdlog/contrib/sinks/date_and_hour_file_sink.h"

AFCLogModule::AFCLogModule(AFIPluginManager* p)
{
    pPluginManager = p;

    //Create spdlog
    try
    {
        CreateLogger();
    }
    catch (std::system_error& error)
    {
        CONSOLE_LOG_NO_FILE << "Create logger failed, error = " << error.what() << std::endl;
        ARK_ASSERT_NO_EFFECT(0);
    }
}

bool AFCLogModule::Shut()
{
    spdlog::drop_all();
    return true;
}

const std::shared_ptr<spdlog::async_logger>& AFCLogModule::GetLogger()
{
    return mxLogger;
}

void AFCLogModule::CreateLogger()
{
    std::vector<spdlog::sink_ptr> sinks_vec;
    std::string log_name;
#if ARK_PLATFORM == PLATFORM_WIN
    log_name = ARK_FORMAT("..\\log\\{}.log", pPluginManager->AppName());
#else
    log_name = ARK_FORMAT("../log/{}.log", pPluginManager->AppName());
#endif

    auto date_and_hour_sink = std::make_shared<spdlog::sinks::date_and_hour_file_sink_mt>(log_name);
#if ARK_RUN_MODE == ARK_RUN_MODE_DEBUG
#if ARK_PLATFORM == PLATFORM_WIN
    auto color_sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>();
#else
    auto color_sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
#endif

    sinks_vec.push_back(color_sink);
#endif
    sinks_vec.push_back(date_and_hour_sink);

    mxLogger = std::make_shared<spdlog::async_logger>(pPluginManager->AppName(), std::begin(sinks_vec), std::end(sinks_vec), 1024);

#if ARK_RUN_MODE == ARK_RUN_MODE_DEBUG
    mxLogger->set_level(spdlog::level::level_enum::trace);
    mxLogger->set_pattern("%^[%Y%m%d %H:%M:%S.%e][%l]%v%$");
#else
    mxLogger->set_pattern("[%Y%m%d %H:%M:%S.%e][%l]%v");
#endif

    mxLogger->flush_on(spdlog::level::err);

    spdlog::register_logger(mxLogger);
}

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

AFCDynamicLogModule::AFCDynamicLogModule(AFIPluginManager* p)
{
    pPluginManager = p;
}

bool AFCDynamicLogModule::Shut()
{
    spdlog::drop_all();
    return true;
}

const std::shared_ptr<spdlog::async_logger>& AFCDynamicLogModule::GetLogger(const int id, const char* name)
{
    auto iter = _dynamic_loggers.find(std::make_pair(id, name));

    if (iter != _dynamic_loggers.end())
    {
        return iter->second;
    }
    else
    {
        //Create spdlog
        try
        {
            CreateLogger(id, name);
        }
        catch (std::system_error& error)
        {
            CONSOLE_LOG_NO_FILE << "Create logger failed, error = " << error.what() << std::endl;
            ARK_ASSERT_NO_EFFECT(0);
        }

        //find twice
        iter = _dynamic_loggers.find(std::make_pair(id, name));

        if (iter != _dynamic_loggers.end())
        {
            return iter->second;
        }
        else
        {
            return _null_logger;
        }
    }
}

void AFCDynamicLogModule::CreateLogger(const int id, const char* name)
{
    std::vector<spdlog::sink_ptr> sinks_vec;
    std::string log_name;
#if ARK_PLATFORM == PLATFORM_WIN
    log_name = fmt::format("..\\log\\{}\\{}.log", id, name);
#else
    log_name = fmt::format("../log/{}/{}.log", id, name);
#endif

    auto date_and_hour_sink = std::make_shared<spdlog::sinks::date_and_hour_file_sink_mt>(log_name);
#if ARK_RUN_MODE == ARK_RUN_MODE_DEBUG
#if ARK_PLATFORM == PLATFORM_WIN
    auto color_sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>();
#else
    auto color_sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
#endif

    sinks_vec.push_back(color_sink);
#endif
    sinks_vec.push_back(date_and_hour_sink);

    auto dynamic_logger = std::make_shared<spdlog::async_logger>(name, std::begin(sinks_vec), std::end(sinks_vec), 1024);

#if ARK_RUN_MODE == ARK_RUN_MODE_DEBUG
    dynamic_logger->set_level(spdlog::level::level_enum::trace);
    dynamic_logger->set_pattern("%^[%Y%m%d %H:%M:%S.%e][%l]%v%$");
#else
    dynamic_logger->set_pattern("[%Y%m%d %H:%M:%S.%e][%l]%v");
#endif
    dynamic_logger->flush_on(spdlog::level::err);

    spdlog::register_logger(dynamic_logger);
    _dynamic_loggers.insert(std::make_pair(std::make_pair(id, name), dynamic_logger));
}<|endoftext|>


<commit_before>/**
 * 6.3.3 返回数组指针
 * @Author Bob
 * @Eamil 0haizhu0@gmail.com
 * @Date 2017/8/12
 */
int main(){
  /**
   * 函数返回值不能直接返回数组，但可以返回指向数组的指针
   */
  typedef int arrT[10]; // arrT是一个类型别名，它表示的类型是含有10个整数的数组
  using arrtT = int[10]; // arrT的等价声明，参见 2.5.1
  arrT* func(int i); // func返回一个指向含有10个整数的数组的指针

  /**
   * 声明一个返回数组指针的函数：想要在声明函数时不使用类型别名，必须牢记定义的数组的维度
   * 格式：Type (*function(parameter_list))[dimension]
   */

  // 回顾
  int arr[10]; // arr是一个含有10个整数的数组
  int *p1[10]; // p1是一个含所有10个指针的数组
  int (*p2)[10] = &arr; // p2 是一个指针，它指向含有10个整数的数组

  // 定义范例
  // 分步骤解析：
  // func(int)：调用函数时需要一个int型实参
  // (*func(int))：可以对函数的返回结果执行解引用操作
  // (*func(int))[10]：解引用func的调用将得到一个大小是10的数组
  // int (*func(int))[10]：数组中的元素是int类型
  int (*func(int i))[10];

  /**
   * 使用尾置返回类型
   */

  return 0;
}
<commit_msg>6.3.3 返回数组指针<commit_after>/**
 * 6.3.3 返回数组指针
 * @Author Bob
 * @Eamil 0haizhu0@gmail.com
 * @Date 2017/8/12
 */
int main() {
  /**
   * 函数返回值不能直接返回数组，但可以返回指向数组的指针
   */
  typedef int arrT[10]; // arrT是一个类型别名，它表示的类型是含有10个整数的数组
  using arrtT = int[10]; // arrT的等价声明，参见 2.5.1
  arrT *func(int i); // func返回一个指向含有10个整数的数组的指针

  /**
   * 声明一个返回数组指针的函数：想要在声明函数时不使用类型别名，必须牢记定义的数组的维度
   * 格式：Type (*function(parameter_list))[dimension]
   */

  // 回顾
  int arr[10]; // arr是一个含有10个整数的数组
  int *p1[10]; // p1是一个含所有10个指针的数组
  int (*p2)[10] = &arr; // p2 是一个指针，它指向含有10个整数的数组

  // 定义范例
  // 分步骤解析：
  // func(int)：调用函数时需要一个int型实参
  // (*func(int))：可以对函数的返回结果执行解引用操作
  // (*func(int))[10]：解引用func的调用将得到一个大小是10的数组
  // int (*func(int))[10]：数组中的元素是int类型
  int (*func(int i))[10];

  /**
   * 使用尾置返回类型：在本应该出现返回类型的地方放置一个auto，然后使用 -> 跟上返回类型
   * 如下所示：函数返回一个指针，并且此指针指向了含有10个整数的数组。
   */
  auto func(int i) -> int (*)[10];

  /**
   * 使用decltype：如果知道函数返回的指针将指向哪个数组，就可以使用decltype关键字声明返回类型
   * 范例：odd是含有5个整数的数组，也就是函数的返回值类型，但decltype不负责把数组转换为指针，
   * 所以decltype的结果是个数组，想要表示arrPtr返回指针需要在函数声明时加上 * 。
   */
  int odd[] = {1, 3, 5, 7, 9};
  int even[] = {0, 2, 4, 6, 8};
  decltype(odd) *arrPtr(int i) {
    return (i % 2) ? &odd : &even;
  }

  return 0;
}
<|endoftext|>


<commit_before>#include "OrbitTest.h"

#include <iostream>
#include <thread>
#include <chrono>
#include <stdio.h>
#include <sstream>

static const uint32_t NUM_THREADS = 10;
static const uint32_t NUM_RECURSIVE_CALLS = 10;

#if __linux__
#define NO_INLINE __attribute__ ((noinline))
#else
#define NO_INLINE __declspec(noinline)
#endif

//-----------------------------------------------------------------------------
uint64_t GetThreadID()
{
    std::stringstream ss;
    ss << std::this_thread::get_id();
    uint64_t id = std::stoull(ss.str());
}

//-----------------------------------------------------------------------------
void SetThreadName(const std::string& a_Name)
{
#if __linux__
    pthread_setname_np(pthread_self(), a_Name.c_str());
#endif
}

//-----------------------------------------------------------------------------
OrbitTest::OrbitTest()
{
}

//-----------------------------------------------------------------------------
OrbitTest::~OrbitTest()
{
    m_ExitRequested = true;

    for (uint32_t i = 0; i < NUM_THREADS; ++i)
    {
        m_Threads[i]->join();
    }
}

//-----------------------------------------------------------------------------
void OrbitTest::Start()
{
    for (uint32_t i = 0; i < NUM_THREADS; ++i)
    {
        auto thread = std::make_shared<std::thread>(&OrbitTest::Loop, this);
        m_Threads.push_back(thread);
    }
}

//-----------------------------------------------------------------------------
void OrbitTest::Loop()
{
    SetThreadName(std::string("OrbitThread_") + std::to_string(GetThreadID()));

    while (!m_ExitRequested)
    {
        TestFunc();
    }
}
//-----------------------------------------------------------------------------
void NO_INLINE OrbitTest::TestFunc(uint32_t a_Depth)
{
    if (a_Depth == NUM_RECURSIVE_CALLS)
        return;

    TestFunc(a_Depth + 1);

    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
<commit_msg>Fix GetThreadID() in OrbitTest.cpp.<commit_after>#include "OrbitTest.h"

#include <iostream>
#include <thread>
#include <chrono>
#include <stdio.h>
#include <sstream>

static const uint32_t NUM_THREADS = 10;
static const uint32_t NUM_RECURSIVE_CALLS = 10;

#if __linux__
#define NO_INLINE __attribute__ ((noinline))
#else
#define NO_INLINE __declspec(noinline)
#endif

//-----------------------------------------------------------------------------
uint64_t GetThreadID()
{
    std::stringstream ss;
    ss << std::this_thread::get_id();
    return std::stoull(ss.str());
}

//-----------------------------------------------------------------------------
void SetThreadName(const std::string& a_Name)
{
#if __linux__
    pthread_setname_np(pthread_self(), a_Name.c_str());
#endif
}

//-----------------------------------------------------------------------------
OrbitTest::OrbitTest()
{
}

//-----------------------------------------------------------------------------
OrbitTest::~OrbitTest()
{
    m_ExitRequested = true;

    for (uint32_t i = 0; i < NUM_THREADS; ++i)
    {
        m_Threads[i]->join();
    }
}

//-----------------------------------------------------------------------------
void OrbitTest::Start()
{
    for (uint32_t i = 0; i < NUM_THREADS; ++i)
    {
        auto thread = std::make_shared<std::thread>(&OrbitTest::Loop, this);
        m_Threads.push_back(thread);
    }
}

//-----------------------------------------------------------------------------
void OrbitTest::Loop()
{
    SetThreadName(std::string("OrbitThread_") + std::to_string(GetThreadID()));

    while (!m_ExitRequested)
    {
        TestFunc();
    }
}
//-----------------------------------------------------------------------------
void NO_INLINE OrbitTest::TestFunc(uint32_t a_Depth)
{
    if (a_Depth == NUM_RECURSIVE_CALLS)
        return;

    TestFunc(a_Depth + 1);

    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
<|endoftext|>


<commit_before>/*-------------------------------
PASA LA CALCULADORA
Autores:
Jaime Sevilla Molina
Victor Gonzalez
Fecha
2014/11
Version: 2.0
---------------------------------*/

//BIBLIOTECAS
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
#include <fstream>
#include <iomanip>

using namespace std;

//TIPOS PROPIOS
typedef enum tJugador
{
	Nadie,
	Jugador,
	Automata
};

typedef enum tDificultad
{
		Facil,
		Dificil,
		Imposible
};

//FUNCIONES
//FUNCIONES DE JUEGO

string saludar ();
void despedirse (tJugador ganador, string nombre);
int menu();
bool acerca();
tJugador pasaCalculadora();
tJugador quienEmpieza();

tDificultad seleccionar_dificultad();
bool mismaFila(int ultimo, int nuevo);
bool mismaColumna(int ultimo, int nuevo);
bool digitoValido(int ultimo, int nuevo);

//FUNCIONES DE IA NIVEL 1
int digitoAleatorio();

int digitoAutomata(int ultimo);

//FUNCIONES DE JUGADOR

int digitoPersona();

int digitoPersona(int ultimo);

char mNumero(int ultimo, int n);

void mostrarCalculadora(int ultimo);

/* Las funciones a continuacion se implementaran en un futuro
//FUNCIONES DE INFORME
//Actualiza el archivo informePC.txt con los tres argumentos. En caso de no encontrar
//el archivo, lo crea y devuelve false; en otro caso devuelve true.
bool actInforme(int jugadas, int ganadas, int abandonos);
*/

//FUNCIONES DE DIFICULTAD AVANZADA
int botDificil(int ultimo);

int main()
{
	tJugador ganador;
	int opcion;

	string nombre = saludar();
	//Bucle Menu
	do
	{
		opcion = menu();
		if(opcion == 1){
			ganador = pasaCalculadora();
			despedirse(ganador, nombre);
		}
		else if(opcion == 2) acerca();

	}
	while(opcion != 0);

	cout << "Hasta la proxima " << nombre << "(pulsa enter)";
	cin;

	return 0;
}

//Saluda al jugador y le pregunta su nombre
string saludar()
{
	string nombre;
	cout << "Bienvenido a Pasa la calculadora!" << endl;
	cout << "Como te llamas? ";
	cin >> nombre;
	cout << "Hola " << nombre << endl << endl;
	return nombre;
}

//Se despide del jugador, la despedida varia segun gane el jugador, el automata o ninguno de ellos (el jugador abandone)
void despedirse(tJugador ganador, string nombre)
{
	if (ganador == Nadie){
		cout << "Abandonas, " << nombre << "? Ohhh..." << endl << endl;
	}
	else if (ganador == Jugador){
		cout << "Enhorabuena " << nombre << ", has ganado!" << endl << endl;
	}
	else /*if (ganador == Automata)*/{
		cout << "Lo siento " << nombre << ", he ganado" << endl << endl;
	}
}

//Proporciona al jugador la posibilidad de jugar, ver las instrucciones del juego o salir.
int menu()
{
	int seleccionar = -1; //Error flag
	cout << "1 - Jugar" << endl;
	cout << "2 - Acerca de" << endl;
	cout << "0 - Salir" << endl;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> seleccionar;

		if(cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (seleccionar < 0 || seleccionar > 2)
		{
			cout << "Error! Introduce un digito entre 0 y 2" << endl;
			seleccionar = -1;
		}

	}
	while (seleccionar == -1);

	return seleccionar;
}

//Muestra el archivo "acerca.txt" siempre que este no contenga errores
bool acerca()
{

	bool ok;
	ifstream acerca;
	char c;

	acerca.open("acerca.txt");

	if(acerca.is_open())
	{
		acerca.get(c); //Lee el primer caracter

		while(!acerca.fail()) //Mientras la lectura no falle
		{
			cout << c;
			acerca.get(c); //Lee el siguiente caracter
		}

		ok = true;
		acerca.close();

	}
	else
	{
		ok = false;
		cout << "Error, el archivo 'acerca.txt' no existe" << endl;
	}

	return ok;
}

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora()
{
	//Variables
	tJugador turno; tDificultad dificultad;
	int total = 0, ultimoDigito = 0;
	const int META=31;
		//Inicializar partida

	dificultad = seleccionar_dificultad();

	srand(time(NULL));//Semilla
	turno = quienEmpieza();

	//Bucle de juego
	do
	{
		//Turno jugador
		if (turno == Jugador)
		{
			ultimoDigito = digitoPersona(ultimoDigito);
			turno = Automata;
		}
		//Turno bot
		else /*if (turno == Automata)*/
		{
			ultimoDigito = digitoAutomata(ultimoDigito);
			turno = Jugador;
		}
		total += ultimoDigito;
		cout << "Total = " << total << endl;
	}
	while ((total < META) && (ultimoDigito != 0));

	if (ultimoDigito == 0) turno = Nadie;
	//Si el jugador abandona, no gana nadie

	return turno;
}

//Decide aleatoriamente quien empieza la partida, si el automata o el jugador
tJugador quienEmpieza()
{
	if (rand() % 2)
	{
		cout << "Tu empiezas" << endl;
		return Jugador;
	}
	else
	{
		cout << "Empiezo yo" << endl;
		return Automata;
	}
}

//Define que numeros se encuentran en la misma fila que el ultimo pulsado
bool mismaFila(int ultimo, int nuevo)
{
	int filaUltimo, filaNuevo;
	filaUltimo = ((ultimo - 1)/3);
	filaNuevo = ((nuevo - 1)/3);
	return (filaUltimo) == (filaNuevo);
}

//Define que numeros se encuentran en la misma columna que el ultimo
bool mismaColumna(int ultimo, int nuevo)
{
	int columnaUltimo, columnaNuevo;
	columnaUltimo = (ultimo % 3);
	columnaNuevo = (nuevo % 3);
	return columnaUltimo == columnaNuevo;
}

//Determina que digitos se pueden pulsar en funcion de las reglas del juego
bool digitoValido(int ultimo, int nuevo)  //hay un bug
{
	if (ultimo == 0) return true;//Si es el primer turno, todos los numeros valen

	return ((mismaFila(ultimo, nuevo))||(mismaColumna(ultimo, nuevo)))&&(ultimo!=nuevo);
}

//Genera un digito aleatorio
int digitoAleatorio()
{
	return (rand() % 9) + 1;
}

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo)
{
	int digito;

	do
	{
	digito = digitoAleatorio();
	}
	while (!digitoValido(ultimo, digito));

	cout << "Elijo el numero " << digito << endl;

	return digito;
}

//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona()
{
	int digito = -1;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> digito;

		if (cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (digito < 0 || digito > 9)
		{
		cout << "Error! Introduce un digito entre 0 y 9" << endl;
		digito = -1;
		}

	}
	while (digito == -1);

	return digito;
}

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo)
{
	int digito = -1; //-1 es mi error flag

	mostrarCalculadora(ultimo);

	do
	{
		digito = digitoPersona();
		if (!digitoValido(ultimo, digito))
		{
			cout << "Error! El digito debe estar en la misma fila y columna que el ultimo" << endl;
			digito = -1;
		}
	}
	while (digito == -1);

	cout << "Has elegido el " << digito << endl;

	return digito;
}

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n)
{
	if(digitoValido(ultimo, n))
	{
		//system ("color 02");
		return char (n+int('0'));

	}
	else
	{
		//system ("color 04");
		return ' ';
	}
}

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo)
{
	for (int i = 7; i<10; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 4; i<7; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 1; i<4; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	//system ("color 07");
}

tDificultad seleccionar_dificultad(){
	cout << "Elige dificultad:" << endl;
	cout << "1 - Facil" << endl;
	cout << "2 - Dificil" << endl;
	cout << "3 - Imposible" << endl;

	if

int botDificil(int total, int ultimo)
{
	for (int i=1, i<10, i++)
	{
		if digitoValido(ultimo, i)
		{
			if (total + i == 30) return i; //Intenta ganar dejando la suma en 30
			else if ((total + i == 29) && (!digitoValido(i, 1))) return i;
			//Si la suma queda en 29 y el adversario no puede coger el 1, ganamos
			else if ((total + i == 28) && (i==6 || i==9)) return i;
			//Si la suma queda en 28 y el adv no puede coger el 1 o el 2, ganamos
		}
	}
	return digitoAutomata(ultimo);
}<commit_msg>Implementado digito_entre()<commit_after>/*-------------------------------
PASA LA CALCULADORA
Autores:
Jaime Sevilla Molina
Victor Gonzalez
Fecha
2014/11
Version: 2.0
---------------------------------*/

//BIBLIOTECAS
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
#include <fstream>
#include <iomanip>

using namespace std;

//TIPOS PROPIOS
typedef enum tJugador
{
	Nadie,
	Jugador,
	Automata
};

typedef enum tDificultad
{
		Facil,
		Dificil,
		Imposible
};

//FUNCIONES
//FUNCIONES DE JUEGO

string saludar();
void despedirse (tJugador ganador, string nombre);
int menu();
bool acerca();
tJugador pasaCalculadora();
tJugador quienEmpieza();

tDificultad seleccionar_dificultad();
bool mismaFila(int ultimo, int nuevo);
bool mismaColumna(int ultimo, int nuevo);
bool digitoValido(int ultimo, int nuevo);

//FUNCIONES DE IA NIVEL 1
int digitoAleatorio();

int digitoAutomata(int ultimo);

//FUNCIONES DE JUGADOR

int digitoEntre(int a, int b);

int digitoPersona(int ultimo);

char mNumero(int ultimo, int n);

void mostrarCalculadora(int ultimo);

/* Las funciones a continuacion se implementaran en un futuro
//FUNCIONES DE INFORME
//Actualiza el archivo informePC.txt con los tres argumentos. En caso de no encontrar
//el archivo, lo crea y devuelve false; en otro caso devuelve true.
bool actInforme(int jugadas, int ganadas, int abandonos);
*/

//FUNCIONES DE DIFICULTAD AVANZADA
int botDificil(int ultimo);

int main()
{
	tJugador ganador;
	int opcion;

	string nombre = saludar();
	//Bucle Menu
	do
	{
		opcion = menu();
		if(opcion == 1){
			ganador = pasaCalculadora();
			despedirse(ganador, nombre);
		}
		else if(opcion == 2) acerca();

	}
	while(opcion != 0);

	cout << "Hasta la proxima " << nombre << "(pulsa enter)";
	cin;

	return 0;
}

//Saluda al jugador y le pregunta su nombre
string saludar()
{
	string nombre;
	cout << "Bienvenido a Pasa la calculadora!" << endl;
	cout << "Como te llamas? ";
	cin >> nombre;
	cout << "Hola " << nombre << endl << endl;
	return nombre;
}

//Se despide del jugador, la despedida varia segun gane el jugador, el automata o ninguno de ellos (el jugador abandone)
void despedirse(tJugador ganador, string nombre)
{
	if (ganador == Nadie){
		cout << "Abandonas, " << nombre << "? Ohhh..." << endl << endl;
	}
	else if (ganador == Jugador){
		cout << "Enhorabuena " << nombre << ", has ganado!" << endl << endl;
	}
	else /*if (ganador == Automata)*/{
		cout << "Lo siento " << nombre << ", he ganado" << endl << endl;
	}
}

//Proporciona al jugador la posibilidad de jugar, ver las instrucciones del juego o salir.
int menu()
{
	int seleccionar = -1; //Error flag
	cout << "1 - Jugar" << endl;
	cout << "2 - Acerca de" << endl;
	cout << "0 - Salir" << endl;

	seleccionar = digitoEntre(0,2);

	return seleccionar;
}

//Muestra el archivo "acerca.txt" siempre que este no contenga errores
bool acerca()
{

	bool ok;
	ifstream acerca;
	char c;

	acerca.open("acerca.txt");

	if(acerca.is_open())
	{
		acerca.get(c); //Lee el primer caracter

		while(!acerca.fail()) //Mientras la lectura no falle
		{
			cout << c;
			acerca.get(c); //Lee el siguiente caracter
		}

		ok = true;
		acerca.close();

	}
	else
	{
		ok = false;
		cout << "Error, el archivo 'acerca.txt' no existe" << endl;
	}

	return ok;
}

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora()
{
	//Variables
	tJugador turno; tDificultad dificultad;
	int total = 0, ultimoDigito = 0;
	const int META=31;
		//Inicializar partida

	dificultad = seleccionar_dificultad();

	srand(time(NULL));//Semilla
	turno = quienEmpieza();

	//Bucle de juego
	do
	{
		//Turno jugador
		if (turno == Jugador)
		{
			ultimoDigito = digitoPersona(ultimoDigito);
			turno = Automata;
		}
		//Turno bot
		else /*if (turno == Automata)*/
		{
			ultimoDigito = digitoAutomata(ultimoDigito);
			turno = Jugador;
		}
		total += ultimoDigito;
		cout << "Total = " << total << endl;
	}
	while ((total < META) && (ultimoDigito != 0));

	if (ultimoDigito == 0) turno = Nadie;
	//Si el jugador abandona, no gana nadie

	return turno;
}

//Decide aleatoriamente quien empieza la partida, si el automata o el jugador
tJugador quienEmpieza()
{
	if (rand() % 2)
	{
		cout << "Tu empiezas" << endl;
		return Jugador;
	}
	else
	{
		cout << "Empiezo yo" << endl;
		return Automata;
	}
}

//Define que numeros se encuentran en la misma fila que el ultimo pulsado
bool mismaFila(int ultimo, int nuevo)
{
	int filaUltimo, filaNuevo;
	filaUltimo = ((ultimo - 1)/3);
	filaNuevo = ((nuevo - 1)/3);
	return (filaUltimo) == (filaNuevo);
}

//Define que numeros se encuentran en la misma columna que el ultimo
bool mismaColumna(int ultimo, int nuevo)
{
	int columnaUltimo, columnaNuevo;
	columnaUltimo = (ultimo % 3);
	columnaNuevo = (nuevo % 3);
	return columnaUltimo == columnaNuevo;
}

//Determina que digitos se pueden pulsar en funcion de las reglas del juego
bool digitoValido(int ultimo, int nuevo)  //hay un bug
{
	if (ultimo == 0) return true;//Si es el primer turno, todos los numeros valen

	return ((mismaFila(ultimo, nuevo))||(mismaColumna(ultimo, nuevo)))&&(ultimo!=nuevo);
}

//Genera un digito aleatorio
int digitoAleatorio()
{
	return (rand() % 9) + 1;
}

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo)
{
	int digito;

	do
	{
	digito = digitoAleatorio();
	}
	while (!digitoValido(ultimo, digito));

	cout << "Elijo el numero " << digito << endl;

	return digito;
}

//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoEntre(int a, int b)
{
	int digito = -1;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> digito;

		if (cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (digito < a || digito > b)
		{
		cout << "Error! Introduce un digito entre " << a << " y " << b << endl;
		digito = -1;
		}

	}
	while (digito == -1);

	return digito;
}

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo)
{
	int digito = -1; //-1 es mi error flag

	mostrarCalculadora(ultimo);

	do
	{
		digito = digitoEntre(0,9);
		if (!digitoValido(ultimo, digito))
		{
			cout << "Error! El digito debe estar en la misma fila y columna que el ultimo" << endl;
			digito = -1;
		}
	}
	while (digito == -1);

	cout << "Has elegido el " << digito << endl;

	return digito;
}

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n)
{
	if(digitoValido(ultimo, n))
	{
		//system ("color 02");
		return char (n+int('0'));

	}
	else
	{
		//system ("color 04");
		return ' ';
	}
}

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo)
{
	for (int i = 7; i<10; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 4; i<7; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 1; i<4; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	//system ("color 07");
}

tDificultad seleccionar_dificultad()
{
	cout << "Elige dificultad:" << endl;
	cout << "1 - Facil" << endl;
	cout << "2 - Dificil" << endl;
	cout << "3 - Imposible" << endl;

	int opcion = digitoEntre(1,3);

	if (opcion == 1) return Facil;
	else if (opcion == 2) return Dificil;
	else /*if (opcion == 3)*/ return Imposible;
}

int botDificil(int total, int ultimo)
{
	for (int i=1; i<10; i++)
	{
		if (digitoValido(ultimo, i))
		{
			if (total + i == 30) return i; //Intenta ganar dejando la suma en 30
			else if ((total + i == 29) && (!digitoValido(i, 1))) return i;
			//Si la suma queda en 29 y el adversario no puede coger el 1, ganamos
			else if ((total + i == 28) && (i==6 || i==9)) return i;
			//Si la suma queda en 28 y el adv no puede coger el 1 o el 2, ganamos
		}
	}
	return digitoAutomata(ultimo);
}<|endoftext|>


<commit_before>//
//  Sequencer.cpp
//  WISTSample
//
//  Created by Nobuhisa Okamura on 11/05/19.
//  Copyright 2011 KORG INC. All rights reserved.
//

#include <vector>
#include <mutex>
#include <algorithm>

#include <mach/mach_time.h>

#include "Sequencer.h"
#include "AudioIO.h"

//  ---------------------------------------------------------------------------
//      Sequencer::Sequencer
//  ---------------------------------------------------------------------------
Sequencer::Sequencer(float samplingRate, int numberOfTracks, int numberOfSteps, int stepsPerBeat) :
samplingRate_(samplingRate),
numberOfTracks_(numberOfTracks),
numberOfSteps_(numberOfSteps),
stepsPerBeat_(stepsPerBeat),
isRunning_(false),
currentStep_(0),
stepFrameLength_(0),
currentFrame_(0),
trigger_(false),
seq_(),
commands_(),
listeners_(),
commandsMutex_()
{
    // 各ステップの再生有無をstd::vector<bool>で記憶するトラックを4本作成
    SetupTracks();
}

//  ---------------------------------------------------------------------------
//      Sequencer::~Sequencer
//  ---------------------------------------------------------------------------
Sequencer::~Sequencer(void)
{
}

//  ---------------------------------------------------------------------------
//      Sequencer::SetupTracks
//  ---------------------------------------------------------------------------
void
Sequencer::SetupTracks()
{
    seq_.clear();
    for (int trackNo = 0; trackNo < numberOfTracks_; ++trackNo)
    {
        std::vector<bool>   partSeq(numberOfSteps_, false);
        seq_.push_back(partSeq);
    }
}

enum
{
    kSeqCommand_Start = 0,
    kSeqCommand_Stop,
    kSeqCommand_UpdateTempo,
    kSeqCommand_UpdateNumSteps,
};

//  ---------------------------------------------------------------------------
//      Sequencer::ProcessCommand
//  ---------------------------------------------------------------------------
inline void
Sequencer::ProcessCommand(SeqCommandEvent& event)
{
    switch (event.command)
    {
        case kSeqCommand_Start:
            if (!isRunning_)
            {
                const float tempo = event.floatValue;
                currentStep_ = 0;
                currentFrame_ = 0;
                stepFrameLength_ = samplingRate_ * 60.0f / tempo / stepsPerBeat_;
                trigger_ = true;
                isRunning_ = true;
            }
            break;
        case kSeqCommand_Stop:
            if (isRunning_)
            {
                isRunning_ = false;
            }
            break;
        case kSeqCommand_UpdateTempo:
            if (1)
            {
                const float tempo = event.floatValue;
                stepFrameLength_ = samplingRate_ * 60.0f / tempo / stepsPerBeat_;
            }
            break;
        case kSeqCommand_UpdateNumSteps:
            if (1) {
                const int numberOfSteps = static_cast<int>(event.floatValue);
                if (numberOfSteps != numberOfSteps_) {
                    numberOfSteps_ = numberOfSteps;
                    SetupTracks();
                }
            }
            break;
        default:
            break;
    }
}

//  ---------------------------------------------------------------------------
//      Sequencer::ProcessCommands
//  ---------------------------------------------------------------------------
inline int
Sequencer::ProcessCommands(AudioIO* io, int offset, int length)
{
    if (!commands_.empty())
    {
        const uint64_t  hostTime = (io != NULL) ? io->GetHostTime() : 0;
        const uint64_t  latency = (io != NULL) ? io->GetLatency() : 0;
        mach_timebase_info_data_t timeInfo;
        ::mach_timebase_info(&timeInfo);
        {
            std::lock_guard<std::mutex> lock(commandsMutex_);
            std::sort(commands_.begin(), commands_.end(), Sequencer::SortEventFunctor);
            for (auto ite = commands_.begin(); ite != commands_.end();)
            {
                bool    doProcess = false;
                if (ite->hostTime == 0)    //  now
                {
                    doProcess = true;
                }
                else if (io != NULL)
                {
                    const int64_t   delta = ite->hostTime - hostTime;
                    const int64_t   deltaNanosec = delta * timeInfo.numer / timeInfo.denom + latency;
                    const int32_t   sampleOffset = static_cast<int32_t>(static_cast<double>(deltaNanosec) * samplingRate_ / 1000000000);
                    if (sampleOffset < offset + length)
                    {
                        const int   eventFrame = sampleOffset - offset;
                        if (eventFrame > 0)
                        {
                            return eventFrame;
                        }
                        doProcess = true;
                    }
                }
                if (doProcess)
                {
                    this->ProcessCommand(*ite);
                    ite = commands_.erase(ite);
                }
                else
                {
                    ++ite;
                }
            }
        }
    }
    return length;
}

//  ---------------------------------------------------------------------------
//      Sequencer::ProcessTrigger
//  ---------------------------------------------------------------------------
inline void
Sequencer::ProcessTrigger(int offset, const std::vector<int> &trackIndexes)
{
    for (auto listener : listeners_)
    {
        listener->NoteOnViaSequencer(offset, trackIndexes, currentStep_);
    }
}

//  ---------------------------------------------------------------------------
//      Sequencer::ProcessTrigger
//  ---------------------------------------------------------------------------
inline void
Sequencer::ProcessTrigger(int offset)
{
    if (trigger_ && (currentFrame_ >= 0))
    {
        if ((currentStep_ >= 0) && (currentStep_ < numberOfSteps_))
        {
            // ここでONトラック(int)だけを集めてProcessTriggerに渡す
            std::vector<int> triggeredTracks;
            const int   numOfTrack = static_cast<const int>(seq_.size());
            for (int trackNo = 0; trackNo < numOfTrack; ++trackNo)
            {
                const auto&   partSeq = seq_[trackNo];
                if (partSeq[currentStep_])
                {
                    triggeredTracks.push_back(trackNo);
                }
            }
            this->ProcessTrigger(offset + currentFrame_, triggeredTracks);
        }
        trigger_ = false;
    }
}

//  ---------------------------------------------------------------------------
//      Sequencer::ProcessSequence
//  ---------------------------------------------------------------------------
inline void
Sequencer::ProcessSequence(int offset, int length)
{
    int rest = length;
    int startFrame = offset;
    while (rest > 0)
    {
        const int   processedLen = std::min<int>(rest, std::max<int>(stepFrameLength_ - currentFrame_, 1));
        this->ProcessTrigger(startFrame);
        currentFrame_ += processedLen;
        rest -= processedLen;
        startFrame += processedLen;
        if (currentFrame_ >= stepFrameLength_)
        {
            currentFrame_ -= stepFrameLength_;
            ++currentStep_;
            if (currentStep_ > numberOfSteps_ - 1)
            {
                currentStep_ = 0;
            }
            trigger_ = true;
        }
    }
}

//  ---------------------------------------------------------------------------
//      Sequencer::Process
//  ---------------------------------------------------------------------------
int
Sequencer::Process(AudioIO* io, int offset, int length)
{
    const int   result = this->ProcessCommands(io, offset, length);
    if (isRunning_ && (result > 0))
    {
        this->ProcessSequence(offset, result);
    }
    return result;
}

#pragma mark -
//  ---------------------------------------------------------------------------
//      Sequencer::AddListener
//  ---------------------------------------------------------------------------
void
Sequencer::AddListener(SequencerListener* listener)
{
    listeners_.push_back(listener);
}

//  ---------------------------------------------------------------------------
//      Sequencer::RemoveListener
//  ---------------------------------------------------------------------------
void
Sequencer::RemoveListener(SequencerListener* listener)
{
    listeners_.erase(std::remove(std::begin(listeners_),
                                 std::end(listeners_),
                                 listener), std::end(listeners_));
}

#pragma mark -
//  ---------------------------------------------------------------------------
//      Sequencer::AddCommand
//  ---------------------------------------------------------------------------
void
Sequencer::AddCommand(const uint64_t hostTime, const int cmd, const float param0)
{
    std::lock_guard<std::mutex> lock(commandsMutex_);
    const SeqCommandEvent   event = { hostTime, cmd, param0 };
    commands_.push_back(event);
}

//  ---------------------------------------------------------------------------
//      Sequencer::Start
//  ---------------------------------------------------------------------------
void
Sequencer::Start(const uint64_t hostTime, const float tempo)
{
    this->AddCommand(hostTime, kSeqCommand_Start, tempo);
}

//  ---------------------------------------------------------------------------
//      Sequencer::Stop
//  ---------------------------------------------------------------------------
void
Sequencer::Stop(const uint64_t hostTime)
{
    this->AddCommand(hostTime, kSeqCommand_Stop, 0.0f/* ignore */);
}

//  ---------------------------------------------------------------------------
//      Sequencer::UpdateTempo
//  ---------------------------------------------------------------------------
void
Sequencer::UpdateTempo(const uint64_t hostTime, const float tempo)
{
    this->AddCommand(hostTime, kSeqCommand_UpdateTempo, tempo);
}

//  ---------------------------------------------------------------------------
//      Sequencer::UpdateNumSteps
//  ---------------------------------------------------------------------------
void
Sequencer::UpdateNumSteps(const uint64_t hostTime, const int numberOfSteps)
{
    this->AddCommand(hostTime, kSeqCommand_UpdateNumSteps, numberOfSteps);
}

//  ---------------------------------------------------------------------------
//      Sequencer::UpdateTrack
//  ---------------------------------------------------------------------------
void
Sequencer::UpdateTrack(const int trackNo, const std::vector<bool> &sequence)
{
    if ((trackNo >= 0) && (trackNo < static_cast<int>(seq_.size())))
    {
        seq_[trackNo] = sequence;
    }
}
<commit_msg>Refactoring<commit_after>//
//  Sequencer.cpp
//  WISTSample
//
//  Created by Nobuhisa Okamura on 11/05/19.
//  Copyright 2011 KORG INC. All rights reserved.
//

#include <vector>
#include <mutex>
#include <algorithm>

#include <mach/mach_time.h>

#include "Sequencer.h"
#include "AudioIO.h"

//  ---------------------------------------------------------------------------
//      Sequencer::Sequencer
//  ---------------------------------------------------------------------------
Sequencer::Sequencer(float samplingRate, int numberOfTracks, int numberOfSteps, int stepsPerBeat) :
samplingRate_(samplingRate),
numberOfTracks_(numberOfTracks),
numberOfSteps_(numberOfSteps),
stepsPerBeat_(stepsPerBeat),
isRunning_(false),
currentStep_(0),
stepFrameLength_(0),
currentFrame_(0),
trigger_(false),
seq_(),
commands_(),
listeners_(),
commandsMutex_()
{
    // 各ステップの再生有無をstd::vector<bool>で記憶するトラックを4本作成
    SetupTracks();
}

//  ---------------------------------------------------------------------------
//      Sequencer::~Sequencer
//  ---------------------------------------------------------------------------
Sequencer::~Sequencer(void)
{
}

//  ---------------------------------------------------------------------------
//      Sequencer::SetupTracks
//  ---------------------------------------------------------------------------
void
Sequencer::SetupTracks()
{
    seq_.clear();
    for (int trackNo = 0; trackNo < numberOfTracks_; ++trackNo)
    {
        std::vector<bool>   partSeq(numberOfSteps_, false);
        seq_.push_back(partSeq);
    }
}

enum
{
    kSeqCommand_Start = 0,
    kSeqCommand_Stop,
    kSeqCommand_UpdateTempo,
    kSeqCommand_UpdateNumSteps,
};

//  ---------------------------------------------------------------------------
//      Sequencer::ProcessCommand
//  ---------------------------------------------------------------------------
inline void
Sequencer::ProcessCommand(SeqCommandEvent& event)
{
    switch (event.command)
    {
        case kSeqCommand_Start:
            if (!isRunning_)
            {
                const float tempo = event.floatValue;
                currentStep_ = 0;
                currentFrame_ = 0;
                stepFrameLength_ = samplingRate_ * 60.0f / tempo / stepsPerBeat_;
                trigger_ = true;
                isRunning_ = true;
            }
            break;
        case kSeqCommand_Stop:
            if (isRunning_)
            {
                isRunning_ = false;
            }
            break;
        case kSeqCommand_UpdateTempo:
            if (1)
            {
                const float tempo = event.floatValue;
                stepFrameLength_ = samplingRate_ * 60.0f / tempo / stepsPerBeat_;
            }
            break;
        case kSeqCommand_UpdateNumSteps:
            if (1) {
                const int numberOfSteps = static_cast<int>(event.floatValue);
                if (numberOfSteps != numberOfSteps_) {
                    numberOfSteps_ = numberOfSteps;
                    SetupTracks();
                }
            }
            break;
        default:
            break;
    }
}

//  ---------------------------------------------------------------------------
//      Sequencer::ProcessCommands
//  ---------------------------------------------------------------------------
inline int
Sequencer::ProcessCommands(AudioIO* io, int offset, int length)
{
    if (!commands_.empty())
    {
        const uint64_t  hostTime = (io != NULL) ? io->GetHostTime() : 0;
        const uint64_t  latency = (io != NULL) ? io->GetLatency() : 0;
        mach_timebase_info_data_t timeInfo;
        ::mach_timebase_info(&timeInfo);
        {
            std::lock_guard<std::mutex> lock(commandsMutex_);
            std::sort(commands_.begin(), commands_.end(), Sequencer::SortEventFunctor);
            for (auto ite = commands_.begin(); ite != commands_.end();)
            {
                bool    doProcess = false;
                if (ite->hostTime == 0)    //  now
                {
                    doProcess = true;
                }
                else if (io != NULL)
                {
                    const int64_t   delta = ite->hostTime - hostTime;
                    const int64_t   deltaNanosec = delta * timeInfo.numer / timeInfo.denom + latency;
                    const int32_t   sampleOffset = static_cast<int32_t>(static_cast<double>(deltaNanosec) * samplingRate_ / 1000000000);
                    if (sampleOffset < offset + length)
                    {
                        const int   eventFrame = sampleOffset - offset;
                        if (eventFrame > 0)
                        {
                            return eventFrame;
                        }
                        doProcess = true;
                    }
                }
                if (doProcess)
                {
                    this->ProcessCommand(*ite);
                    ite = commands_.erase(ite);
                }
                else
                {
                    ++ite;
                }
            }
        }
    }
    return length;
}

//  ---------------------------------------------------------------------------
//      Sequencer::ProcessTrigger
//  ---------------------------------------------------------------------------
inline void
Sequencer::ProcessTrigger(int offset, const std::vector<int> &trackIndexes)
{
    for (auto listener : listeners_)
    {
        listener->NoteOnViaSequencer(offset + currentFrame_, trackIndexes, currentStep_);
    }
}

//  ---------------------------------------------------------------------------
//      Sequencer::ProcessTrigger
//  ---------------------------------------------------------------------------
inline void
Sequencer::ProcessTrigger(int offset)
{
    if (trigger_ && (currentFrame_ >= 0))
    {
        if ((currentStep_ >= 0) && (currentStep_ < numberOfSteps_))
        {
            // ここでONトラック(int)だけを集めてProcessTriggerに渡す
            std::vector<int> triggeredTracks;
            const int   numOfTrack = static_cast<const int>(seq_.size());
            for (int trackNo = 0; trackNo < numOfTrack; ++trackNo)
            {
                const auto&   partSeq = seq_[trackNo];
                if (partSeq[currentStep_])
                {
                    triggeredTracks.push_back(trackNo);
                }
            }
            this->ProcessTrigger(offset, triggeredTracks);
        }
        trigger_ = false;
    }
}

//  ---------------------------------------------------------------------------
//      Sequencer::ProcessSequence
//  ---------------------------------------------------------------------------
inline void
Sequencer::ProcessSequence(int offset, int length)
{
    int rest = length;
    int startFrame = offset;
    while (rest > 0)
    {
        const int   processedLen = std::min<int>(rest, std::max<int>(stepFrameLength_ - currentFrame_, 1));
        this->ProcessTrigger(startFrame);
        currentFrame_ += processedLen;
        rest -= processedLen;
        startFrame += processedLen;
        if (currentFrame_ >= stepFrameLength_)
        {
            currentFrame_ -= stepFrameLength_;
            ++currentStep_;
            if (currentStep_ > numberOfSteps_ - 1)
            {
                currentStep_ = 0;
            }
            trigger_ = true;
        }
    }
}

//  ---------------------------------------------------------------------------
//      Sequencer::Process
//  ---------------------------------------------------------------------------
int
Sequencer::Process(AudioIO* io, int offset, int length)
{
    const int   result = this->ProcessCommands(io, offset, length);
    if (isRunning_ && (result > 0))
    {
        this->ProcessSequence(offset, result);
    }
    return result;
}

#pragma mark -
//  ---------------------------------------------------------------------------
//      Sequencer::AddListener
//  ---------------------------------------------------------------------------
void
Sequencer::AddListener(SequencerListener* listener)
{
    listeners_.push_back(listener);
}

//  ---------------------------------------------------------------------------
//      Sequencer::RemoveListener
//  ---------------------------------------------------------------------------
void
Sequencer::RemoveListener(SequencerListener* listener)
{
    listeners_.erase(std::remove(std::begin(listeners_),
                                 std::end(listeners_),
                                 listener), std::end(listeners_));
}

#pragma mark -
//  ---------------------------------------------------------------------------
//      Sequencer::AddCommand
//  ---------------------------------------------------------------------------
void
Sequencer::AddCommand(const uint64_t hostTime, const int cmd, const float param0)
{
    std::lock_guard<std::mutex> lock(commandsMutex_);
    const SeqCommandEvent   event = { hostTime, cmd, param0 };
    commands_.push_back(event);
}

//  ---------------------------------------------------------------------------
//      Sequencer::Start
//  ---------------------------------------------------------------------------
void
Sequencer::Start(const uint64_t hostTime, const float tempo)
{
    this->AddCommand(hostTime, kSeqCommand_Start, tempo);
}

//  ---------------------------------------------------------------------------
//      Sequencer::Stop
//  ---------------------------------------------------------------------------
void
Sequencer::Stop(const uint64_t hostTime)
{
    this->AddCommand(hostTime, kSeqCommand_Stop, 0.0f/* ignore */);
}

//  ---------------------------------------------------------------------------
//      Sequencer::UpdateTempo
//  ---------------------------------------------------------------------------
void
Sequencer::UpdateTempo(const uint64_t hostTime, const float tempo)
{
    this->AddCommand(hostTime, kSeqCommand_UpdateTempo, tempo);
}

//  ---------------------------------------------------------------------------
//      Sequencer::UpdateNumSteps
//  ---------------------------------------------------------------------------
void
Sequencer::UpdateNumSteps(const uint64_t hostTime, const int numberOfSteps)
{
    this->AddCommand(hostTime, kSeqCommand_UpdateNumSteps, numberOfSteps);
}

//  ---------------------------------------------------------------------------
//      Sequencer::UpdateTrack
//  ---------------------------------------------------------------------------
void
Sequencer::UpdateTrack(const int trackNo, const std::vector<bool> &sequence)
{
    if ((trackNo >= 0) && (trackNo < static_cast<int>(seq_.size())))
    {
        seq_[trackNo] = sequence;
    }
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTreeDifferenceFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkTreeDifferenceFilter.h"

#include "vtkDataSetAttributes.h"
#include "vtkDoubleArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkStringArray.h"
#include "vtkTree.h"

vtkStandardNewMacro(vtkTreeDifferenceFilter);

//---------------------------------------------------------------------------
vtkTreeDifferenceFilter::vtkTreeDifferenceFilter()
{
  this->SetNumberOfInputPorts(2);
  this->SetNumberOfOutputPorts(1);

  this->IdArrayName = 0;
  this->ComparisonArrayName = 0;
  this->OutputArrayName = 0;
  this->ComparisonArrayIsVertexData = false;
}

//---------------------------------------------------------------------------
vtkTreeDifferenceFilter::~vtkTreeDifferenceFilter()
{
  // release memory
  this->SetIdArrayName(0);
  this->SetComparisonArrayName(0);
  this->SetOutputArrayName(0);
}

//---------------------------------------------------------------------------
int vtkTreeDifferenceFilter::FillInputPortInformation(int port, vtkInformation *info)
{
  if(port == 0)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTree");
    }
  else if(port == 1)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTree");
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
    }

  return 1;
}

//---------------------------------------------------------------------------
int vtkTreeDifferenceFilter::RequestData(
  vtkInformation*,
  vtkInformationVector** inputVector,
  vtkInformationVector* outputVector)
{
  vtkInformation* tree1_info = inputVector[0]->GetInformationObject(0);
  vtkTree* tree1 = vtkTree::SafeDownCast(
    tree1_info->Get(vtkDataObject::DATA_OBJECT()));

  // Copy the structure into the output.
  vtkTree* outputTree = vtkTree::GetData(outputVector);

  vtkInformation* tree2_info = inputVector[1]->GetInformationObject(0);
  if(!tree2_info)
    {
    // If no second tree provided, we're done
    outputTree->CheckedShallowCopy(tree1);
    return 0;
    }

  vtkTree* tree2 = vtkTree::SafeDownCast(
    tree2_info->Get(vtkDataObject::DATA_OBJECT()));

  if (this->IdArrayName != 0)
    {
    if (!this->GenerateMapping(tree1, tree2))
      {
      return 0;
      }
    }
  else
    {
    this->VertexMap.clear();
    for (vtkIdType vertex = 0; vertex < tree1->GetNumberOfVertices(); ++vertex)
      {
      this->VertexMap[vertex] = vertex;
      }

    this->EdgeMap.clear();
    for (vtkIdType edge = 0; edge < tree1->GetNumberOfEdges(); ++edge)
      {
      this->EdgeMap[edge] = edge;
      }
    }

  vtkSmartPointer<vtkDoubleArray> resultArray =
    this->ComputeDifference(tree1, tree2);

  if (!outputTree->CheckedShallowCopy(tree1))
    {
    vtkErrorMacro(<<"Invalid tree structure.");
    return 0;
    }

  if (this->ComparisonArrayIsVertexData)
    {
    outputTree->GetVertexData()->AddArray(resultArray);
    }
  else
    {
    outputTree->GetEdgeData()->AddArray(resultArray);
    }

  return 1;
}

//---------------------------------------------------------------------------
bool vtkTreeDifferenceFilter::GenerateMapping(vtkTree *tree1, vtkTree *tree2)
{
  this->VertexMap.clear();
  this->VertexMap.assign(tree1->GetNumberOfVertices(), -1);

  this->EdgeMap.clear();
  this->EdgeMap.assign(tree1->GetNumberOfEdges(), -1);

  vtkStringArray *nodeNames1 = vtkStringArray::SafeDownCast(
    tree1->GetVertexData()->GetAbstractArray(this->IdArrayName));
  if (nodeNames1 == NULL)
    {
    vtkErrorMacro("tree #1's VertexData does not have a vtkStringArray named "
      << this->IdArrayName);
    return false;
    }

  vtkStringArray *nodeNames2 = vtkStringArray::SafeDownCast(
    tree2->GetVertexData()->GetAbstractArray(this->IdArrayName));
  if (nodeNames2 == NULL)
    {
    vtkErrorMacro("tree #2's VertexData does not have a vtkStringArray named "
      << this->IdArrayName);
    return false;
    }

  vtkIdType root1 = tree1->GetRoot();
  vtkIdType root2 = tree2->GetRoot();

  vtkIdType edgeId1 = -1;
  vtkIdType edgeId2 = -1;

  // iterate over the vertex names for tree #1, finding the corresponding
  // vertex in tree #2.
  for (vtkIdType vertexItr = 0; vertexItr < nodeNames1->GetNumberOfTuples();
       ++vertexItr)
    {
    vtkIdType vertexId1 = vertexItr;
    std::string nodeName = nodeNames1->GetValue(vertexId1);
    if (nodeName.compare("") == 0)
      {
      continue;
      }

    // record this correspondence in the maps
    vtkIdType vertexId2 = nodeNames2->LookupValue(nodeName);
    if (vertexId2 == -1)
      {
      vtkWarningMacro("tree #2 does not contain a vertex named " << nodeName);
      continue;
      }
    this->VertexMap[vertexId1] = vertexId2;

    if (vertexId1 == root1 || vertexId2 == root2)
      {
      continue;
      }

    edgeId1 = tree1->GetEdgeId(tree1->GetParent(vertexId1), vertexId1);
    edgeId2 = tree2->GetEdgeId(tree2->GetParent(vertexId2), vertexId2);
    this->EdgeMap[edgeId1] = edgeId2;

    // ascend the tree until we reach the root, mapping parent vertices to
    // each other along the way.
    while (tree1->GetParent(vertexId1) != root1 &&
           tree2->GetParent(vertexId2) != root2)
      {
      vertexId1 = tree1->GetParent(vertexId1);
      vertexId2 = tree2->GetParent(vertexId2);
      if (this->VertexMap[vertexId1] == -1)
        {
        this->VertexMap[vertexId1] = vertexId2;
        edgeId1 = tree1->GetEdgeId(tree1->GetParent(vertexId1), vertexId1);
        edgeId2 = tree2->GetEdgeId(tree2->GetParent(vertexId2), vertexId2);
        this->EdgeMap[edgeId1] = edgeId2;
        }
      }
    }

  return true;
}

//---------------------------------------------------------------------------
vtkSmartPointer<vtkDoubleArray>
vtkTreeDifferenceFilter::ComputeDifference(vtkTree *tree1, vtkTree *tree2)
{
  if (this->ComparisonArrayName == 0)
    {
    vtkErrorMacro("ComparisonArrayName has not been set.");
    return NULL;
    }

  vtkDataSetAttributes *treeData1, *treeData2;
  const char *dataName;
  if (this->ComparisonArrayIsVertexData)
    {
    treeData1 = tree1->GetVertexData();
    treeData2 = tree2->GetVertexData();
    dataName = "VertexData";
    }
  else
    {
    treeData1 = tree1->GetEdgeData();
    treeData2 = tree2->GetEdgeData();
    dataName = "EdgeData";
    }

  vtkDataArray *arrayToCompare1 =
    treeData1->GetArray(this->ComparisonArrayName);
  if (arrayToCompare1 == NULL)
    {
    vtkErrorMacro("tree #1's " << dataName <<
      " does not have a vtkDoubleArray named " << this->IdArrayName);
    return NULL;
    }

  vtkDataArray *arrayToCompare2 =
    treeData2->GetArray(this->ComparisonArrayName);
  if (arrayToCompare2 == NULL)
    {
    vtkErrorMacro("tree #2's " << dataName <<
      " does not have a vtkDoubleArray named " << this->IdArrayName);
    return NULL;
    }

  vtkSmartPointer<vtkDoubleArray> resultArray =
    vtkSmartPointer<vtkDoubleArray>::New();
  resultArray->SetNumberOfValues(arrayToCompare1->GetNumberOfTuples());
  resultArray->FillComponent(0, vtkMath::Nan());

  if (this->OutputArrayName == 0)
    {
    resultArray->SetName("difference");
    }
  else
    {
    resultArray->SetName(this->OutputArrayName);
    }

  vtkIdType treeId2;
  for (vtkIdType treeId1 = 0; treeId1 < arrayToCompare1->GetNumberOfTuples();
       ++treeId1)
    {
    if (this->ComparisonArrayIsVertexData)
      {
      treeId2 = this->VertexMap[treeId1];
      }
    else
      {
      treeId2 = this->EdgeMap[treeId1];
      }
    double result =
      arrayToCompare1->GetTuple1(treeId1) - arrayToCompare2->GetTuple1(treeId2);
    resultArray->SetValue(treeId1, result);
    }

  return resultArray;
}

//---------------------------------------------------------------------------
void vtkTreeDifferenceFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  if (this->IdArrayName)
    {
    os << indent << "IdArrayName: "
       << this->IdArrayName << std::endl;
    }
  else
    {
    os << indent << "IdArrayName: "
       << "(None)" << std::endl;
    }
  if (this->ComparisonArrayName)
    {
    os << indent << "ComparisonArrayName: "
       << this->ComparisonArrayName << std::endl;
    }
  else
    {
    os << indent << "ComparisonArrayName: "
       << "(None)" << std::endl;
    }
  if (this->OutputArrayName)
    {
    os << indent << "OutputArrayName: "
       << this->OutputArrayName << std::endl;
    }
  else
    {
    os << indent << "OutputArrayName: "
       << "(None)" << std::endl;
    }
  os << indent << "ComparisonArrayIsVertexData: "
     << this->ComparisonArrayIsVertexData << std::endl;
}
<commit_msg>fix error message<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTreeDifferenceFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkTreeDifferenceFilter.h"

#include "vtkDataSetAttributes.h"
#include "vtkDoubleArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkStringArray.h"
#include "vtkTree.h"

vtkStandardNewMacro(vtkTreeDifferenceFilter);

//---------------------------------------------------------------------------
vtkTreeDifferenceFilter::vtkTreeDifferenceFilter()
{
  this->SetNumberOfInputPorts(2);
  this->SetNumberOfOutputPorts(1);

  this->IdArrayName = 0;
  this->ComparisonArrayName = 0;
  this->OutputArrayName = 0;
  this->ComparisonArrayIsVertexData = false;
}

//---------------------------------------------------------------------------
vtkTreeDifferenceFilter::~vtkTreeDifferenceFilter()
{
  // release memory
  this->SetIdArrayName(0);
  this->SetComparisonArrayName(0);
  this->SetOutputArrayName(0);
}

//---------------------------------------------------------------------------
int vtkTreeDifferenceFilter::FillInputPortInformation(int port, vtkInformation *info)
{
  if(port == 0)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTree");
    }
  else if(port == 1)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTree");
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
    }

  return 1;
}

//---------------------------------------------------------------------------
int vtkTreeDifferenceFilter::RequestData(
  vtkInformation*,
  vtkInformationVector** inputVector,
  vtkInformationVector* outputVector)
{
  vtkInformation* tree1_info = inputVector[0]->GetInformationObject(0);
  vtkTree* tree1 = vtkTree::SafeDownCast(
    tree1_info->Get(vtkDataObject::DATA_OBJECT()));

  // Copy the structure into the output.
  vtkTree* outputTree = vtkTree::GetData(outputVector);

  vtkInformation* tree2_info = inputVector[1]->GetInformationObject(0);
  if(!tree2_info)
    {
    // If no second tree provided, we're done
    outputTree->CheckedShallowCopy(tree1);
    return 0;
    }

  vtkTree* tree2 = vtkTree::SafeDownCast(
    tree2_info->Get(vtkDataObject::DATA_OBJECT()));

  if (this->IdArrayName != 0)
    {
    if (!this->GenerateMapping(tree1, tree2))
      {
      return 0;
      }
    }
  else
    {
    this->VertexMap.clear();
    for (vtkIdType vertex = 0; vertex < tree1->GetNumberOfVertices(); ++vertex)
      {
      this->VertexMap[vertex] = vertex;
      }

    this->EdgeMap.clear();
    for (vtkIdType edge = 0; edge < tree1->GetNumberOfEdges(); ++edge)
      {
      this->EdgeMap[edge] = edge;
      }
    }

  vtkSmartPointer<vtkDoubleArray> resultArray =
    this->ComputeDifference(tree1, tree2);

  if (!outputTree->CheckedShallowCopy(tree1))
    {
    vtkErrorMacro(<<"Invalid tree structure.");
    return 0;
    }

  if (this->ComparisonArrayIsVertexData)
    {
    outputTree->GetVertexData()->AddArray(resultArray);
    }
  else
    {
    outputTree->GetEdgeData()->AddArray(resultArray);
    }

  return 1;
}

//---------------------------------------------------------------------------
bool vtkTreeDifferenceFilter::GenerateMapping(vtkTree *tree1, vtkTree *tree2)
{
  this->VertexMap.clear();
  this->VertexMap.assign(tree1->GetNumberOfVertices(), -1);

  this->EdgeMap.clear();
  this->EdgeMap.assign(tree1->GetNumberOfEdges(), -1);

  vtkStringArray *nodeNames1 = vtkStringArray::SafeDownCast(
    tree1->GetVertexData()->GetAbstractArray(this->IdArrayName));
  if (nodeNames1 == NULL)
    {
    vtkErrorMacro("tree #1's VertexData does not have a vtkStringArray named "
      << this->IdArrayName);
    return false;
    }

  vtkStringArray *nodeNames2 = vtkStringArray::SafeDownCast(
    tree2->GetVertexData()->GetAbstractArray(this->IdArrayName));
  if (nodeNames2 == NULL)
    {
    vtkErrorMacro("tree #2's VertexData does not have a vtkStringArray named "
      << this->IdArrayName);
    return false;
    }

  vtkIdType root1 = tree1->GetRoot();
  vtkIdType root2 = tree2->GetRoot();

  vtkIdType edgeId1 = -1;
  vtkIdType edgeId2 = -1;

  // iterate over the vertex names for tree #1, finding the corresponding
  // vertex in tree #2.
  for (vtkIdType vertexItr = 0; vertexItr < nodeNames1->GetNumberOfTuples();
       ++vertexItr)
    {
    vtkIdType vertexId1 = vertexItr;
    std::string nodeName = nodeNames1->GetValue(vertexId1);
    if (nodeName.compare("") == 0)
      {
      continue;
      }

    // record this correspondence in the maps
    vtkIdType vertexId2 = nodeNames2->LookupValue(nodeName);
    if (vertexId2 == -1)
      {
      vtkWarningMacro("tree #2 does not contain a vertex named " << nodeName);
      continue;
      }
    this->VertexMap[vertexId1] = vertexId2;

    if (vertexId1 == root1 || vertexId2 == root2)
      {
      continue;
      }

    edgeId1 = tree1->GetEdgeId(tree1->GetParent(vertexId1), vertexId1);
    edgeId2 = tree2->GetEdgeId(tree2->GetParent(vertexId2), vertexId2);
    this->EdgeMap[edgeId1] = edgeId2;

    // ascend the tree until we reach the root, mapping parent vertices to
    // each other along the way.
    while (tree1->GetParent(vertexId1) != root1 &&
           tree2->GetParent(vertexId2) != root2)
      {
      vertexId1 = tree1->GetParent(vertexId1);
      vertexId2 = tree2->GetParent(vertexId2);
      if (this->VertexMap[vertexId1] == -1)
        {
        this->VertexMap[vertexId1] = vertexId2;
        edgeId1 = tree1->GetEdgeId(tree1->GetParent(vertexId1), vertexId1);
        edgeId2 = tree2->GetEdgeId(tree2->GetParent(vertexId2), vertexId2);
        this->EdgeMap[edgeId1] = edgeId2;
        }
      }
    }

  return true;
}

//---------------------------------------------------------------------------
vtkSmartPointer<vtkDoubleArray>
vtkTreeDifferenceFilter::ComputeDifference(vtkTree *tree1, vtkTree *tree2)
{
  if (this->ComparisonArrayName == 0)
    {
    vtkErrorMacro("ComparisonArrayName has not been set.");
    return NULL;
    }

  vtkDataSetAttributes *treeData1, *treeData2;
  const char *dataName;
  if (this->ComparisonArrayIsVertexData)
    {
    treeData1 = tree1->GetVertexData();
    treeData2 = tree2->GetVertexData();
    dataName = "VertexData";
    }
  else
    {
    treeData1 = tree1->GetEdgeData();
    treeData2 = tree2->GetEdgeData();
    dataName = "EdgeData";
    }

  vtkDataArray *arrayToCompare1 =
    treeData1->GetArray(this->ComparisonArrayName);
  if (arrayToCompare1 == NULL)
    {
    vtkErrorMacro("tree #1's " << dataName <<
      " does not have a vtkDoubleArray named " << this->ComparisonArrayName);
    return NULL;
    }

  vtkDataArray *arrayToCompare2 =
    treeData2->GetArray(this->ComparisonArrayName);
  if (arrayToCompare2 == NULL)
    {
    vtkErrorMacro("tree #2's " << dataName <<
      " does not have a vtkDoubleArray named " << this->ComparisonArrayName);
    return NULL;
    }

  vtkSmartPointer<vtkDoubleArray> resultArray =
    vtkSmartPointer<vtkDoubleArray>::New();
  resultArray->SetNumberOfValues(arrayToCompare1->GetNumberOfTuples());
  resultArray->FillComponent(0, vtkMath::Nan());

  if (this->OutputArrayName == 0)
    {
    resultArray->SetName("difference");
    }
  else
    {
    resultArray->SetName(this->OutputArrayName);
    }

  vtkIdType treeId2;
  for (vtkIdType treeId1 = 0; treeId1 < arrayToCompare1->GetNumberOfTuples();
       ++treeId1)
    {
    if (this->ComparisonArrayIsVertexData)
      {
      treeId2 = this->VertexMap[treeId1];
      }
    else
      {
      treeId2 = this->EdgeMap[treeId1];
      }
    double result =
      arrayToCompare1->GetTuple1(treeId1) - arrayToCompare2->GetTuple1(treeId2);
    resultArray->SetValue(treeId1, result);
    }

  return resultArray;
}

//---------------------------------------------------------------------------
void vtkTreeDifferenceFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  if (this->IdArrayName)
    {
    os << indent << "IdArrayName: "
       << this->IdArrayName << std::endl;
    }
  else
    {
    os << indent << "IdArrayName: "
       << "(None)" << std::endl;
    }
  if (this->ComparisonArrayName)
    {
    os << indent << "ComparisonArrayName: "
       << this->ComparisonArrayName << std::endl;
    }
  else
    {
    os << indent << "ComparisonArrayName: "
       << "(None)" << std::endl;
    }
  if (this->OutputArrayName)
    {
    os << indent << "OutputArrayName: "
       << this->OutputArrayName << std::endl;
    }
  else
    {
    os << indent << "OutputArrayName: "
       << "(None)" << std::endl;
    }
  os << indent << "ComparisonArrayIsVertexData: "
     << this->ComparisonArrayIsVertexData << std::endl;
}
<|endoftext|>


<commit_before>#include "vector.h"
#include "../nullc.h"
#include "typeinfo.h"

#include <memory>

namespace NULLCVector
{
#pragma pack(push, 4)
	struct vector
	{
		unsigned int	elemType;
		unsigned int	flags;
		unsigned int	elemSize;
		NULLCAutoArray	data;
		unsigned int	size;
	};

	struct vector_iterator
	{
		vector*			arr;
		unsigned int	pos;
	};
#pragma pack(pop)

	void ConstructVector(vector* vec, unsigned int type, int reserved)
	{
		vec->elemType = type;
		vec->flags = nullcIsPointer(type);
		vec->size = 0;
		vec->elemSize = nullcGetTypeSize(type);
		vec->data.typeID = type;
		if(reserved)
		{
			vec->data.ptr = (char*)nullcAllocate(vec->elemSize * reserved);
			vec->data.len = reserved;
		}else{
			vec->data.ptr = NULL;
			vec->data.len = 0;
		}
	}

	void VectorPushBack(NULLCRef val, vector* vec)
	{
		// Check that we received type that is equal to array element type
		if(val.typeID != (vec->flags ? nullcGetSubType(vec->elemType) : vec->elemType))
		{
			nullcThrowError("vector::push_back received value (%s) that is different from vector type (%s)", nullcGetTypeName(val.typeID), nullcGetTypeName(vec->elemType));
			return;
		}
		// If not enough space
		if(vec->size == vec->data.len)
		{
			// Allocate new
			unsigned int newSize = 32 > vec->data.len ? 32 : (vec->data.len << 1) + vec->data.len;
			char *newData = (char*)nullcAllocate(vec->elemSize * newSize);
			memcpy(newData, vec->data.ptr, vec->elemSize * vec->data.len);
			vec->data.len = newSize;
			vec->data.ptr = newData;
		}
		memcpy(vec->data.ptr + vec->elemSize * vec->size, vec->flags ? (char*)&val.ptr : val.ptr, vec->elemSize);
		vec->size++;
	}

	void VectorPopBack(vector* vec)
	{
		if(!vec->size)
		{
			nullcThrowError("vector::pop_back called on an empty vector");
			return;
		}
		vec->size--;
	}

	NULLCRef VectorFront(vector* vec)
	{
		NULLCRef ret = { 0, 0 };
		if(!vec->size)
		{
			nullcThrowError("vector::front called on an empty vector");
			return ret;
		}
		ret.typeID = (vec->flags ? nullcGetSubType(vec->elemType) : vec->elemType);
		ret.ptr = vec->flags ? *(char**)vec->data.ptr : vec->data.ptr;
		return ret;
	}

	NULLCRef VectorBack(vector* vec)
	{
		NULLCRef ret = { 0, 0 };
		if(!vec->size)
		{
			nullcThrowError("vector::back called on an empty vector");
			return ret;
		}
		ret.typeID = (vec->flags ? nullcGetSubType(vec->elemType) : vec->elemType);
		ret.ptr = vec->flags ? ((char**)vec->data.ptr)[vec->size - 1] : (vec->data.ptr + vec->elemSize * (vec->size - 1));
		return ret;
	}

	NULLCRef VectorIndex(vector* vec, unsigned int index)
	{
		NULLCRef ret = { 0, 0 };
		if(index >= vec->size)
		{
			nullcThrowError("operator[] array index out of bounds");
			return ret;
		}
		ret.typeID = (vec->flags ? nullcGetSubType(vec->elemType) : vec->elemType);
		ret.ptr = vec->flags ? ((char**)vec->data.ptr)[index] : (vec->data.ptr + vec->elemSize * index);
		return ret;
	}

	void VectorReserve(unsigned int size, vector* vec)
	{
		// If not enough space
		if(size > vec->data.len)
		{
			// Allocate new
			char *newData = (char*)nullcAllocate(vec->elemSize * size);
			memcpy(newData, vec->data.ptr, vec->elemSize * vec->data.len);
			vec->data.len = size;
			vec->data.ptr = newData;
		}
	}

	void VectorResize(unsigned int size, vector* vec)
	{
		VectorReserve(size, vec);
		vec->size = size;
	}

	void VectorClear(vector* vec)
	{
		vec->size = 0;
	}

	void VectorDestroy(vector* vec)
	{
		vec->size = 0;
		vec->data.len = 0;
		vec->data.ptr = NULL;
	}

	int VectorSize(vector* vec)
	{
		return vec->size;
	}

	int VectorCapacity(vector* vec)
	{
		return vec->data.len;
	}

	NULLCRef VectorNext(vector_iterator* iter)
	{
		NULLCRef ret;
		ret.typeID = (iter->arr->flags ? nullcGetSubType(iter->arr->elemType) : iter->arr->elemType);
		ret.ptr =  iter->arr->flags ? ((char**)iter->arr->data.ptr)[iter->pos] : iter->arr->data.ptr + iter->arr->elemSize * iter->pos;
		iter->pos++;
		return ret;
	}
	int VectorHasNext(vector_iterator* iter)
	{
		return iter->arr && iter->pos < iter->arr->size;
	}

}

#define REGISTER_FUNC(funcPtr, name, index) if(!nullcBindModuleFunction("old.vector", (void(*)())NULLCVector::funcPtr, name, index)) return false;
bool	nullcInitVectorModule()
{
	REGISTER_FUNC(ConstructVector, "cConstructVector", 0);

	REGISTER_FUNC(VectorPushBack, "vector::push_back", 0);
	REGISTER_FUNC(VectorPopBack, "vector::pop_back", 0);
	REGISTER_FUNC(VectorFront, "vector::front", 0);
	REGISTER_FUNC(VectorBack, "vector::back", 0);
	REGISTER_FUNC(VectorIndex, "[]", 0);
	REGISTER_FUNC(VectorReserve, "vector::reserve", 0);
	REGISTER_FUNC(VectorResize, "vector::resize", 0);
	REGISTER_FUNC(VectorClear, "vector::clear", 0);
	REGISTER_FUNC(VectorDestroy, "vector::destroy", 0);
	REGISTER_FUNC(VectorSize, "vector::size", 0);
	REGISTER_FUNC(VectorCapacity, "vector::capacity", 0);

	REGISTER_FUNC(VectorNext, "vector_iterator::next", 0);
	REGISTER_FUNC(VectorHasNext, "vector_iterator::hasnext", 0);

	return true;
}
<commit_msg>linux: compilation fix<commit_after>#include "vector.h"
#include "../nullc.h"
#include "typeinfo.h"

#include <memory>
#include <memory.h>

namespace NULLCVector
{
#pragma pack(push, 4)
	struct vector
	{
		unsigned int	elemType;
		unsigned int	flags;
		unsigned int	elemSize;
		NULLCAutoArray	data;
		unsigned int	size;
	};

	struct vector_iterator
	{
		vector*			arr;
		unsigned int	pos;
	};
#pragma pack(pop)

	void ConstructVector(vector* vec, unsigned int type, int reserved)
	{
		vec->elemType = type;
		vec->flags = nullcIsPointer(type);
		vec->size = 0;
		vec->elemSize = nullcGetTypeSize(type);
		vec->data.typeID = type;
		if(reserved)
		{
			vec->data.ptr = (char*)nullcAllocate(vec->elemSize * reserved);
			vec->data.len = reserved;
		}else{
			vec->data.ptr = NULL;
			vec->data.len = 0;
		}
	}

	void VectorPushBack(NULLCRef val, vector* vec)
	{
		// Check that we received type that is equal to array element type
		if(val.typeID != (vec->flags ? nullcGetSubType(vec->elemType) : vec->elemType))
		{
			nullcThrowError("vector::push_back received value (%s) that is different from vector type (%s)", nullcGetTypeName(val.typeID), nullcGetTypeName(vec->elemType));
			return;
		}
		// If not enough space
		if(vec->size == vec->data.len)
		{
			// Allocate new
			unsigned int newSize = 32 > vec->data.len ? 32 : (vec->data.len << 1) + vec->data.len;
			char *newData = (char*)nullcAllocate(vec->elemSize * newSize);
			memcpy(newData, vec->data.ptr, vec->elemSize * vec->data.len);
			vec->data.len = newSize;
			vec->data.ptr = newData;
		}
		memcpy(vec->data.ptr + vec->elemSize * vec->size, vec->flags ? (char*)&val.ptr : val.ptr, vec->elemSize);
		vec->size++;
	}

	void VectorPopBack(vector* vec)
	{
		if(!vec->size)
		{
			nullcThrowError("vector::pop_back called on an empty vector");
			return;
		}
		vec->size--;
	}

	NULLCRef VectorFront(vector* vec)
	{
		NULLCRef ret = { 0, 0 };
		if(!vec->size)
		{
			nullcThrowError("vector::front called on an empty vector");
			return ret;
		}
		ret.typeID = (vec->flags ? nullcGetSubType(vec->elemType) : vec->elemType);
		ret.ptr = vec->flags ? *(char**)vec->data.ptr : vec->data.ptr;
		return ret;
	}

	NULLCRef VectorBack(vector* vec)
	{
		NULLCRef ret = { 0, 0 };
		if(!vec->size)
		{
			nullcThrowError("vector::back called on an empty vector");
			return ret;
		}
		ret.typeID = (vec->flags ? nullcGetSubType(vec->elemType) : vec->elemType);
		ret.ptr = vec->flags ? ((char**)vec->data.ptr)[vec->size - 1] : (vec->data.ptr + vec->elemSize * (vec->size - 1));
		return ret;
	}

	NULLCRef VectorIndex(vector* vec, unsigned int index)
	{
		NULLCRef ret = { 0, 0 };
		if(index >= vec->size)
		{
			nullcThrowError("operator[] array index out of bounds");
			return ret;
		}
		ret.typeID = (vec->flags ? nullcGetSubType(vec->elemType) : vec->elemType);
		ret.ptr = vec->flags ? ((char**)vec->data.ptr)[index] : (vec->data.ptr + vec->elemSize * index);
		return ret;
	}

	void VectorReserve(unsigned int size, vector* vec)
	{
		// If not enough space
		if(size > vec->data.len)
		{
			// Allocate new
			char *newData = (char*)nullcAllocate(vec->elemSize * size);
			memcpy(newData, vec->data.ptr, vec->elemSize * vec->data.len);
			vec->data.len = size;
			vec->data.ptr = newData;
		}
	}

	void VectorResize(unsigned int size, vector* vec)
	{
		VectorReserve(size, vec);
		vec->size = size;
	}

	void VectorClear(vector* vec)
	{
		vec->size = 0;
	}

	void VectorDestroy(vector* vec)
	{
		vec->size = 0;
		vec->data.len = 0;
		vec->data.ptr = NULL;
	}

	int VectorSize(vector* vec)
	{
		return vec->size;
	}

	int VectorCapacity(vector* vec)
	{
		return vec->data.len;
	}

	NULLCRef VectorNext(vector_iterator* iter)
	{
		NULLCRef ret;
		ret.typeID = (iter->arr->flags ? nullcGetSubType(iter->arr->elemType) : iter->arr->elemType);
		ret.ptr =  iter->arr->flags ? ((char**)iter->arr->data.ptr)[iter->pos] : iter->arr->data.ptr + iter->arr->elemSize * iter->pos;
		iter->pos++;
		return ret;
	}
	int VectorHasNext(vector_iterator* iter)
	{
		return iter->arr && iter->pos < iter->arr->size;
	}

}

#define REGISTER_FUNC(funcPtr, name, index) if(!nullcBindModuleFunction("old.vector", (void(*)())NULLCVector::funcPtr, name, index)) return false;
bool	nullcInitVectorModule()
{
	REGISTER_FUNC(ConstructVector, "cConstructVector", 0);

	REGISTER_FUNC(VectorPushBack, "vector::push_back", 0);
	REGISTER_FUNC(VectorPopBack, "vector::pop_back", 0);
	REGISTER_FUNC(VectorFront, "vector::front", 0);
	REGISTER_FUNC(VectorBack, "vector::back", 0);
	REGISTER_FUNC(VectorIndex, "[]", 0);
	REGISTER_FUNC(VectorReserve, "vector::reserve", 0);
	REGISTER_FUNC(VectorResize, "vector::resize", 0);
	REGISTER_FUNC(VectorClear, "vector::clear", 0);
	REGISTER_FUNC(VectorDestroy, "vector::destroy", 0);
	REGISTER_FUNC(VectorSize, "vector::size", 0);
	REGISTER_FUNC(VectorCapacity, "vector::capacity", 0);

	REGISTER_FUNC(VectorNext, "vector_iterator::next", 0);
	REGISTER_FUNC(VectorHasNext, "vector_iterator::hasnext", 0);

	return true;
}
<|endoftext|>