<commit_before>#include <vector>
#include <thread>
#include <set>
#include <mutex>
#include <chrono>
#include <condition_variable>
#include <gtest/gtest.h>
#include "cppkafka/consumer.h"
#include "cppkafka/producer.h"

using std::vector;
using std::move;
using std::string;
using std::thread;
using std::set;
using std::mutex;
using std::tie;
using std::condition_variable;
using std::lock_guard;
using std::unique_lock;
using std::chrono::seconds;
using std::chrono::milliseconds;
using std::chrono::system_clock;

using namespace cppkafka;

class ConsumerRunner {
public:
    ConsumerRunner(Consumer& consumer, size_t expected, size_t partitions)
    : consumer_(consumer) {
        bool booted = false;
        mutex mtx;
        condition_variable cond;
        thread_ = thread([&, expected, partitions]() {
            consumer_.set_timeout(milliseconds(500));
            size_t number_eofs = 0;
            auto start = system_clock::now();
            while (system_clock::now() - start < seconds(10) && messages_.size() < expected) {
                Message msg = consumer_.poll();
                if (msg && number_eofs != partitions && msg.get_error() == RD_KAFKA_RESP_ERR__PARTITION_EOF) {
                    number_eofs++;
                    if (number_eofs == partitions) {
                        lock_guard<mutex> _(mtx);
                        booted = true;
                        cond.notify_one();
                    }
                }
                else if (msg && !msg.get_error() && number_eofs == partitions) {
                    messages_.push_back(move(msg));
                }
            }
        });

        unique_lock<mutex> lock(mtx);
        while (!booted) {
            cond.wait(lock);
        }
    }

    ConsumerRunner(const ConsumerRunner&) = delete;
    ConsumerRunner& operator=(const ConsumerRunner&) = delete;

    ~ConsumerRunner() {
        try_join();
    }

    const std::vector<Message>& get_messages() const {
        return messages_;
    }

    void try_join() {
        if (thread_.joinable()) {
            thread_.join();
        }
    }
private:
    Consumer& consumer_;
    thread thread_;
    std::vector<Message> messages_;
};

class ConsumerTest : public testing::Test {
public:
    static const string KAFKA_TOPIC;

    Configuration make_producer_config() {
        Configuration config;
        config.set("metadata.broker.list", KAFKA_TEST_INSTANCE);
        return config;
    }

    Configuration make_consumer_config(const string& group_id = "consumer_test") {
        Configuration config;
        config.set("metadata.broker.list", KAFKA_TEST_INSTANCE);
        config.set("enable.auto.commit", false);
        config.set("group.id", group_id);
        return config;
    }
};

const string ConsumerTest::KAFKA_TOPIC = "cppkafka_test1";

TEST_F(ConsumerTest, AssignmentCallback) {
    vector<TopicPartition> assignment;
    int partition = 0;

    // Create a consumer and subscribe to the topic
    Consumer consumer(make_consumer_config());
    consumer.set_assignment_callback([&](const vector<TopicPartition>& topic_partitions) {
        assignment = topic_partitions;
    });
    consumer.subscribe({ KAFKA_TOPIC });
    ConsumerRunner runner(consumer, 1, 3);

    // Produce a message just so we stop the consumer
    Producer producer(make_producer_config());
    Topic topic = producer.get_topic(KAFKA_TOPIC);
    string payload = "Hello world!";
    producer.produce(topic, partition, payload);
    runner.try_join();

    // All 3 partitions should be ours
    EXPECT_EQ(3, assignment.size());
    set<int> partitions = { 0, 1, 2 };
    for (const auto& topic_partition : assignment) {
        EXPECT_EQ(KAFKA_TOPIC, topic_partition.get_topic());
        EXPECT_TRUE(partitions.erase(topic_partition.get_partition()));
    }
    EXPECT_EQ(1, runner.get_messages().size());

    EXPECT_EQ(vector<string>{ KAFKA_TOPIC }, consumer.get_subscription());

    assignment = consumer.get_assignment();
    EXPECT_EQ(3, assignment.size());

    int64_t low;
    int64_t high;
    tie(low, high) = consumer.get_offsets({ KAFKA_TOPIC, partition });
    EXPECT_GT(high, low);
    EXPECT_EQ(high, runner.get_messages().back().get_offset() + 1);
}

TEST_F(ConsumerTest, Rebalance) {
    vector<TopicPartition> assignment1;
    vector<TopicPartition> assignment2;
    bool revocation_called = false;
    int partition = 0;

    // Create a consumer and subscribe to the topic
    Consumer consumer1(make_consumer_config());
    consumer1.set_assignment_callback([&](const vector<TopicPartition>& topic_partitions) {
        assignment1 = topic_partitions;
    });
    consumer1.set_revocation_callback([&](const vector<TopicPartition>&) {
        revocation_called = true;
    });
    consumer1.subscribe(KAFKA_TOPIC);
    ConsumerRunner runner1(consumer1, 1, 3);

    // Create a second consumer and subscribe to the topic
    Consumer consumer2(make_consumer_config());
    consumer2.set_assignment_callback([&](const vector<TopicPartition>& topic_partitions) {
        assignment2 = topic_partitions;
    });
    consumer2.subscribe({ KAFKA_TOPIC });
    ConsumerRunner runner2(consumer2, 1, 1);

    EXPECT_TRUE(revocation_called);

    // Produce a message just so we stop the consumer
    Producer producer(make_producer_config());
    Topic topic = producer.get_topic(KAFKA_TOPIC);
    string payload = "Hello world!";
    producer.produce(topic, partition, payload);
    runner1.try_join();
    runner2.try_join();

    // All 3 partitions should be assigned
    EXPECT_EQ(3, assignment1.size() + assignment2.size());
    set<int> partitions = { 0, 1, 2 };
    for (const auto& topic_partition : assignment1) {
        EXPECT_EQ(KAFKA_TOPIC, topic_partition.get_topic());
        EXPECT_TRUE(partitions.erase(topic_partition.get_partition()));
    }
    for (const auto& topic_partition : assignment2) {
        EXPECT_EQ(KAFKA_TOPIC, topic_partition.get_topic());
        EXPECT_TRUE(partitions.erase(topic_partition.get_partition()));
    }
    EXPECT_EQ(1, runner1.get_messages().size() + runner2.get_messages().size());
}

TEST_F(ConsumerTest, OffsetCommit) {
    int partition = 0;
    int64_t message_offset = 0;
    bool offset_commit_called = false;

    // Create a consumer and subscribe to the topic
    Configuration config = make_consumer_config("offset_commit");
    config.set_offset_commit_callback([&](Consumer&, Error error,
                                          const TopicPartitionList& topic_partitions) {
        offset_commit_called = true;
        EXPECT_FALSE(error);
        ASSERT_EQ(1, topic_partitions.size());
        EXPECT_EQ(KAFKA_TOPIC, topic_partitions[0].get_topic());
        EXPECT_EQ(0, topic_partitions[0].get_partition());
        EXPECT_EQ(message_offset + 1, topic_partitions[0].get_offset());
    });
    Consumer consumer(config);
    consumer.assign({ { KAFKA_TOPIC, 0 } });
    ConsumerRunner runner(consumer, 1, 1);

    // Produce a message just so we stop the consumer
    Producer producer(make_producer_config());
    Topic topic = producer.get_topic(KAFKA_TOPIC);
    string payload = "Hello world!";
    producer.produce(topic, partition, payload);
    runner.try_join();

    ASSERT_EQ(1, runner.get_messages().size());
    const Message& msg = runner.get_messages()[0];
    message_offset = msg.get_offset();
    consumer.commit(msg);
    for (size_t i = 0; i < 3 && !offset_commit_called; ++i) {
        consumer.poll();
    }
    EXPECT_TRUE(offset_commit_called);
}
<commit_msg>Remove bogus code<commit_after>#include <vector>
#include <thread>
#include <set>
#include <mutex>
#include <chrono>
#include <condition_variable>
#include <gtest/gtest.h>
#include "cppkafka/consumer.h"
#include "cppkafka/producer.h"

using std::vector;
using std::move;
using std::string;
using std::thread;
using std::set;
using std::mutex;
using std::tie;
using std::condition_variable;
using std::lock_guard;
using std::unique_lock;
using std::chrono::seconds;
using std::chrono::milliseconds;
using std::chrono::system_clock;

using namespace cppkafka;

class ConsumerRunner {
public:
    ConsumerRunner(Consumer& consumer, size_t expected, size_t partitions)
    : consumer_(consumer) {
        bool booted = false;
        mutex mtx;
        condition_variable cond;
        thread_ = thread([&, expected, partitions]() {
            consumer_.set_timeout(milliseconds(500));
            size_t number_eofs = 0;
            auto start = system_clock::now();
            while (system_clock::now() - start < seconds(10) && messages_.size() < expected) {
                Message msg = consumer_.poll();
                if (msg && number_eofs != partitions && msg.get_error() == RD_KAFKA_RESP_ERR__PARTITION_EOF) {
                    number_eofs++;
                    if (number_eofs == partitions) {
                        lock_guard<mutex> _(mtx);
                        booted = true;
                        cond.notify_one();
                    }
                }
                else if (msg && !msg.get_error() && number_eofs == partitions) {
                    messages_.push_back(move(msg));
                }
            }
        });

        unique_lock<mutex> lock(mtx);
        while (!booted) {
            cond.wait(lock);
        }
    }

    ConsumerRunner(const ConsumerRunner&) = delete;
    ConsumerRunner& operator=(const ConsumerRunner&) = delete;

    ~ConsumerRunner() {
        try_join();
    }

    const std::vector<Message>& get_messages() const {
        return messages_;
    }

    void try_join() {
        if (thread_.joinable()) {
            thread_.join();
        }
    }
private:
    Consumer& consumer_;
    thread thread_;
    std::vector<Message> messages_;
};

class ConsumerTest : public testing::Test {
public:
    static const string KAFKA_TOPIC;

    Configuration make_producer_config() {
        Configuration config;
        config.set("metadata.broker.list", KAFKA_TEST_INSTANCE);
        return config;
    }

    Configuration make_consumer_config(const string& group_id = "consumer_test") {
        Configuration config;
        config.set("metadata.broker.list", KAFKA_TEST_INSTANCE);
        config.set("enable.auto.commit", false);
        config.set("group.id", group_id);
        return config;
    }
};

const string ConsumerTest::KAFKA_TOPIC = "cppkafka_test1";

TEST_F(ConsumerTest, AssignmentCallback) {
    vector<TopicPartition> assignment;
    int partition = 0;

    // Create a consumer and subscribe to the topic
    Consumer consumer(make_consumer_config());
    consumer.set_assignment_callback([&](const vector<TopicPartition>& topic_partitions) {
        assignment = topic_partitions;
    });
    consumer.subscribe({ KAFKA_TOPIC });
    ConsumerRunner runner(consumer, 1, 3);

    // Produce a message just so we stop the consumer
    Producer producer(make_producer_config());
    Topic topic = producer.get_topic(KAFKA_TOPIC);
    string payload = "Hello world!";
    producer.produce(topic, partition, payload);
    runner.try_join();

    // All 3 partitions should be ours
    EXPECT_EQ(3, assignment.size());
    set<int> partitions = { 0, 1, 2 };
    for (const auto& topic_partition : assignment) {
        EXPECT_EQ(KAFKA_TOPIC, topic_partition.get_topic());
        EXPECT_TRUE(partitions.erase(topic_partition.get_partition()));
    }
    EXPECT_EQ(1, runner.get_messages().size());

    EXPECT_EQ(vector<string>{ KAFKA_TOPIC }, consumer.get_subscription());

    assignment = consumer.get_assignment();
    EXPECT_EQ(3, assignment.size());

    int64_t low;
    int64_t high;
    tie(low, high) = consumer.get_offsets({ KAFKA_TOPIC, partition });
    EXPECT_GT(high, low);
    EXPECT_EQ(high, runner.get_messages().back().get_offset() + 1);
}

TEST_F(ConsumerTest, Rebalance) {
    vector<TopicPartition> assignment1;
    vector<TopicPartition> assignment2;
    bool revocation_called = false;
    int partition = 0;

    // Create a consumer and subscribe to the topic
    Consumer consumer1(make_consumer_config());
    consumer1.set_assignment_callback([&](const vector<TopicPartition>& topic_partitions) {
        assignment1 = topic_partitions;
    });
    consumer1.set_revocation_callback([&](const vector<TopicPartition>&) {
        revocation_called = true;
    });
    consumer1.subscribe({ KAFKA_TOPIC });
    ConsumerRunner runner1(consumer1, 1, 3);

    // Create a second consumer and subscribe to the topic
    Consumer consumer2(make_consumer_config());
    consumer2.set_assignment_callback([&](const vector<TopicPartition>& topic_partitions) {
        assignment2 = topic_partitions;
    });
    consumer2.subscribe({ KAFKA_TOPIC });
    ConsumerRunner runner2(consumer2, 1, 1);

    EXPECT_TRUE(revocation_called);

    // Produce a message just so we stop the consumer
    Producer producer(make_producer_config());
    Topic topic = producer.get_topic(KAFKA_TOPIC);
    string payload = "Hello world!";
    producer.produce(topic, partition, payload);
    runner1.try_join();
    runner2.try_join();

    // All 3 partitions should be assigned
    EXPECT_EQ(3, assignment1.size() + assignment2.size());
    set<int> partitions = { 0, 1, 2 };
    for (const auto& topic_partition : assignment1) {
        EXPECT_EQ(KAFKA_TOPIC, topic_partition.get_topic());
        EXPECT_TRUE(partitions.erase(topic_partition.get_partition()));
    }
    for (const auto& topic_partition : assignment2) {
        EXPECT_EQ(KAFKA_TOPIC, topic_partition.get_topic());
        EXPECT_TRUE(partitions.erase(topic_partition.get_partition()));
    }
    EXPECT_EQ(1, runner1.get_messages().size() + runner2.get_messages().size());
}

TEST_F(ConsumerTest, OffsetCommit) {
    int partition = 0;
    int64_t message_offset = 0;
    bool offset_commit_called = false;

    // Create a consumer and subscribe to the topic
    Configuration config = make_consumer_config("offset_commit");
    config.set_offset_commit_callback([&](Consumer&, Error error,
                                          const TopicPartitionList& topic_partitions) {
        offset_commit_called = true;
        EXPECT_FALSE(error);
        ASSERT_EQ(1, topic_partitions.size());
        EXPECT_EQ(KAFKA_TOPIC, topic_partitions[0].get_topic());
        EXPECT_EQ(0, topic_partitions[0].get_partition());
        EXPECT_EQ(message_offset + 1, topic_partitions[0].get_offset());
    });
    Consumer consumer(config);
    consumer.assign({ { KAFKA_TOPIC, 0 } });
    ConsumerRunner runner(consumer, 1, 1);

    // Produce a message just so we stop the consumer
    Producer producer(make_producer_config());
    Topic topic = producer.get_topic(KAFKA_TOPIC);
    string payload = "Hello world!";
    producer.produce(topic, partition, payload);
    runner.try_join();

    ASSERT_EQ(1, runner.get_messages().size());
    const Message& msg = runner.get_messages()[0];
    message_offset = msg.get_offset();
    consumer.commit(msg);
    for (size_t i = 0; i < 3 && !offset_commit_called; ++i) {
        consumer.poll();
    }
    EXPECT_TRUE(offset_commit_called);
}
<|endoftext|>


<commit_before><commit_msg>Planning: Add is_on_lane logic for watch obstacle<commit_after><|endoftext|>


<commit_before>/*
 * Website:
 *      https://github.com/wo3kie/dojo
 *
 * Author:
 *      Lukasz Czerwinski
 *
 * Compilation:
 *      g++ --std=c++11 mandelbrot.cpp -o mandelbrot
 *
 * Usage:
 *      $ ./mandelbrot
 */

#include <iostream>

char digit(int iteration, int maxIteration){
    return '0' + (iteration % 10);
}

char hash(int iteration, int maxIteration){
    return (iteration >= maxIteration) ? '#' : ' ';
}

char asciiArt1(int iteration, int maxIteration){
    char const * const ascii = " .,:;^*&#@";
    return ascii[ iteration % 10 ];
}

char asciiArt2(int iteration, int maxIteration){
    char const * const ascii = "@#&*^;:,. ";
    return ascii[ iteration % 10 ];
}

void mandelbrot( char (*getAscii)(int, int) ){
    double scale = 1;

    int width = scale * 150;
    double const wStep = 4.0 / width;

    int height = scale * 60;
    double const hStep = 4.0 / height;

    int const maxIteration = 50;

    for( int h = 0 ; h < height ; ++h ){
        for( int w = 0 ; w < width ; ++w ){
            double const x0 = wStep * w - 2;
            double const y0 = hStep * h - 2;

            int iteration = 0;
            double x = 0;
            double y = 0;

            for( ; x * x + y * y < 4 && iteration < maxIteration ; ++iteration ){
                double const temp = x * x - y * y + x0;
                y = 2 * x * y + y0;
                x = temp;
            }

            std::cout << getAscii(iteration, maxIteration);
        }

        std::cout << std::endl;
    }
}

int main(){
    mandelbrot( & digit );
    mandelbrot( & hash );
    mandelbrot( & asciiArt1 );
    mandelbrot( & asciiArt2 );
}
<commit_msg>mandelbrot<commit_after>/*
 * Website:
 *      https://github.com/wo3kie/dojo
 *
 * Author:
 *      Lukasz Czerwinski
 *
 * Compilation:
 *      g++ --std=c++11 mandelbrot.cpp -o mandelbrot
 *
 * Usage:
 *      $ ./mandelbrot
 */

#include <iostream>

char digit(int iteration, int maxIteration){
    return '0' + (iteration % 10);
}

char hash(int iteration, int maxIteration){
    return (iteration == maxIteration) ? '#' : ' ';
}

char asciiArt1(int iteration, int maxIteration){
    char const * const ascii = " .,:;^*&#@";
    return ascii[ iteration % 10 ];
}

char asciiArt2(int iteration, int maxIteration){
    char const * const ascii = "@#&*^;:,. ";
    return ascii[ iteration % 10 ];
}

void mandelbrot(
    char (*getAscii)(int, int),
    unsigned const rows = 60,
    unsigned const columns = 150
){
    for( double r = -1.5 ; r < 1.5 ; r += ( 3.0 / rows ) ){
        for( double c = -2.5 ; c < 1.5 ; c += ( 4.0 / columns ) ){
            int iteration = 0;
            int const maxIteration = 50;

            for( double x = 0, y = 0
                ; x * x + y * y < 4 && iteration < maxIteration
                ; ++iteration
            ){
                double const temp = c + ( x * x - y * y );
                y = r + ( 2 * x * y );
                x = temp;
            }

            std::cout << getAscii(iteration, maxIteration);
        }

        std::cout << std::endl;
    }
}

int main(){
    mandelbrot( & digit );
    mandelbrot( & hash );
    mandelbrot( & asciiArt1 );
    mandelbrot( & asciiArt2 );
}
<|endoftext|>


<commit_before>/*
 *
 *    Copyright (c) 2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    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 "CommonDeviceCallbacks.h"

#if CONFIG_BT_ENABLED
#include "esp_bt.h"
#if CONFIG_BT_NIMBLE_ENABLED
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
#include "esp_nimble_hci.h"
#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
#include "nimble/nimble_port.h"
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // CONFIG_BT_ENABLED

#include "esp_err.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "route_hook/esp_route_hook.h"
#include <app-common/zap-generated/attribute-id.h>
#include <app-common/zap-generated/cluster-id.h>
#include <app/server/Dnssd.h>
#include <app/util/util.h>
#include <lib/support/CodeUtils.h>
#if CONFIG_ENABLE_OTA_REQUESTOR
#include <ota/OTAHelper.h>
#endif

static const char * TAG = "app-devicecallbacks";

using namespace chip;
using namespace chip::DeviceLayer;
using namespace chip::System;

DeviceCallbacksDelegate * appDelegate = nullptr;
#if CONFIG_ENABLE_OTA_REQUESTOR
static bool isOTAInitialized = false;
#endif

void CommonDeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, intptr_t arg)
{
    switch (event->Type)
    {
    case DeviceEventType::kInternetConnectivityChange:
        OnInternetConnectivityChange(event);
        break;

    case DeviceEventType::kCHIPoBLEConnectionEstablished:
        ESP_LOGI(TAG, "CHIPoBLE connection established");
        break;

    case DeviceEventType::kCHIPoBLEConnectionClosed:
        ESP_LOGI(TAG, "CHIPoBLE disconnected");
        break;

    case DeviceEventType::kThreadConnectivityChange:
#if CONFIG_ENABLE_OTA_REQUESTOR
        if (event->ThreadConnectivityChange.Result == kConnectivity_Established && !isOTAInitialized)
        {
            OTAHelpers::Instance().InitOTARequestor();
            isOTAInitialized = true;
        }
#endif
        break;

    case DeviceEventType::kCommissioningComplete: {
        ESP_LOGI(TAG, "Commissioning complete");
#if CONFIG_BT_NIMBLE_ENABLED && CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING

        if (ble_hs_is_enabled())
        {
            int ret       = nimble_port_stop();
            esp_err_t err = ESP_OK;
            if (ret == 0)
            {
                nimble_port_deinit();
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
                err = esp_nimble_hci_and_controller_deinit();
#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
                err += esp_bt_mem_release(ESP_BT_MODE_BLE);
                if (err == ESP_OK)
                {
                    ESP_LOGI(TAG, "BLE deinit successful and memory reclaimed");
                }
            }
            else
            {
                ESP_LOGW(TAG, "nimble_port_stop() failed");
            }
        }
        else
        {
            ESP_LOGI(TAG, "BLE already deinited");
        }
#endif
    }
    break;

    case DeviceEventType::kInterfaceIpAddressChanged:
        if ((event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV4_Assigned) ||
            (event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV6_Assigned))
        {
            // MDNS server restart on any ip assignment: if link local ipv6 is configured, that
            // will not trigger a 'internet connectivity change' as there is no internet
            // connectivity. MDNS still wants to refresh its listening interfaces to include the
            // newly selected address.
            chip::app::DnssdServer::Instance().StartServer();
        }
        if (event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV6_Assigned)
        {
            ESP_ERROR_CHECK(esp_route_hook_init(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF")));
        }
        break;
    }

    ESP_LOGI(TAG, "Current free heap: %u\n", static_cast<unsigned int>(heap_caps_get_free_size(MALLOC_CAP_8BIT)));
}

void CommonDeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event)
{
    appDelegate = DeviceCallbacksDelegate::Instance().GetAppDelegate();
    if (event->InternetConnectivityChange.IPv4 == kConnectivity_Established)
    {
        ESP_LOGI(TAG, "IPv4 Server ready...");
        if (appDelegate != nullptr)
        {
            appDelegate->OnIPv4ConnectivityEstablished();
        }
        chip::app::DnssdServer::Instance().StartServer();
#if CONFIG_ENABLE_OTA_REQUESTOR
        if (!isOTAInitialized)
        {
            OTAHelpers::Instance().InitOTARequestor();
            isOTAInitialized = true;
        }
#endif
    }
    else if (event->InternetConnectivityChange.IPv4 == kConnectivity_Lost)
    {
        ESP_LOGE(TAG, "Lost IPv4 connectivity...");
        if (appDelegate != nullptr)
        {
            appDelegate->OnIPv4ConnectivityLost();
        }
    }
    if (event->InternetConnectivityChange.IPv6 == kConnectivity_Established)
    {
        ESP_LOGI(TAG, "IPv6 Server ready...");
        chip::app::DnssdServer::Instance().StartServer();

#if CONFIG_ENABLE_OTA_REQUESTOR
        if (!isOTAInitialized)
        {
            OTAHelpers::Instance().InitOTARequestor();
            isOTAInitialized = true;
        }
#endif
    }
    else if (event->InternetConnectivityChange.IPv6 == kConnectivity_Lost)
    {
        ESP_LOGE(TAG, "Lost IPv6 connectivity...");
    }
}
<commit_msg>[ESP32] Release BTDM memory rather than just releasing BLE memory. (#23165)<commit_after>/*
 *
 *    Copyright (c) 2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    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 "CommonDeviceCallbacks.h"

#if CONFIG_BT_ENABLED
#include "esp_bt.h"
#if CONFIG_BT_NIMBLE_ENABLED
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
#include "esp_nimble_hci.h"
#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
#include "nimble/nimble_port.h"
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // CONFIG_BT_ENABLED

#include "esp_err.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "route_hook/esp_route_hook.h"
#include <app-common/zap-generated/attribute-id.h>
#include <app-common/zap-generated/cluster-id.h>
#include <app/server/Dnssd.h>
#include <app/util/util.h>
#include <lib/support/CodeUtils.h>
#if CONFIG_ENABLE_OTA_REQUESTOR
#include <ota/OTAHelper.h>
#endif

static const char * TAG = "app-devicecallbacks";

using namespace chip;
using namespace chip::DeviceLayer;
using namespace chip::System;

DeviceCallbacksDelegate * appDelegate = nullptr;
#if CONFIG_ENABLE_OTA_REQUESTOR
static bool isOTAInitialized = false;
#endif

void CommonDeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, intptr_t arg)
{
    switch (event->Type)
    {
    case DeviceEventType::kInternetConnectivityChange:
        OnInternetConnectivityChange(event);
        break;

    case DeviceEventType::kCHIPoBLEConnectionEstablished:
        ESP_LOGI(TAG, "CHIPoBLE connection established");
        break;

    case DeviceEventType::kCHIPoBLEConnectionClosed:
        ESP_LOGI(TAG, "CHIPoBLE disconnected");
        break;

    case DeviceEventType::kThreadConnectivityChange:
#if CONFIG_ENABLE_OTA_REQUESTOR
        if (event->ThreadConnectivityChange.Result == kConnectivity_Established && !isOTAInitialized)
        {
            OTAHelpers::Instance().InitOTARequestor();
            isOTAInitialized = true;
        }
#endif
        break;

    case DeviceEventType::kCommissioningComplete: {
        ESP_LOGI(TAG, "Commissioning complete");
#if CONFIG_BT_NIMBLE_ENABLED && CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING

        if (ble_hs_is_enabled())
        {
            int ret       = nimble_port_stop();
            esp_err_t err = ESP_OK;
            if (ret == 0)
            {
                nimble_port_deinit();
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
                err = esp_nimble_hci_and_controller_deinit();
#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
                err += esp_bt_mem_release(ESP_BT_MODE_BTDM);
                if (err == ESP_OK)
                {
                    ESP_LOGI(TAG, "BLE deinit successful and memory reclaimed");
                }
            }
            else
            {
                ESP_LOGW(TAG, "nimble_port_stop() failed");
            }
        }
        else
        {
            ESP_LOGI(TAG, "BLE already deinited");
        }
#endif
    }
    break;

    case DeviceEventType::kInterfaceIpAddressChanged:
        if ((event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV4_Assigned) ||
            (event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV6_Assigned))
        {
            // MDNS server restart on any ip assignment: if link local ipv6 is configured, that
            // will not trigger a 'internet connectivity change' as there is no internet
            // connectivity. MDNS still wants to refresh its listening interfaces to include the
            // newly selected address.
            chip::app::DnssdServer::Instance().StartServer();
        }
        if (event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV6_Assigned)
        {
            ESP_ERROR_CHECK(esp_route_hook_init(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF")));
        }
        break;
    }

    ESP_LOGI(TAG, "Current free heap: %u\n", static_cast<unsigned int>(heap_caps_get_free_size(MALLOC_CAP_8BIT)));
}

void CommonDeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event)
{
    appDelegate = DeviceCallbacksDelegate::Instance().GetAppDelegate();
    if (event->InternetConnectivityChange.IPv4 == kConnectivity_Established)
    {
        ESP_LOGI(TAG, "IPv4 Server ready...");
        if (appDelegate != nullptr)
        {
            appDelegate->OnIPv4ConnectivityEstablished();
        }
        chip::app::DnssdServer::Instance().StartServer();
#if CONFIG_ENABLE_OTA_REQUESTOR
        if (!isOTAInitialized)
        {
            OTAHelpers::Instance().InitOTARequestor();
            isOTAInitialized = true;
        }
#endif
    }
    else if (event->InternetConnectivityChange.IPv4 == kConnectivity_Lost)
    {
        ESP_LOGE(TAG, "Lost IPv4 connectivity...");
        if (appDelegate != nullptr)
        {
            appDelegate->OnIPv4ConnectivityLost();
        }
    }
    if (event->InternetConnectivityChange.IPv6 == kConnectivity_Established)
    {
        ESP_LOGI(TAG, "IPv6 Server ready...");
        chip::app::DnssdServer::Instance().StartServer();

#if CONFIG_ENABLE_OTA_REQUESTOR
        if (!isOTAInitialized)
        {
            OTAHelpers::Instance().InitOTARequestor();
            isOTAInitialized = true;
        }
#endif
    }
    else if (event->InternetConnectivityChange.IPv6 == kConnectivity_Lost)
    {
        ESP_LOGE(TAG, "Lost IPv6 connectivity...");
    }
}
<|endoftext|>


<commit_before>/** @file
 *
 * @ingroup dspWindowFunctionLib
 *
 * @brief Generalized Window Function Wrapper for Jamoma DSP
 *
 * @details
 *
 * @authors Tim Place, Nathan Wolek, Trond Lossius,
 *
 * @copyright Copyright © 2010 by Timothy Place @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTWindowFunction.h"

#define thisTTClass			WindowFunction
#define thisTTClassName		"WindowFunction"
#define thisTTClassTags		"dspWindowFunctionLib, audio, processor"

TT_AUDIO_CONSTRUCTOR,
	mFunctionObject(NULL),
	mNumPoints(8192),
	mPadding(0)
{
	addAttributeWithSetter(Function,	kTypeSymbol);
	addAttributeWithSetter(NumPoints,	kTypeUInt32);
	addAttributeWithSetter(Mode,		kTypeSymbol);
	addAttributeWithSetter(Padding,		kTypeUInt32);

	addMessageWithArguments(getFunctions);
	addMessageWithArguments(setParameter);

	setAttributeValue(TT("function"), TT("rectangular"));
	setAttributeValue(TT("mode"), TT("lookup"));
}

WindowFunction::~WindowFunction()
{
	delete mFunctionObject;
}

TTErr WindowFunction::setFunction(const TTValue& function)
{
	TTErr err;

	mFunction = function;
	err = TTObjectBaseInstantiate(mFunction, &mFunctionObject, mMaxNumChannels);
	if (!err)
		err = fill();
	return err;
}

TTErr WindowFunction::setParameter(const TTValue& aParameterValueForTheFunction, TTValue&)
{
	TTErr err;

	if (aParameterValueForTheFunction.size() < 2)
		err = kTTErrWrongNumValues;
	else {
		TTSymbol	parameterName = aParameterValueForTheFunction;
		TTValue		v;

		v.copyFrom(aParameterValueForTheFunction, 1);
		err = mFunctionObject->setAttributeValue(parameterName, v);
		if (!err)
			fill();
	}

	return err;
}

TTErr WindowFunction::fill()
{
	mLookupTable.assign(mNumPoints, 0.0);
	if (mFunctionObject) {
		TTInt32 numPoints = mNumPoints-(mPadding*2);

		TTLimitMin<TTInt32>(numPoints, 0);
		for (TTInt32 i=0; i<numPoints; i++)
			mFunctionObject->calculate(i/TTFloat64(numPoints-1), mLookupTable[i+mPadding]);
	}
	else
		mLookupTable.assign(mNumPoints, 0.0);

	return kTTErrNone;
}

TTErr WindowFunction::setNumPoints(const TTValue& numPoints)
{
	return doSetNumPoints(numPoints);
}

TTErr WindowFunction::doSetNumPoints(const TTUInt32 numPoints)
{
	mNumPoints = numPoints;
	mLookupTable.resize(mNumPoints);
	return fill();
}

TTErr WindowFunction::setPadding(const TTValue& padding)
{
	mPadding = padding;
	return fill();
}

TTErr WindowFunction::setMode(const TTValue& mode)
{
	mMode = mode;
	if (mMode == TT("apply")) {
		setProcessMethod(processApply);
		setCalculateMethod(lookupValue);
	}
	else if (mMode == TT("generate")) {
		setProcessMethod(processGenerate);
		setCalculateMethod(calculateValue);
	}
	else {
		setProcessMethod(processLookup);
		setCalculateMethod(lookupValue);
	}
	return kTTErrNone;
}

TTErr WindowFunction::getFunctions(const TTValue&, TTValue& listOfWindowTypesToReturn)
{
	return TTGetRegisteredClassNamesForTags(listOfWindowTypesToReturn, TT("window"));
}

#if 0
#pragma mark -
#pragma mark Process Routines
#endif

inline TTErr WindowFunction::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt data)
{
	return mFunctionObject->calculate(x, y);
}

inline TTErr WindowFunction::lookupValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt data)
{
	y = mLookupTable[TTClip(x, 0.0, 1.0) * mNumPoints];
	return kTTErrNone;
}

TTErr WindowFunction::processGenerate(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	return mFunctionObject->process(inputs, outputs);
}

TTErr WindowFunction::processLookup(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	TT_WRAP_CALCULATE_METHOD(lookupValue)
}

TTErr WindowFunction::processApply(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	TTAudioSignal&		in = inputs->getSignal(0);
	TTAudioSignal&		out = outputs->getSignal(0);
	TTUInt16			vs = in.getVectorSizeAsInt();
	TTSampleValuePtr	inSample;
	TTSampleValuePtr	outSample;
	TTUInt16			numChannels = TTAudioSignal::getMinChannelCount(in, out);
	TTUInt16			channel;

	// In 'apply' mode we automatically update the lookup table size to the vector size
	// This is slow, but hopefully only happens once (if ever)
	if (vs != mNumPoints)
		doSetNumPoints(vs);

	for (channel=0; channel<numChannels; channel++) {
		inSample = in.mSampleVectors[channel];
		outSample = out.mSampleVectors[channel];

		for (TTUInt32 i=0; i<vs; i++)
			*outSample++ = (*inSample++) * mLookupTable[i];
	}
	return kTTErrNone;
}

<commit_msg>Substituting TTUInt16 for TTChannelCount where relevant in WindowFunctionLib<commit_after>/** @file
 *
 * @ingroup dspWindowFunctionLib
 *
 * @brief Generalized Window Function Wrapper for Jamoma DSP
 *
 * @details
 *
 * @authors Tim Place, Nathan Wolek, Trond Lossius,
 *
 * @copyright Copyright © 2010 by Timothy Place @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTWindowFunction.h"

#define thisTTClass			WindowFunction
#define thisTTClassName		"WindowFunction"
#define thisTTClassTags		"dspWindowFunctionLib, audio, processor"

TT_AUDIO_CONSTRUCTOR,
	mFunctionObject(NULL),
	mNumPoints(8192),
	mPadding(0)
{
	addAttributeWithSetter(Function,	kTypeSymbol);
	addAttributeWithSetter(NumPoints,	kTypeUInt32);
	addAttributeWithSetter(Mode,		kTypeSymbol);
	addAttributeWithSetter(Padding,		kTypeUInt32);

	addMessageWithArguments(getFunctions);
	addMessageWithArguments(setParameter);

	setAttributeValue(TT("function"), TT("rectangular"));
	setAttributeValue(TT("mode"), TT("lookup"));
}

WindowFunction::~WindowFunction()
{
	delete mFunctionObject;
}

TTErr WindowFunction::setFunction(const TTValue& function)
{
	TTErr err;

	mFunction = function;
	err = TTObjectBaseInstantiate(mFunction, &mFunctionObject, mMaxNumChannels);
	if (!err)
		err = fill();
	return err;
}

TTErr WindowFunction::setParameter(const TTValue& aParameterValueForTheFunction, TTValue&)
{
	TTErr err;

	if (aParameterValueForTheFunction.size() < 2)
		err = kTTErrWrongNumValues;
	else {
		TTSymbol	parameterName = aParameterValueForTheFunction;
		TTValue		v;

		v.copyFrom(aParameterValueForTheFunction, 1);
		err = mFunctionObject->setAttributeValue(parameterName, v);
		if (!err)
			fill();
	}

	return err;
}

TTErr WindowFunction::fill()
{
	mLookupTable.assign(mNumPoints, 0.0);
	if (mFunctionObject) {
		TTInt32 numPoints = mNumPoints-(mPadding*2);

		TTLimitMin<TTInt32>(numPoints, 0);
		for (TTInt32 i=0; i<numPoints; i++)
			mFunctionObject->calculate(i/TTFloat64(numPoints-1), mLookupTable[i+mPadding]);
	}
	else
		mLookupTable.assign(mNumPoints, 0.0);

	return kTTErrNone;
}

TTErr WindowFunction::setNumPoints(const TTValue& numPoints)
{
	return doSetNumPoints(numPoints);
}

TTErr WindowFunction::doSetNumPoints(const TTUInt32 numPoints)
{
	mNumPoints = numPoints;
	mLookupTable.resize(mNumPoints);
	return fill();
}

TTErr WindowFunction::setPadding(const TTValue& padding)
{
	mPadding = padding;
	return fill();
}

TTErr WindowFunction::setMode(const TTValue& mode)
{
	mMode = mode;
	if (mMode == TT("apply")) {
		setProcessMethod(processApply);
		setCalculateMethod(lookupValue);
	}
	else if (mMode == TT("generate")) {
		setProcessMethod(processGenerate);
		setCalculateMethod(calculateValue);
	}
	else {
		setProcessMethod(processLookup);
		setCalculateMethod(lookupValue);
	}
	return kTTErrNone;
}

TTErr WindowFunction::getFunctions(const TTValue&, TTValue& listOfWindowTypesToReturn)
{
	return TTGetRegisteredClassNamesForTags(listOfWindowTypesToReturn, TT("window"));
}

#if 0
#pragma mark -
#pragma mark Process Routines
#endif

inline TTErr WindowFunction::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt data)
{
	return mFunctionObject->calculate(x, y);
}

inline TTErr WindowFunction::lookupValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt data)
{
	y = mLookupTable[TTClip(x, 0.0, 1.0) * mNumPoints];
	return kTTErrNone;
}

TTErr WindowFunction::processGenerate(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	return mFunctionObject->process(inputs, outputs);
}

TTErr WindowFunction::processLookup(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	TT_WRAP_CALCULATE_METHOD(lookupValue)
}

TTErr WindowFunction::processApply(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	TTAudioSignal&		in = inputs->getSignal(0);
	TTAudioSignal&		out = outputs->getSignal(0);
	TTUInt16			vs = in.getVectorSizeAsInt();
	TTSampleValuePtr	inSample;
	TTSampleValuePtr	outSample;
	TTChannelCount		numChannels = TTAudioSignal::getMinChannelCount(in, out);
	TTChannelCount		channel;

	// In 'apply' mode we automatically update the lookup table size to the vector size
	// This is slow, but hopefully only happens once (if ever)
	if (vs != mNumPoints)
		doSetNumPoints(vs);

	for (channel=0; channel<numChannels; channel++) {
		inSample = in.mSampleVectors[channel];
		outSample = out.mSampleVectors[channel];

		for (TTUInt32 i=0; i<vs; i++)
			*outSample++ = (*inSample++) * mLookupTable[i];
	}
	return kTTErrNone;
}

<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
// Licensed to Qualys, Inc. (QUALYS) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// QUALYS licenses this file to You 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.
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/// @file
/// IronBee - Unit testing utility functions implementation.
/// @brief IronBee - String Util Test Functions
///
/// @author Nick LeRoy <nleroy@qualys.com>
//////////////////////////////////////////////////////////////////////////////

#include "ironbee_config_auto.h"

#include <ironbee/types.h>
#include <ironbee/string.h>

#include <stdexcept>
#include <assert.h>
#include <stdio.h>

// Basic text buffer
class TextBuf
{
public:
    TextBuf(size_t bufsize)
        : m_size(bufsize), m_buf(new char [bufsize+1]),
          m_fmtsize(2*bufsize), m_fmtbuf(new char [m_fmtsize+1])
    {
        SetStr("");
    };

    TextBuf(size_t bufsize, const char *s)
        : m_size(bufsize), m_buf(new char [bufsize+1]),
          m_fmtsize(2*bufsize), m_fmtbuf(new char [m_fmtsize+1])
    {
        SetStr(s);
    };

    TextBuf(size_t bufsize, const char *text, size_t len)
        : m_size(bufsize), m_buf(new char [bufsize]),
          m_fmtsize(2*bufsize), m_fmtbuf(new char [bufsize*2])
    {
        SetText(text, len);
    };

    size_t SetNull( bool is_bytestr )
    {
        m_buf[0] = '\0';
        m_len = 0;
        m_null = true;
        m_bytestr = is_bytestr;
        InvalidateFmt( );
        return m_len;
    }

    size_t SetStr(const char *s, bool is_bytestr=false)
    {
        if (s == NULL) {
            return SetNull( false );
        }
        strncpy(m_buf, s, m_size);
        m_len = strlen(m_buf);
        m_null = false;
        m_bytestr = is_bytestr;
        InvalidateFmt( );
        return m_len;
    };

    size_t SetText(const char *text, size_t len)
    {
        assert (len < m_size);
        if (text == NULL) {
            return SetNull( true );
        }
        memcpy(m_buf, text, len);
        m_len = len;
        m_buf[len] = '\0';
        m_bytestr = true;
        InvalidateFmt( );
        return m_len;
    };

    void InvalidateFmt(void) const { m_fmtvalid = false; };
    bool IsFmtValid(void) const { return m_fmtvalid; };

    void SetByteStr(bool is_bytestr) { m_bytestr = is_bytestr; };
    bool IsByteStr(void) const { return m_bytestr; };
    bool IsNull(void) const { return m_null; };

    virtual const char *GetBuf(void) const {
        return m_null == true ? NULL : m_buf;
    };
    virtual size_t GetLen(void) const { return m_len; };
    virtual const char *GetFmt(void) const {
        if (IsFmtValid() == false) {
            if (m_bytestr) {
                return BuildFmt(m_buf, m_len);
            }
            else {
                return BuildFmt(m_buf);
            }
        }
        return m_fmtbuf;
    };

    bool operator == (const TextBuf &other) const {
        //assert(other.IsByteStr() == IsByteStr());
        if (IsNull() || other.IsNull() ) {
            return false;
        }
        if (IsByteStr()) {
            if (GetLen() != other.GetLen()) {
                return false;
            }
            return (memcmp(GetBuf(), other.GetBuf(), GetLen()) == 0);
        }
        else {
            return (strcmp(GetBuf(), other.GetBuf()) == 0);
        }
    };

    bool operator != (const TextBuf &other) const {
        return !(*this == other);
    };

    const char *BuildFmt(void) const {
        if (m_bytestr) {
            return BuildFmt(m_buf, m_len);
        }
        else {
            return BuildFmt(m_buf);
        }
    }

    const char *BuildFmt(const char *str) const {
        return BuildFmt(str, strlen(str));
    };

    const char *BuildFmt(const char *str, size_t len) const {
        char *buf = m_fmtbuf;
        const char *end = m_fmtbuf + m_fmtsize;
        size_t n = 0;
        while ( (n < len) && (buf < end) ) {
            if (*str == '\n') {
                *buf++ = '\\';
                *buf++ = 'n';
            }
            else if (*str == '\t') {
                *buf++ = '\\';
                *buf++ = 't';
            }
            else if (*str == '\0') {
                *buf++ = '\\';
                *buf++ = '0';
            }
            else {
                *buf++ = *str;
            }
            ++str;
            ++n;
        }
        *buf = '\0';
        m_fmtvalid = true;
        return m_fmtbuf;
    };

protected:
    size_t        m_size;
    char         *m_buf;
    bool          m_bytestr;
    bool          m_null;
    size_t        m_len;
    size_t        m_fmtsize;
    // The formatted buffer is mutable
    mutable char *m_fmtbuf;
    mutable bool  m_fmtvalid;

};

<commit_msg>GCC/G++ 4.1.2 requires a virtual destructor for test class.<commit_after>//////////////////////////////////////////////////////////////////////////////
// Licensed to Qualys, Inc. (QUALYS) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// QUALYS licenses this file to You 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.
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/// @file
/// IronBee - Unit testing utility functions implementation.
/// @brief IronBee - String Util Test Functions
///
/// @author Nick LeRoy <nleroy@qualys.com>
//////////////////////////////////////////////////////////////////////////////

#include "ironbee_config_auto.h"

#include <ironbee/types.h>
#include <ironbee/string.h>

#include <stdexcept>
#include <assert.h>
#include <stdio.h>

// Basic text buffer
class TextBuf
{
public:
    TextBuf(size_t bufsize)
        : m_size(bufsize), m_buf(new char [bufsize+1]),
          m_fmtsize(2*bufsize), m_fmtbuf(new char [m_fmtsize+1])
    {
        SetStr("");
    };

    TextBuf(size_t bufsize, const char *s)
        : m_size(bufsize), m_buf(new char [bufsize+1]),
          m_fmtsize(2*bufsize), m_fmtbuf(new char [m_fmtsize+1])
    {
        SetStr(s);
    };

    TextBuf(size_t bufsize, const char *text, size_t len)
        : m_size(bufsize), m_buf(new char [bufsize]),
          m_fmtsize(2*bufsize), m_fmtbuf(new char [bufsize*2])
    {
        SetText(text, len);
    };

    virtual ~TextBuf(){}

    size_t SetNull( bool is_bytestr )
    {
        m_buf[0] = '\0';
        m_len = 0;
        m_null = true;
        m_bytestr = is_bytestr;
        InvalidateFmt( );
        return m_len;
    }

    size_t SetStr(const char *s, bool is_bytestr=false)
    {
        if (s == NULL) {
            return SetNull( false );
        }
        strncpy(m_buf, s, m_size);
        m_len = strlen(m_buf);
        m_null = false;
        m_bytestr = is_bytestr;
        InvalidateFmt( );
        return m_len;
    };

    size_t SetText(const char *text, size_t len)
    {
        assert (len < m_size);
        if (text == NULL) {
            return SetNull( true );
        }
        memcpy(m_buf, text, len);
        m_len = len;
        m_buf[len] = '\0';
        m_bytestr = true;
        InvalidateFmt( );
        return m_len;
    };

    void InvalidateFmt(void) const { m_fmtvalid = false; };
    bool IsFmtValid(void) const { return m_fmtvalid; };

    void SetByteStr(bool is_bytestr) { m_bytestr = is_bytestr; };
    bool IsByteStr(void) const { return m_bytestr; };
    bool IsNull(void) const { return m_null; };

    virtual const char *GetBuf(void) const {
        return m_null == true ? NULL : m_buf;
    };
    virtual size_t GetLen(void) const { return m_len; };
    virtual const char *GetFmt(void) const {
        if (IsFmtValid() == false) {
            if (m_bytestr) {
                return BuildFmt(m_buf, m_len);
            }
            else {
                return BuildFmt(m_buf);
            }
        }
        return m_fmtbuf;
    };

    bool operator == (const TextBuf &other) const {
        //assert(other.IsByteStr() == IsByteStr());
        if (IsNull() || other.IsNull() ) {
            return false;
        }
        if (IsByteStr()) {
            if (GetLen() != other.GetLen()) {
                return false;
            }
            return (memcmp(GetBuf(), other.GetBuf(), GetLen()) == 0);
        }
        else {
            return (strcmp(GetBuf(), other.GetBuf()) == 0);
        }
    };

    bool operator != (const TextBuf &other) const {
        return !(*this == other);
    };

    const char *BuildFmt(void) const {
        if (m_bytestr) {
            return BuildFmt(m_buf, m_len);
        }
        else {
            return BuildFmt(m_buf);
        }
    }

    const char *BuildFmt(const char *str) const {
        return BuildFmt(str, strlen(str));
    };

    const char *BuildFmt(const char *str, size_t len) const {
        char *buf = m_fmtbuf;
        const char *end = m_fmtbuf + m_fmtsize;
        size_t n = 0;
        while ( (n < len) && (buf < end) ) {
            if (*str == '\n') {
                *buf++ = '\\';
                *buf++ = 'n';
            }
            else if (*str == '\t') {
                *buf++ = '\\';
                *buf++ = 't';
            }
            else if (*str == '\0') {
                *buf++ = '\\';
                *buf++ = '0';
            }
            else {
                *buf++ = *str;
            }
            ++str;
            ++n;
        }
        *buf = '\0';
        m_fmtvalid = true;
        return m_fmtbuf;
    };

protected:
    size_t        m_size;
    char         *m_buf;
    bool          m_bytestr;
    bool          m_null;
    size_t        m_len;
    size_t        m_fmtsize;
    // The formatted buffer is mutable
    mutable char *m_fmtbuf;
    mutable bool  m_fmtvalid;

};

<|endoftext|>


<commit_before>// Author: Guido Volpi 12/10/2007

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TPieEditor                                                          //
//                                                                      //
//  Implements GUI for pie-chart attributes.                            //
//                                                                      //
//  Title': set the title of the graph                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
//Begin_Html
/*

*/
//End_Html

#include "TGedEditor.h"
#include "TGComboBox.h"
#include "TGButtonGroup.h"
#include "TPieEditor.h"
#include "TGTextEntry.h"
#include "TGNumberEntry.h"
#include "TGToolTip.h"
#include "TGLabel.h"
#include "TPie.h"
#include "TVirtualPad.h"
#include "TGColorSelect.h"
#include "TGComboBox.h"
#include "TColor.h"
#include "TBox.h"
#include "TPaveLabel.h"

ClassImp(TPieEditor)

enum EPieWid {
   kPie = 0,
   kPIE_HOR,
   kPIE_RAD,
   kPIE_TAN,
   kPIE_FILL,
   kPIE_OUTLINE,
   kPIE_TITLE,
   kPIE_3D,
   kPIE_3DANGLE,
   kPIE_3DTHICKNESS,
   kFONT_COLOR,
   kFONT_SIZE,
   kFONT_STYLE
};

//______________________________________________________________________________
TPieEditor::TPieEditor(const TGWindow *p, Int_t width,
                         Int_t height, UInt_t options, Pixel_t back)
   : TGedFrame(p, width, height, options | kVerticalFrame, back)
{
   // Constructor of graph editor.

   fPie = 0;
   // TextEntry to change the title
   MakeTitle("Pie Chart");

   fTitle = new TGTextEntry(this, new TGTextBuffer(50), kPIE_TITLE);
   fTitle->Resize(135, fTitle->GetDefaultHeight());
   fTitle->SetToolTipText("Enter the pie title string");
   // better take kLHintsLeft and Right - Right is not working at the moment
   AddFrame(fTitle, new TGLayoutHints(kLHintsLeft, 3, 1, 2, 5));

   // Radio Buttons to change the draw options of the graph
   TGCompositeFrame *f2 = new TGCompositeFrame(this, 80, 20, kVerticalFrame);
   fgr = new TGButtonGroup(f2,3,1,3,5,"Label direction");
   fgr->SetRadioButtonExclusive(kTRUE);
   fLblDirH = new TGRadioButton(fgr,"Horizontal",kPIE_HOR);   // no draw option
   fLblDirH->SetToolTipText("Draw horizontal labels");
   fLblDirR = new TGRadioButton(fgr,"Radial",kPIE_RAD);  // option C
   fLblDirR->SetToolTipText("Draw labels radially");
   fLblDirT = new TGRadioButton(fgr,"Tangential",kPIE_TAN); // option L
   fLblDirT->SetToolTipText("Draw labels tangential to the piechart");

   fgr->SetLayoutHints(fShape1lh=new TGLayoutHints(kLHintsLeft, 0,3,0,0), fLblDirH);
   fgr->Show();
   fgr->ChangeOptions(kFitWidth|kChildFrame|kVerticalFrame);
   f2->AddFrame(fgr, new TGLayoutHints(kLHintsLeft, 4, 0, 0, 0));

   // CheckBox to activate/deactivate the drawing of the Marker
   fOutlineOnOff = new TGCheckButton(f2,"Outline",kPIE_OUTLINE);
   fOutlineOnOff->SetToolTipText("Draw a line to mark the pie");
   f2->AddFrame(fOutlineOnOff, new TGLayoutHints(kLHintsTop, 5, 1, 0, 3));
   AddFrame(f2, new TGLayoutHints(kLHintsTop, 1, 1, 0, 0));

   // Exclusion zone parameters
   MakeTitle("3D options");
   TGCompositeFrame *f3 = new TGCompositeFrame(this, 80, 20, kHorizontalFrame);
   AddFrame(f3, new TGLayoutHints(kLHintsTop, 1, 1, 5, 0));

   fIs3D = new TGCheckButton(f3,"3D",kPIE_3D);
   fIs3D->SetToolTipText("Draw a 3D charts");
   f3->AddFrame(fIs3D, new TGLayoutHints(kLHintsTop, 5, 1, 0, 0));

   f3DAngle = new TGNumberEntry(f3, 0, 2, kPIE_3DANGLE,  TGNumberEntry::kNESInteger, TGNumberEntry::kNEANonNegative,TGNumberFormat::kNELLimitMinMax, 0, 90);
   //f3DAngle->SetToolTipText("3D angle: 0-90")
   f3DAngle->Resize(50, 20);
   f3->AddFrame(f3DAngle, new TGLayoutHints(kLHintsLeft, 7, 1, 1, 1));
   f3DAngle->Associate(f3);

   f3DHeight = new TGNumberEntry(f3, 0, 3, kPIE_3DTHICKNESS,  TGNumberEntry::kNESReal, TGNumberEntry::kNEANonNegative);
   //f3DHeight->SetToolTipText("3D thick")
   f3DHeight->Resize(50, 20);
   f3->AddFrame(f3DHeight, new TGLayoutHints(kLHintsLeft, 7, 1, 1, 1));
   f3DHeight->Associate(f3);

   MakeTitle("Text");
   TGCompositeFrame *f4 = new TGCompositeFrame(this, 80, 20, kHorizontalFrame);
   fColorSelect = new TGColorSelect(f4, 0, kFONT_COLOR);
   f4->AddFrame(fColorSelect, new TGLayoutHints(kLHintsLeft, 1, 1, 1, 1));
   fColorSelect->Associate(this);
   fSizeCombo = BuildFontSizeComboBox(f4, kFONT_SIZE);
   f4->AddFrame(fSizeCombo, new TGLayoutHints(kLHintsLeft, 3, 1, 1, 1));
   fSizeCombo->Resize(91, 20);
   fSizeCombo->Associate(this);
   AddFrame(f4, new TGLayoutHints(kLHintsTop, 1, 1, 0, 0));
   fTypeCombo = new TGFontTypeComboBox(this, kFONT_STYLE);
   fTypeCombo->Resize(137, 20);
   AddFrame(fTypeCombo, new TGLayoutHints(kLHintsLeft, 3, 1, 1, 1));
}

//______________________________________________________________________________
TPieEditor::~TPieEditor()
{
   // Destructor of pie editor.
}

//_____________________________________________________________________________
void TPieEditor::ConnectSignals2Slots()
{
   // Connect signals to slots.

   fTitle->Connect("TextChanged(const char *)","TPieEditor",this,"DoTitle(const char *)");
   fgr->Connect("Clicked(Int_t)","TPieEditor",this,"DoShape()");
   fOutlineOnOff->Connect("Toggled(Bool_t)","TPieEditor",this,"DoMarkerOnOff(Bool_t)");
   f3DAngle->Connect("ValueSet(Long_t)", "TPieEditor", this, "DoChange3DAngle()");
   f3DHeight->Connect("ValueSet(Long_t)", "TPieEditor", this, "DoChange3DAngle()");
   fIs3D->Connect("Clicked()","TPieEditor",this,"DoGraphLineWidth()");

   // text attributes connection
   fTypeCombo->Connect("Selected(Int_t)","TPieEditor",this,"DoTextChange()");
   fSizeCombo->Connect("Selected(Int_t)","TPieEditor",this,"DoTextChange()");
   fColorSelect->Connect("ColorSelected(Pixel_t)","TPieEditor",this,"DoTextChange()");

   fInit = kFALSE;  // connect the slots to the signals only once
}

//______________________________________________________________________________
void TPieEditor::ActivateBaseClassEditors(TClass* cl)
{
   // Exclude TAttTextEditor from this interface.
   TGedEditor *fGedEditor = GetGedEditor();
   fGedEditor->ExcludeClassEditor(TAttText::Class());
   TGedFrame::ActivateBaseClassEditors(cl);
}

//______________________________________________________________________________
void TPieEditor::SetModel(TObject* obj)
{
   // Pick up the used values of graph attributes.

   fPie = (TPie *)obj;
   fAvoidSignal = kTRUE;

   // set the Title TextEntry
   const char *text = fPie->GetTitle();
   fTitle->SetText(text);

   TString soption = GetDrawOption();

   bool optionSame(kFALSE);

   // For the label orientation there are 3 possibilities:
   //   0: horizontal
   //   1: radial
   //   2: tangent
   Int_t lblor(0);

   // Parse the options
   Int_t idx;
   // Paint the TPie in an existing canvas
   if ( (idx=soption.Index("same"))>=0 ) {
      optionSame = kTRUE;
      soption.Remove(idx,4);
   }

   if ( (idx=soption.Index("nol"))>=0 ) {
      fOutlineOnOff->SetState(kButtonUp,kFALSE);
      soption.Remove(idx,3);
   }
   else {
      fOutlineOnOff->SetState(kButtonDown,kFALSE);
   }

   // check if is active the pseudo-3d
   if ( (idx=soption.Index("3d"))>=0 ) {
      fIs3D->SetState(kButtonDown, kFALSE);
      f3DAngle->SetNumber(fPie->GetAngle3D());
      f3DHeight->SetNumber(fPie->GetHeight());
      soption.Remove(idx,2);
   } else {
      fIs3D->SetState(kButtonUp, kFALSE);
   }

   // seek if have to draw the labels around the pie chart
   if ( (idx=soption.Index("t"))>=0 ) {
      lblor = 2;
      soption.Remove(idx,1);
   }

   // Seek if have to paint the labels along the radii
   if ( (idx=soption.Index("r"))>=0 ) {
      lblor = 1;
      soption.Remove(idx,1);
   }

   switch(lblor) {
   case 0:
      fLblDirH->SetState(kButtonDown,kTRUE);
      break;
   case 1:
      fLblDirR->SetState(kButtonDown,kTRUE);
      break;
   case 2:
      fLblDirT->SetState(kButtonDown,kTRUE);
      break;
   }

   // set text attributes
   fTypeCombo->Select(fPie->GetTextFont() / 10);

   Color_t c = fPie->GetTextColor();
   Pixel_t p = TColor::Number2Pixel(c);
   fColorSelect->SetColor(p, kFALSE);

   Float_t s = fPie->GetTextSize();
   Float_t dy;

   if (obj->InheritsFrom(TPaveLabel::Class())) {
      TBox *pl = (TBox*)obj;
      dy = s * (pl->GetY2() - pl->GetY1());
   }
   else
      dy = s * (fGedEditor->GetPad()->GetY2() - fGedEditor->GetPad()->GetY1());

   Int_t size = fGedEditor->GetPad()->YtoPixel(0.0) - fGedEditor->GetPad()->YtoPixel(dy);
   if (size > 50) size = 50;
   if (size < 0)  size = 0;
   fSizeCombo->Select(size, kFALSE);

   if (fInit) ConnectSignals2Slots();
   fAvoidSignal = kFALSE;
}

//______________________________________________________________________________
void TPieEditor::DoTitle(const char *text)
{
   // Slot for setting the graph title.

   if (fAvoidSignal) return;
   fPie->SetTitle(text);
   Update();
}

//______________________________________________________________________________
void TPieEditor::DoShape()
{
   // Slot connected to the draw options.

   if (fAvoidSignal) return;

   TString opt = GetDrawOption();

   if (fLblDirH->GetState()==kButtonDown) {
      if (opt.Contains("t")) opt.Remove(opt.First("t"),1);
      if (opt.Contains("r")) opt.Remove(opt.First("r"),1);
   }
   else if (fLblDirR->GetState()==kButtonDown) {
      if (opt.Contains("t")) opt.Remove(opt.First("t"),1);
      if (!opt.Contains("r")) opt += "r";
   }
   else if (fLblDirT->GetState()==kButtonDown) {
      if (!opt.Contains("t")) opt += "t";
      if (opt.Contains("r")) opt.Remove(opt.First("r"),1);
   }

   SetDrawOption(opt);
   if (gPad) gPad->GetVirtCanvas()->SetCursor(kPointer);
   gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kPointer));
}

//______________________________________________________________________________
void TPieEditor::DoMarkerOnOff(Bool_t)
{
   // Slot for setting markers as visible/invisible.

   if (fAvoidSignal) return;
   TString t = GetDrawOption();

   if (t.Contains("nol") && fOutlineOnOff->GetState() == kButtonDown) {
      t.Remove(t.First("nol"),3);
   }
   else if (!t.Contains("nol") && fOutlineOnOff->GetState() == kButtonUp) {
      t += "nol";
   }

   SetDrawOption(t);
}

//______________________________________________________________________________
void TPieEditor::DoChange3DAngle()
{
   // Slot for setting the 3D angle
   if (fAvoidSignal) return;

   fPie->SetAngle3D(static_cast<Int_t>(f3DAngle->GetNumber()));
   fPie->SetHeight(f3DHeight->GetNumber());

   Update();

}

//______________________________________________________________________________
void TPieEditor::DoGraphLineWidth()
{
   // Slot connected to the graph line width.
   if (fAvoidSignal) return;

   TString opt = GetDrawOption();
   if (!opt.Contains("3d") && fIs3D->IsDown())
      opt += "3d";
   else if (opt.Contains("3d") && !fIs3D->IsDown())
      opt.Remove(opt.First("3d"),2);

   SetDrawOption(opt);

   Update();
}

//______________________________________________________________________________
void TPieEditor::DoTextChange()
{
   if (fAvoidSignal) return;

   fPie->SetTextColor(TColor::GetColor(fColorSelect->GetColor()));

   fPie->SetTextFont(fTypeCombo->GetSelected()*10);

   TVirtualPad* pad = fGedEditor->GetPad();

   Float_t val = TString(fSizeCombo->GetSelectedEntry()->GetTitle()).Atoi();

   Float_t dy = pad->AbsPixeltoY(0) - pad->AbsPixeltoY(val);
   Float_t textSize;

   if (fGedEditor->GetModel()->InheritsFrom(TPaveLabel::Class())) {
      TBox *pl = (TBox*)fGedEditor->GetModel();
      textSize = dy/(pl->GetY2() - pl->GetY1());
   }
   else
      textSize = dy/(pad->GetY2() - pad->GetY1());

   fPie->SetTextSize(textSize);

   Update();

}

//______________________________________________________________________________
TGComboBox* TPieEditor::BuildFontSizeComboBox(TGFrame* parent, Int_t id)
{
   // Create text size combo box.

   char a[100];
   TGComboBox *c = new TGComboBox(parent, id);

   c->AddEntry("Default", 0);
   for (int i = 1; i <= 50; i++) {
      snprintf(a, 100, "%d", i);
      c->AddEntry(a, i);
   }

   return c;
}
<commit_msg>- Several fixes:   - One missing include for windows.   - One shadowed variable.   - One wrong argument type.<commit_after>// Author: Guido Volpi 12/10/2007

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TPieEditor                                                          //
//                                                                      //
//  Implements GUI for pie-chart attributes.                            //
//                                                                      //
//  Title': set the title of the graph                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
//Begin_Html
/*

*/
//End_Html

#include "snprintf.h"
#include "TGedEditor.h"
#include "TGComboBox.h"
#include "TGButtonGroup.h"
#include "TPieEditor.h"
#include "TGTextEntry.h"
#include "TGNumberEntry.h"
#include "TGToolTip.h"
#include "TGLabel.h"
#include "TPie.h"
#include "TVirtualPad.h"
#include "TGColorSelect.h"
#include "TGComboBox.h"
#include "TColor.h"
#include "TBox.h"
#include "TPaveLabel.h"

ClassImp(TPieEditor)

enum EPieWid {
   kPie = 0,
   kPIE_HOR,
   kPIE_RAD,
   kPIE_TAN,
   kPIE_FILL,
   kPIE_OUTLINE,
   kPIE_TITLE,
   kPIE_3D,
   kPIE_3DANGLE,
   kPIE_3DTHICKNESS,
   kFONT_COLOR,
   kFONT_SIZE,
   kFONT_STYLE
};

//______________________________________________________________________________
TPieEditor::TPieEditor(const TGWindow *p, Int_t width,
                         Int_t height, UInt_t options, Pixel_t back)
   : TGedFrame(p, width, height, options | kVerticalFrame, back)
{
   // Constructor of graph editor.

   fPie = 0;
   // TextEntry to change the title
   MakeTitle("Pie Chart");

   fTitle = new TGTextEntry(this, new TGTextBuffer(50), kPIE_TITLE);
   fTitle->Resize(135, fTitle->GetDefaultHeight());
   fTitle->SetToolTipText("Enter the pie title string");
   // better take kLHintsLeft and Right - Right is not working at the moment
   AddFrame(fTitle, new TGLayoutHints(kLHintsLeft, 3, 1, 2, 5));

   // Radio Buttons to change the draw options of the graph
   TGCompositeFrame *f2 = new TGCompositeFrame(this, 80, 20, kVerticalFrame);
   fgr = new TGButtonGroup(f2,3,1,3,5,"Label direction");
   fgr->SetRadioButtonExclusive(kTRUE);
   fLblDirH = new TGRadioButton(fgr,"Horizontal",kPIE_HOR);   // no draw option
   fLblDirH->SetToolTipText("Draw horizontal labels");
   fLblDirR = new TGRadioButton(fgr,"Radial",kPIE_RAD);  // option C
   fLblDirR->SetToolTipText("Draw labels radially");
   fLblDirT = new TGRadioButton(fgr,"Tangential",kPIE_TAN); // option L
   fLblDirT->SetToolTipText("Draw labels tangential to the piechart");

   fgr->SetLayoutHints(fShape1lh=new TGLayoutHints(kLHintsLeft, 0,3,0,0), fLblDirH);
   fgr->Show();
   fgr->ChangeOptions(kFitWidth|kChildFrame|kVerticalFrame);
   f2->AddFrame(fgr, new TGLayoutHints(kLHintsLeft, 4, 0, 0, 0));

   // CheckBox to activate/deactivate the drawing of the Marker
   fOutlineOnOff = new TGCheckButton(f2,"Outline",kPIE_OUTLINE);
   fOutlineOnOff->SetToolTipText("Draw a line to mark the pie");
   f2->AddFrame(fOutlineOnOff, new TGLayoutHints(kLHintsTop, 5, 1, 0, 3));
   AddFrame(f2, new TGLayoutHints(kLHintsTop, 1, 1, 0, 0));

   // Exclusion zone parameters
   MakeTitle("3D options");
   TGCompositeFrame *f3 = new TGCompositeFrame(this, 80, 20, kHorizontalFrame);
   AddFrame(f3, new TGLayoutHints(kLHintsTop, 1, 1, 5, 0));

   fIs3D = new TGCheckButton(f3,"3D",kPIE_3D);
   fIs3D->SetToolTipText("Draw a 3D charts");
   f3->AddFrame(fIs3D, new TGLayoutHints(kLHintsTop, 5, 1, 0, 0));

   f3DAngle = new TGNumberEntry(f3, 0, 2, kPIE_3DANGLE,  TGNumberEntry::kNESInteger, TGNumberEntry::kNEANonNegative,TGNumberFormat::kNELLimitMinMax, 0, 90);
   //f3DAngle->SetToolTipText("3D angle: 0-90")
   f3DAngle->Resize(50, 20);
   f3->AddFrame(f3DAngle, new TGLayoutHints(kLHintsLeft, 7, 1, 1, 1));
   f3DAngle->Associate(f3);

   f3DHeight = new TGNumberEntry(f3, 0, 3, kPIE_3DTHICKNESS,  TGNumberEntry::kNESReal, TGNumberEntry::kNEANonNegative);
   //f3DHeight->SetToolTipText("3D thick")
   f3DHeight->Resize(50, 20);
   f3->AddFrame(f3DHeight, new TGLayoutHints(kLHintsLeft, 7, 1, 1, 1));
   f3DHeight->Associate(f3);

   MakeTitle("Text");
   TGCompositeFrame *f4 = new TGCompositeFrame(this, 80, 20, kHorizontalFrame);
   fColorSelect = new TGColorSelect(f4, 0, kFONT_COLOR);
   f4->AddFrame(fColorSelect, new TGLayoutHints(kLHintsLeft, 1, 1, 1, 1));
   fColorSelect->Associate(this);
   fSizeCombo = BuildFontSizeComboBox(f4, kFONT_SIZE);
   f4->AddFrame(fSizeCombo, new TGLayoutHints(kLHintsLeft, 3, 1, 1, 1));
   fSizeCombo->Resize(91, 20);
   fSizeCombo->Associate(this);
   AddFrame(f4, new TGLayoutHints(kLHintsTop, 1, 1, 0, 0));
   fTypeCombo = new TGFontTypeComboBox(this, kFONT_STYLE);
   fTypeCombo->Resize(137, 20);
   AddFrame(fTypeCombo, new TGLayoutHints(kLHintsLeft, 3, 1, 1, 1));
}

//______________________________________________________________________________
TPieEditor::~TPieEditor()
{
   // Destructor of pie editor.
}

//_____________________________________________________________________________
void TPieEditor::ConnectSignals2Slots()
{
   // Connect signals to slots.

   fTitle->Connect("TextChanged(const char *)","TPieEditor",this,"DoTitle(const char *)");
   fgr->Connect("Clicked(Int_t)","TPieEditor",this,"DoShape()");
   fOutlineOnOff->Connect("Toggled(Bool_t)","TPieEditor",this,"DoMarkerOnOff(Bool_t)");
   f3DAngle->Connect("ValueSet(Long_t)", "TPieEditor", this, "DoChange3DAngle()");
   f3DHeight->Connect("ValueSet(Long_t)", "TPieEditor", this, "DoChange3DAngle()");
   fIs3D->Connect("Clicked()","TPieEditor",this,"DoGraphLineWidth()");

   // text attributes connection
   fTypeCombo->Connect("Selected(Int_t)","TPieEditor",this,"DoTextChange()");
   fSizeCombo->Connect("Selected(Int_t)","TPieEditor",this,"DoTextChange()");
   fColorSelect->Connect("ColorSelected(Pixel_t)","TPieEditor",this,"DoTextChange()");

   fInit = kFALSE;  // connect the slots to the signals only once
}

//______________________________________________________________________________
void TPieEditor::ActivateBaseClassEditors(TClass* cl)
{
   // Exclude TAttTextEditor from this interface.
   TGedEditor *GedEditor = GetGedEditor();
   GedEditor->ExcludeClassEditor(TAttText::Class());
   TGedFrame::ActivateBaseClassEditors(cl);
}

//______________________________________________________________________________
void TPieEditor::SetModel(TObject* obj)
{
   // Pick up the used values of graph attributes.

   fPie = (TPie *)obj;
   fAvoidSignal = kTRUE;

   // set the Title TextEntry
   const char *text = fPie->GetTitle();
   fTitle->SetText(text);

   TString soption = GetDrawOption();

   bool optionSame(kFALSE);

   // For the label orientation there are 3 possibilities:
   //   0: horizontal
   //   1: radial
   //   2: tangent
   Int_t lblor(0);

   // Parse the options
   Int_t idx;
   // Paint the TPie in an existing canvas
   if ( (idx=soption.Index("same"))>=0 ) {
      optionSame = kTRUE;
      soption.Remove(idx,4);
   }

   if ( (idx=soption.Index("nol"))>=0 ) {
      fOutlineOnOff->SetState(kButtonUp,kFALSE);
      soption.Remove(idx,3);
   }
   else {
      fOutlineOnOff->SetState(kButtonDown,kFALSE);
   }

   // check if is active the pseudo-3d
   if ( (idx=soption.Index("3d"))>=0 ) {
      fIs3D->SetState(kButtonDown, kFALSE);
      f3DAngle->SetNumber(fPie->GetAngle3D());
      f3DHeight->SetNumber(fPie->GetHeight());
      soption.Remove(idx,2);
   } else {
      fIs3D->SetState(kButtonUp, kFALSE);
   }

   // seek if have to draw the labels around the pie chart
   if ( (idx=soption.Index("t"))>=0 ) {
      lblor = 2;
      soption.Remove(idx,1);
   }

   // Seek if have to paint the labels along the radii
   if ( (idx=soption.Index("r"))>=0 ) {
      lblor = 1;
      soption.Remove(idx,1);
   }

   switch(lblor) {
   case 0:
      fLblDirH->SetState(kButtonDown,kTRUE);
      break;
   case 1:
      fLblDirR->SetState(kButtonDown,kTRUE);
      break;
   case 2:
      fLblDirT->SetState(kButtonDown,kTRUE);
      break;
   }

   // set text attributes
   fTypeCombo->Select(fPie->GetTextFont() / 10);

   Color_t c = fPie->GetTextColor();
   Pixel_t p = TColor::Number2Pixel(c);
   fColorSelect->SetColor(p, kFALSE);

   Float_t s = fPie->GetTextSize();
   Float_t dy;

   if (obj->InheritsFrom(TPaveLabel::Class())) {
      TBox *pl = (TBox*)obj;
      dy = s * (pl->GetY2() - pl->GetY1());
   }
   else
      dy = s * (fGedEditor->GetPad()->GetY2() - fGedEditor->GetPad()->GetY1());

   Int_t size = fGedEditor->GetPad()->YtoPixel(0.0) - fGedEditor->GetPad()->YtoPixel(dy);
   if (size > 50) size = 50;
   if (size < 0)  size = 0;
   fSizeCombo->Select(size, kFALSE);

   if (fInit) ConnectSignals2Slots();
   fAvoidSignal = kFALSE;
}

//______________________________________________________________________________
void TPieEditor::DoTitle(const char *text)
{
   // Slot for setting the graph title.

   if (fAvoidSignal) return;
   fPie->SetTitle(text);
   Update();
}

//______________________________________________________________________________
void TPieEditor::DoShape()
{
   // Slot connected to the draw options.

   if (fAvoidSignal) return;

   TString opt = GetDrawOption();

   if (fLblDirH->GetState()==kButtonDown) {
      if (opt.Contains("t")) opt.Remove(opt.First("t"),1);
      if (opt.Contains("r")) opt.Remove(opt.First("r"),1);
   }
   else if (fLblDirR->GetState()==kButtonDown) {
      if (opt.Contains("t")) opt.Remove(opt.First("t"),1);
      if (!opt.Contains("r")) opt += "r";
   }
   else if (fLblDirT->GetState()==kButtonDown) {
      if (!opt.Contains("t")) opt += "t";
      if (opt.Contains("r")) opt.Remove(opt.First("r"),1);
   }

   SetDrawOption(opt);
   if (gPad) gPad->GetVirtCanvas()->SetCursor(kPointer);
   gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kPointer));
}

//______________________________________________________________________________
void TPieEditor::DoMarkerOnOff(Bool_t)
{
   // Slot for setting markers as visible/invisible.

   if (fAvoidSignal) return;
   TString t = GetDrawOption();

   if (t.Contains("nol") && fOutlineOnOff->GetState() == kButtonDown) {
      t.Remove(t.First("nol"),3);
   }
   else if (!t.Contains("nol") && fOutlineOnOff->GetState() == kButtonUp) {
      t += "nol";
   }

   SetDrawOption(t);
}

//______________________________________________________________________________
void TPieEditor::DoChange3DAngle()
{
   // Slot for setting the 3D angle
   if (fAvoidSignal) return;

   fPie->SetAngle3D(static_cast<Int_t>(f3DAngle->GetNumber()));
   fPie->SetHeight(f3DHeight->GetNumber());

   Update();

}

//______________________________________________________________________________
void TPieEditor::DoGraphLineWidth()
{
   // Slot connected to the graph line width.
   if (fAvoidSignal) return;

   TString opt = GetDrawOption();
   if (!opt.Contains("3d") && fIs3D->IsDown())
      opt += "3d";
   else if (opt.Contains("3d") && !fIs3D->IsDown())
      opt.Remove(opt.First("3d"),2);

   SetDrawOption(opt);

   Update();
}

//______________________________________________________________________________
void TPieEditor::DoTextChange()
{
   if (fAvoidSignal) return;

   fPie->SetTextColor(TColor::GetColor(fColorSelect->GetColor()));

   fPie->SetTextFont(fTypeCombo->GetSelected()*10);

   TVirtualPad* pad = fGedEditor->GetPad();

   Float_t val = TString(fSizeCombo->GetSelectedEntry()->GetTitle()).Atoi();

   Float_t dy = pad->AbsPixeltoY(0) - pad->AbsPixeltoY((Int_t)val);
   Float_t textSize;

   if (fGedEditor->GetModel()->InheritsFrom(TPaveLabel::Class())) {
      TBox *pl = (TBox*)fGedEditor->GetModel();
      textSize = dy/(pl->GetY2() - pl->GetY1());
   }
   else
      textSize = dy/(pad->GetY2() - pad->GetY1());

   fPie->SetTextSize(textSize);

   Update();

}

//______________________________________________________________________________
TGComboBox* TPieEditor::BuildFontSizeComboBox(TGFrame* parent, Int_t id)
{
   // Create text size combo box.

   char a[100];
   TGComboBox *c = new TGComboBox(parent, id);

   c->AddEntry("Default", 0);
   for (int i = 1; i <= 50; i++) {
      snprintf(a, 100, "%d", i);
      c->AddEntry(a, i);
   }

   return c;
}
<|endoftext|>