<commit_before>/******************************************************************
 *
 * Copyright 2016 Samsung Electronics 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.
 *
 ******************************************************************/

// std
#include <iostream>
#include <stdlib.h>
#include <cstdint>
#include <limits>

// ns
#include "NSCommon.h"
#include "NSProviderService.h"
#include "NSUtils.h"
#include "NSTopicsList.h"

// base
#include "logger.h"
#include "octypes.h"
#include "oic_string.h"
#include "oic_malloc.h"
#include "ocstack.h"

// external
#include "pthread.h"

#define TAG "NotiProviderWrapperExample"
using namespace std;
using namespace OIC::Service;
std::vector<std::string> discoveredConsumers;
uint64_t mainMessageId = 0;

extern char *strdup(const char *s);

bool isExit = false;

int id = 0;
std::string REMOTE_SERVER_ADDRESS;

void *OCProcessThread(void *ptr)
{
    (void) ptr;
    while (!isExit)
    {
        usleep(2000);
        if (OCProcess() != OC_STACK_OK)
        {
            std::cout << "OCStack process error" << std::endl;
            return NULL;
        }
    }

    return NULL;
}

void subscribeRequestCallback(std::shared_ptr<OIC::Service::NSConsumer> consumer)
{
    std::cout << "consumer requested to subscribe" << std::endl;

    std::cout << "Consumer Device ID: " << consumer->getConsumerId() << std::endl;
    discoveredConsumers.push_back(consumer->getConsumerId());
    consumer->acceptSubscription(true);
}

void syncCallback(OIC::Service::NSSyncInfo sync)
{
    std::cout << "SyncInfo Received " << std::endl;
    std::cout << "Sync ID : " <<  sync.getMessageId() << std::endl;
    std::cout << "Provider ID : " <<  sync.getProviderId() << std::endl;
    std::cout << "Sync State: " << (int) sync.getState() << std::endl;
}

std::shared_ptr<OIC::Service::NSConsumer> printAvailableConsumers()
{
    std::cout << "Choose the Consumer ID for operation" << std::endl;
    int pos = 1;
    unsigned int option = 0;
    for (auto it : discoveredConsumers)
    {
        std::cout << pos << ". " << it << std::endl;
        pos++;
    }
    while (!(std::cin >> option))
    {
        std::cout << "Bad value!" << std::endl;;
        std::cin.clear();
        std::cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }
    option--;
    if (option > discoveredConsumers.size())
    {
        return NULL;
    }
    std::string consumerId = discoveredConsumers[option];
    std::shared_ptr<OIC::Service::NSConsumer> consumer =
        NSProviderService::getInstance()->getConsumer(consumerId);
    return consumer;
}

int main()
{
    int num = 0;
    pthread_t processThread = 0;

    std::cout << "start Iotivity" << std::endl;

    if (OCInit(NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)
    {
        std::cout << "OCStack init error" << std::endl;
        return 0;
    }

    pthread_create(&processThread, NULL, OCProcessThread, NULL);

    while (!isExit)
    {
        std::cout << "1. Start the Notification Provider(Accepter: Provider)" << std::endl;
        std::cout << "2. Start the Notification Provider(Accepter: Consumer)" << std::endl;
        std::cout << "3. Allow Subscription" << std::endl;
        std::cout << "4. Deny Subscription" << std::endl;
        std::cout << "5. SendMessage " << std::endl;
        std::cout << "6. SendSyncInfo" << std::endl;

        std::cout << "7. RegisterTopic" << std::endl;
        std::cout << "8. UnregisterTopic" << std::endl;
        std::cout << "9. SetTopic" << std::endl;
        std::cout << "10. UnsetTopic" << std::endl;
        std::cout << "11. GetConsumerTopicList" << std::endl;
        std::cout << "12. GetRegisteredTopicList" << std::endl;
#ifdef WITH_CLOUD
        std::cout << "13. Enable NS Provider RemoteService" << std::endl;
        std::cout << "14. Disable NS Provider RemoteService" << std::endl;
#endif
        std::cout << "15. Stop the Notification Provider" << std::endl;
        std::cout << "16. Exit()" << std::endl;

        std::cout << "input : ";

        std::cin >> num;

        switch (num)
        {
            case 1:
                {
                    std::cout << "Start (Accepter: Provider)" << std::endl;
                    NSProviderService::ProviderConfig cfg;
                    cfg.m_subscribeRequestCb = subscribeRequestCallback;
                    cfg.m_syncInfoCb = syncCallback;
                    cfg.subControllability = true;

                    NSProviderService::getInstance()->start(cfg);
                    break;
                }
            case 2:
                {
                    std::cout << "Start (Accepter: Consumer)" << std::endl;
                    NSProviderService::ProviderConfig cfg;
                    cfg.m_subscribeRequestCb = subscribeRequestCallback;
                    cfg.m_syncInfoCb = syncCallback;
                    cfg.subControllability = false;

                    NSProviderService::getInstance()->start(cfg);
                    break;
                }
            case 3:
                {
                    std::cout << "Allow Subscription" << std::endl;
                    std::shared_ptr<OIC::Service::NSConsumer> consumer = printAvailableConsumers();
                    if (consumer != nullptr)
                    {
                        std::cout << "ALLOW" << std::endl;
                        consumer->acceptSubscription(true);
                    }
                    break;
                }
            case 4:
                {
                    std::cout << "Deny Subscription" << std::endl;
                    std::shared_ptr<OIC::Service::NSConsumer>consumer = printAvailableConsumers();
                    if (consumer != nullptr)
                    {
                        std::cout << "DENY" << std::endl;
                        consumer->acceptSubscription(false);
                    }
                    break;
                }
            case 5:
                {
                    std::cout << "------------------------------------" << std::endl;
                    std::cout << "SendMessage" << std::endl;
                    std::cout << "------------------------------------" << std::endl;

                    std::string dummy;
                    std::string title;
                    std::string body;
                    std::string topic;

                    std::cout << "id : " << ++id << std::endl;
                    std::cout << "title : ";

                    std::getline(std::cin, dummy);
                    std::getline(std::cin, title);

                    std::cout << "body : ";
                    std::getline(std::cin, body);

                    std::cout << "topic : ";
                    std::getline(std::cin, topic);

                    std::cout << "app - mTitle : " << title << std::endl;
                    std::cout << "app - mContentText : " << body << std::endl;
                    std::cout << "app - mTopic : " << topic << std::endl;

                    OIC::Service::NSMessage msg = NSProviderService::getInstance()->createMessage();

                    msg.setType(OIC::Service::NSMessage::NSMessageType::NS_MESSAGE_INFO);
                    msg.setTitle(title.c_str());
                    msg.setContentText(body.c_str());
                    msg.setSourceName("OCF");
                    msg.setTopic(topic);
                    msg.setTTL(40);
                    msg.setTime("12:30");
                    OIC::Service::NSMediaContents *mediaContents =
                        new OIC::Service::NSMediaContents("iconImage");
                    msg.setMediaContents(mediaContents);

                    OC::OCRepresentation rep;
                    rep.setValue("Key1", "Value1");
                    rep.setValue("Key2", "Value2");
                    msg.setExtraInfo(rep);

                    mainMessageId = msg.getMessageId();
                    std::cout << "ProviderID for Message : " << msg.getProviderId() << std::endl;
                    std::cout << "MessageID for Message : " << msg.getMessageId() << std::endl;

                    NSProviderService::getInstance()->sendMessage(msg);
                    break;
                }
            case 6:
                {
                    std::cout << "------------------------------------" << std::endl;
                    std::cout <<  "SendSyncInfo" << std::endl;
                    std::cout << "------------------------------------" << std::endl;
                    if (!mainMessageId)
                    {
                        std::cout <<  "Message ID is empty" << std::endl;
                        break;
                    }
                    std::cout << "1. Send Read Sync" << std::endl;
                    std::cout << "2. Send Delete Sync" << std::endl;
                    int syn = 0;
                    while (!(std::cin >> syn))
                    {
                        std::cout << "Bad value!" << std::endl;;
                        std::cin.clear();
                        std::cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    }
                    switch (syn)
                    {
                        case 1:
                            {
                                std::cout << "Sending Read Sync" << std::endl;
                                NSProviderService::getInstance()->sendSyncInfo(mainMessageId,
                                        OIC::Service::NSSyncInfo::NSSyncType::NS_SYNC_READ);
                            }
                            break;
                        case 2:
                            {
                                std::cout << "Sending Delete Sync" << std::endl;
                                NSProviderService::getInstance()->sendSyncInfo(mainMessageId,
                                        OIC::Service::NSSyncInfo::NSSyncType::NS_SYNC_DELETED);
                            }
                            break;
                        default:
                            {
                                cout << "Invalid Input!. sending default Read Sync";
                                NSProviderService::getInstance()->sendSyncInfo(mainMessageId,
                                        OIC::Service::NSSyncInfo::NSSyncType::NS_SYNC_READ);
                                std::cin.clear();
                                std::cin.ignore(numeric_limits<streamsize>::max(), '\n');
                                break;
                            }
                    }
                    break;
                }

            case 7:
                {
                    std::cout <<  "RegisterTopic" << std::endl;
                    NSProviderService::getInstance()->registerTopic("OCF_TOPIC1");
                    NSProviderService::getInstance()->registerTopic("OCF_TOPIC2");
                    NSProviderService::getInstance()->registerTopic("OCF_TOPIC3");
                    NSProviderService::getInstance()->registerTopic("OCF_TOPIC4");
                    break;
                }
            case 8:
                {
                    std::cout <<  "UnregisterTopic" << std::endl;
                    NSProviderService::getInstance()->unregisterTopic("OCF_TOPIC2");
                    break;
                }
            case 9:
                {
                    std::cout <<  "SetTopic" << std::endl;
                    std::shared_ptr<OIC::Service::NSConsumer> consumer = printAvailableConsumers();
                    if (consumer != nullptr)
                    {
                        consumer->setTopic("OCF_TOPIC1");
                        consumer->setTopic("OCF_TOPIC2");
                        consumer->setTopic("OCF_TOPIC3");
                        std::cout <<  "SelectTopic completed" << std::endl;
                    }
                    break;
                }
            case 10:
                {
                    std::cout <<  "UnsetTopic" << std::endl;
                    std::shared_ptr<OIC::Service::NSConsumer> consumer = printAvailableConsumers();
                    if (consumer != nullptr)
                    {
                        consumer->unsetTopic("OCF_TOPIC1");
                        std::cout <<  "UnSelectTopic completed" << std::endl;
                    }
                    break;
                }

            case 11:
                {
                    std::cout <<  "GetConsumerTopicList" << std::endl;
                    std::shared_ptr<OIC::Service::NSConsumer> consumer = printAvailableConsumers();
                    if (consumer != nullptr)
                    {
                        auto nsTopics = consumer->getConsumerTopicList();
                        if (nsTopics != nullptr)
                        {
                            for (auto it : nsTopics->getTopicsList())
                            {

                                std::cout << it.getTopicName() << std::endl;
                                std::cout << (int) it.getState() << std::endl;
                            }
                        }
                        std::cout <<  "GetConsumerTopicList completed" << std::endl;
                    }
                    break;
                }

            case 12:
                {
                    std::cout <<  "GetRegisteredTopicList" << std::endl;
                    auto nsTopics = NSProviderService::getInstance()->getRegisteredTopicList();
                    for (auto it : nsTopics->getTopicsList())
                    {

                        std::cout << it.getTopicName() << std::endl;
                        std::cout << (int) it.getState() << std::endl;
                    }
                    break;
                }
#ifdef WITH_CLOUD
            case 13:
                {
                    std::cout << "Enable NS Provider RemoteService" << std::endl;
                    std::cout << "Input the Server Address :";
                    std::cin >> REMOTE_SERVER_ADDRESS;
                    NSProviderService::getInstance()->enableRemoteService(REMOTE_SERVER_ADDRESS);
                    break;
                }
            case 14:
                {
                    std::cout << "Disable NS Provider RemoteService" << std::endl;
                    std::cout << "Input the Server Address :";
                    NSProviderService::getInstance()->disableRemoteService(REMOTE_SERVER_ADDRESS);
                    break;
                }
#endif
            case 15:
                {
                    std::cout << "Stop the Notification Provider" << std::endl;
                    NSProviderService::getInstance()->stop();
                    break;
                }
            case 16:
                {
                    std::cout << "Exit()" << std::endl;
                    NSProviderService::getInstance()->stop();
                    isExit = true;
                    break;
                }
            default:
                {
                    std::cout << "Under Construction" << std::endl;
                    std::cin.clear();
                    std::cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    break;
                }
        }

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

    return 0;
}
<commit_msg>[IOT-2789]Fix for NS sample crash<commit_after>/******************************************************************
 *
 * Copyright 2016 Samsung Electronics 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.
 *
 ******************************************************************/

// std
#include <iostream>
#include <stdlib.h>
#include <cstdint>
#include <limits>

// ns
#include "NSCommon.h"
#include "NSProviderService.h"
#include "NSUtils.h"
#include "NSTopicsList.h"

// base
#include "logger.h"
#include "octypes.h"
#include "oic_string.h"
#include "oic_malloc.h"
#include "ocstack.h"

// external
#include "pthread.h"

#define TAG "NotiProviderWrapperExample"
using namespace std;
using namespace OIC::Service;
std::vector<std::string> discoveredConsumers;
uint64_t mainMessageId = 0;

extern char *strdup(const char *s);

bool isExit = false;

int id = 0;
std::string REMOTE_SERVER_ADDRESS;

void *OCProcessThread(void *ptr)
{
    (void) ptr;
    while (!isExit)
    {
        usleep(2000);
        if (OCProcess() != OC_STACK_OK)
        {
            std::cout << "OCStack process error" << std::endl;
            return NULL;
        }
    }

    return NULL;
}

void subscribeRequestCallback(std::shared_ptr<OIC::Service::NSConsumer> consumer)
{
    std::cout << "consumer requested to subscribe" << std::endl;

    std::cout << "Consumer Device ID: " << consumer->getConsumerId() << std::endl;
    discoveredConsumers.push_back(consumer->getConsumerId());
    consumer->acceptSubscription(true);
}

void syncCallback(OIC::Service::NSSyncInfo sync)
{
    std::cout << "SyncInfo Received " << std::endl;
    std::cout << "Sync ID : " <<  sync.getMessageId() << std::endl;
    std::cout << "Provider ID : " <<  sync.getProviderId() << std::endl;
    std::cout << "Sync State: " << (int) sync.getState() << std::endl;
}

std::shared_ptr<OIC::Service::NSConsumer> printAvailableConsumers()
{
    std::cout << "Choose the Consumer ID for operation" << std::endl;
    int pos = 1;
    unsigned int option = 0;
    for (auto it : discoveredConsumers)
    {
        std::cout << pos << ". " << it << std::endl;
        pos++;
    }
    while (!(std::cin >> option))
    {
        std::cout << "Bad value!" << std::endl;;
        std::cin.clear();
        std::cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }
    if (option > discoveredConsumers.size())
    {
        return NULL;
    }
    option--;
    std::string consumerId = discoveredConsumers[option];
    std::shared_ptr<OIC::Service::NSConsumer> consumer =
        NSProviderService::getInstance()->getConsumer(consumerId);
    return consumer;
}

int main()
{
    int num = 0;
    pthread_t processThread = 0;

    std::cout << "start Iotivity" << std::endl;

    if (OCInit(NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)
    {
        std::cout << "OCStack init error" << std::endl;
        return 0;
    }

    pthread_create(&processThread, NULL, OCProcessThread, NULL);

    while (!isExit)
    {
        std::cout << "1. Start the Notification Provider(Accepter: Provider)" << std::endl;
        std::cout << "2. Start the Notification Provider(Accepter: Consumer)" << std::endl;
        std::cout << "3. Allow Subscription" << std::endl;
        std::cout << "4. Deny Subscription" << std::endl;
        std::cout << "5. SendMessage " << std::endl;
        std::cout << "6. SendSyncInfo" << std::endl;

        std::cout << "7. RegisterTopic" << std::endl;
        std::cout << "8. UnregisterTopic" << std::endl;
        std::cout << "9. SetTopic" << std::endl;
        std::cout << "10. UnsetTopic" << std::endl;
        std::cout << "11. GetConsumerTopicList" << std::endl;
        std::cout << "12. GetRegisteredTopicList" << std::endl;
#ifdef WITH_CLOUD
        std::cout << "13. Enable NS Provider RemoteService" << std::endl;
        std::cout << "14. Disable NS Provider RemoteService" << std::endl;
#endif
        std::cout << "15. Stop the Notification Provider" << std::endl;
        std::cout << "16. Exit()" << std::endl;

        std::cout << "input : ";

        std::cin >> num;

        switch (num)
        {
            case 1:
                {
                    std::cout << "Start (Accepter: Provider)" << std::endl;
                    NSProviderService::ProviderConfig cfg;
                    cfg.m_subscribeRequestCb = subscribeRequestCallback;
                    cfg.m_syncInfoCb = syncCallback;
                    cfg.subControllability = true;

                    NSProviderService::getInstance()->start(cfg);
                    break;
                }
            case 2:
                {
                    std::cout << "Start (Accepter: Consumer)" << std::endl;
                    NSProviderService::ProviderConfig cfg;
                    cfg.m_subscribeRequestCb = subscribeRequestCallback;
                    cfg.m_syncInfoCb = syncCallback;
                    cfg.subControllability = false;

                    NSProviderService::getInstance()->start(cfg);
                    break;
                }
            case 3:
                {
                    std::cout << "Allow Subscription" << std::endl;
                    std::shared_ptr<OIC::Service::NSConsumer> consumer = printAvailableConsumers();
                    if (consumer != nullptr)
                    {
                        std::cout << "ALLOW" << std::endl;
                        consumer->acceptSubscription(true);
                    }
                    break;
                }
            case 4:
                {
                    std::cout << "Deny Subscription" << std::endl;
                    std::shared_ptr<OIC::Service::NSConsumer>consumer = printAvailableConsumers();
                    if (consumer != nullptr)
                    {
                        std::cout << "DENY" << std::endl;
                        consumer->acceptSubscription(false);
                    }
                    break;
                }
            case 5:
                {
                    std::cout << "------------------------------------" << std::endl;
                    std::cout << "SendMessage" << std::endl;
                    std::cout << "------------------------------------" << std::endl;

                    std::string dummy;
                    std::string title;
                    std::string body;
                    std::string topic;

                    std::cout << "id : " << ++id << std::endl;
                    std::cout << "title : ";

                    std::getline(std::cin, dummy);
                    std::getline(std::cin, title);

                    std::cout << "body : ";
                    std::getline(std::cin, body);

                    std::cout << "topic : ";
                    std::getline(std::cin, topic);

                    std::cout << "app - mTitle : " << title << std::endl;
                    std::cout << "app - mContentText : " << body << std::endl;
                    std::cout << "app - mTopic : " << topic << std::endl;

                    OIC::Service::NSMessage msg = NSProviderService::getInstance()->createMessage();

                    msg.setType(OIC::Service::NSMessage::NSMessageType::NS_MESSAGE_INFO);
                    msg.setTitle(title.c_str());
                    msg.setContentText(body.c_str());
                    msg.setSourceName("OCF");
                    msg.setTopic(topic);
                    msg.setTTL(40);
                    msg.setTime("12:30");
                    OIC::Service::NSMediaContents *mediaContents =
                        new OIC::Service::NSMediaContents("iconImage");
                    msg.setMediaContents(mediaContents);

                    OC::OCRepresentation rep;
                    rep.setValue("Key1", "Value1");
                    rep.setValue("Key2", "Value2");
                    msg.setExtraInfo(rep);

                    mainMessageId = msg.getMessageId();
                    std::cout << "ProviderID for Message : " << msg.getProviderId() << std::endl;
                    std::cout << "MessageID for Message : " << msg.getMessageId() << std::endl;

                    NSProviderService::getInstance()->sendMessage(msg);
                    break;
                }
            case 6:
                {
                    std::cout << "------------------------------------" << std::endl;
                    std::cout <<  "SendSyncInfo" << std::endl;
                    std::cout << "------------------------------------" << std::endl;
                    if (!mainMessageId)
                    {
                        std::cout <<  "Message ID is empty" << std::endl;
                        break;
                    }
                    std::cout << "1. Send Read Sync" << std::endl;
                    std::cout << "2. Send Delete Sync" << std::endl;
                    int syn = 0;
                    while (!(std::cin >> syn))
                    {
                        std::cout << "Bad value!" << std::endl;;
                        std::cin.clear();
                        std::cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    }
                    switch (syn)
                    {
                        case 1:
                            {
                                std::cout << "Sending Read Sync" << std::endl;
                                NSProviderService::getInstance()->sendSyncInfo(mainMessageId,
                                        OIC::Service::NSSyncInfo::NSSyncType::NS_SYNC_READ);
                            }
                            break;
                        case 2:
                            {
                                std::cout << "Sending Delete Sync" << std::endl;
                                NSProviderService::getInstance()->sendSyncInfo(mainMessageId,
                                        OIC::Service::NSSyncInfo::NSSyncType::NS_SYNC_DELETED);
                            }
                            break;
                        default:
                            {
                                cout << "Invalid Input!. sending default Read Sync";
                                NSProviderService::getInstance()->sendSyncInfo(mainMessageId,
                                        OIC::Service::NSSyncInfo::NSSyncType::NS_SYNC_READ);
                                std::cin.clear();
                                std::cin.ignore(numeric_limits<streamsize>::max(), '\n');
                                break;
                            }
                    }
                    break;
                }

            case 7:
                {
                    std::cout <<  "RegisterTopic" << std::endl;
                    NSProviderService::getInstance()->registerTopic("OCF_TOPIC1");
                    NSProviderService::getInstance()->registerTopic("OCF_TOPIC2");
                    NSProviderService::getInstance()->registerTopic("OCF_TOPIC3");
                    NSProviderService::getInstance()->registerTopic("OCF_TOPIC4");
                    break;
                }
            case 8:
                {
                    std::cout <<  "UnregisterTopic" << std::endl;
                    NSProviderService::getInstance()->unregisterTopic("OCF_TOPIC2");
                    break;
                }
            case 9:
                {
                    std::cout <<  "SetTopic" << std::endl;
                    std::shared_ptr<OIC::Service::NSConsumer> consumer = printAvailableConsumers();
                    if (consumer != nullptr)
                    {
                        consumer->setTopic("OCF_TOPIC1");
                        consumer->setTopic("OCF_TOPIC2");
                        consumer->setTopic("OCF_TOPIC3");
                        std::cout <<  "SelectTopic completed" << std::endl;
                    }
                    break;
                }
            case 10:
                {
                    std::cout <<  "UnsetTopic" << std::endl;
                    std::shared_ptr<OIC::Service::NSConsumer> consumer = printAvailableConsumers();
                    if (consumer != nullptr)
                    {
                        consumer->unsetTopic("OCF_TOPIC1");
                        std::cout <<  "UnSelectTopic completed" << std::endl;
                    }
                    break;
                }

            case 11:
                {
                    std::cout <<  "GetConsumerTopicList" << std::endl;
                    std::shared_ptr<OIC::Service::NSConsumer> consumer = printAvailableConsumers();
                    if (consumer != nullptr)
                    {
                        auto nsTopics = consumer->getConsumerTopicList();
                        if (nsTopics != nullptr)
                        {
                            for (auto it : nsTopics->getTopicsList())
                            {

                                std::cout << it.getTopicName() << std::endl;
                                std::cout << (int) it.getState() << std::endl;
                            }
                        }
                        std::cout <<  "GetConsumerTopicList completed" << std::endl;
                    }
                    break;
                }

            case 12:
                {
                    std::cout <<  "GetRegisteredTopicList" << std::endl;
                    auto nsTopics = NSProviderService::getInstance()->getRegisteredTopicList();
                    for (auto it : nsTopics->getTopicsList())
                    {

                        std::cout << it.getTopicName() << std::endl;
                        std::cout << (int) it.getState() << std::endl;
                    }
                    break;
                }
#ifdef WITH_CLOUD
            case 13:
                {
                    std::cout << "Enable NS Provider RemoteService" << std::endl;
                    std::cout << "Input the Server Address :";
                    std::cin >> REMOTE_SERVER_ADDRESS;
                    NSProviderService::getInstance()->enableRemoteService(REMOTE_SERVER_ADDRESS);
                    break;
                }
            case 14:
                {
                    std::cout << "Disable NS Provider RemoteService" << std::endl;
                    std::cout << "Input the Server Address :";
                    NSProviderService::getInstance()->disableRemoteService(REMOTE_SERVER_ADDRESS);
                    break;
                }
#endif
            case 15:
                {
                    std::cout << "Stop the Notification Provider" << std::endl;
                    NSProviderService::getInstance()->stop();
                    break;
                }
            case 16:
                {
                    std::cout << "Exit()" << std::endl;
                    NSProviderService::getInstance()->stop();
                    isExit = true;
                    break;
                }
            default:
                {
                    std::cout << "Under Construction" << std::endl;
                    std::cin.clear();
                    std::cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    break;
                }
        }

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

    return 0;
}
<|endoftext|>


<commit_before>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/platform/glfw/key_event_handler.h"

#include <iostream>

#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/json_message_codec.h"

static constexpr char kChannelName[] = "flutter/keyevent";

static constexpr char kKeyCodeKey[] = "keyCode";
static constexpr char kKeyMapKey[] = "keymap";
static constexpr char kTypeKey[] = "type";

static constexpr char kAndroidKeyMap[] = "android";
static constexpr char kKeyUp[] = "keyup";
static constexpr char kKeyDown[] = "keydown";

namespace flutter {

KeyEventHandler::KeyEventHandler(flutter::BinaryMessenger* messenger)
    : channel_(
          std::make_unique<flutter::BasicMessageChannel<rapidjson::Document>>(
              messenger,
              kChannelName,
              &flutter::JsonMessageCodec::GetInstance())) {}

KeyEventHandler::~KeyEventHandler() = default;

void KeyEventHandler::CharHook(GLFWwindow* window, unsigned int code_point) {}

void KeyEventHandler::KeyboardHook(GLFWwindow* window,
                                   int key,
                                   int scancode,
                                   int action,
                                   int mods) {
  // TODO: Translate to a cross-platform key code system rather than passing
  // the native key code.
  rapidjson::Document event(rapidjson::kObjectType);
  auto& allocator = event.GetAllocator();
  event.AddMember(kKeyCodeKey, key, allocator);
  event.AddMember(kKeyMapKey, kAndroidKeyMap, allocator);

  switch (action) {
    case GLFW_PRESS:
      event.AddMember(kTypeKey, kKeyDown, allocator);
      break;
    case GLFW_RELEASE:
      event.AddMember(kTypeKey, kKeyUp, allocator);
      break;
    default:
      std::cerr << "Unknown key event action: " << action << std::endl;
      return;
  }
  channel_->Send(event);
}

}  // namespace flutter<commit_msg>[glfw] Send the glfw key data to the framework. (#9386)<commit_after>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/platform/glfw/key_event_handler.h"

#include <iostream>

#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/json_message_codec.h"

static constexpr char kChannelName[] = "flutter/keyevent";

static constexpr char kKeyCodeKey[] = "keyCode";
static constexpr char kKeyMapKey[] = "keymap";
static constexpr char kScanCodeKey[] = "scanCode";
static constexpr char kModifiersKey[] = "modifiers";
static constexpr char kTypeKey[] = "type";
static constexpr char kToolkitKey[] = "toolkit";
static constexpr char kUnicodeScalarValues[] = "unicodeScalarValues";

static constexpr char kLinuxKeyMap[] = "linux";
static constexpr char kGLFWKey[] = "glfw";

static constexpr char kKeyUp[] = "keyup";
static constexpr char kKeyDown[] = "keydown";

// Masks used for UTF-8 to UTF-32 conversion.
static constexpr int kTwoByteMask = 0xC0;
static constexpr int kThreeByteMask = 0xE0;
static constexpr int kFourByteMask = 0xF0;

namespace flutter {

namespace {

// Information about the UTF-8 encoded code point.
struct UTF8CodePointInfo {
  // The bit-mask that determines the length of the code point.
  int first_byte_mask;
  // The number of bytes of the code point.
  size_t length;
};

// Creates a [UTF8CodePointInfo] from a given byte. [first_byte] must be the
// first byte in the code point.
UTF8CodePointInfo GetUTF8CodePointInfo(int first_byte) {
  UTF8CodePointInfo byte_info;

  // The order matters. Otherwise, it is possible that comparing against i.e.
  // kThreeByteMask and kFourByteMask could be both true.
  if ((first_byte & kFourByteMask) == kFourByteMask) {
    byte_info.first_byte_mask = 0x07;
    byte_info.length = 4;
  } else if ((first_byte & kThreeByteMask) == kThreeByteMask) {
    byte_info.first_byte_mask = 0x0F;
    byte_info.length = 3;
  } else if ((first_byte & kTwoByteMask) == kTwoByteMask) {
    byte_info.first_byte_mask = 0x1F;
    byte_info.length = 2;
  } else {
    byte_info.first_byte_mask = 0xFF;
    byte_info.length = 1;
  }
  return byte_info;
}

// Queries GLFW for the printable key name given a [key] and [scan_code] and
// converts it to UTF-32. The Flutter framework accepts only one code point,
// therefore, only the first code point will be used. There is unlikely to be
// more than one, but there is no guarantee that it won't happen.
bool GetUTF32CodePointFromGLFWKey(int key,
                                  int scan_code,
                                  uint32_t* code_point) {
  // Get the name of the printable key, encoded as UTF-8.
  // There's a known issue with glfwGetKeyName, where users with multiple
  // layouts configured on their machines, will not always return the right
  // value. See: https://github.com/glfw/glfw/issues/1462
  const char* utf8 = glfwGetKeyName(key, scan_code);
  if (utf8 == nullptr) {
    return false;
  }
  // The first byte determines the length of the whole code point.
  const auto byte_info = GetUTF8CodePointInfo(utf8[0]);
  // Tracks how many bits the current byte should shift to the left.
  int shift = byte_info.length - 1;

  const int complement_mask = 0x3F;
  uint32_t result = 0;

  size_t current_byte_index = 0;
  while (current_byte_index < byte_info.length) {
    const int current_byte = utf8[current_byte_index];
    const int mask =
        current_byte_index == 0 ? byte_info.first_byte_mask : complement_mask;
    current_byte_index++;
    const int bits_to_shift = 6 * shift--;
    result += (current_byte & mask) << bits_to_shift;
  }
  *code_point = result;
  return true;
}
}  // namespace

KeyEventHandler::KeyEventHandler(flutter::BinaryMessenger* messenger)
    : channel_(
          std::make_unique<flutter::BasicMessageChannel<rapidjson::Document>>(
              messenger,
              kChannelName,
              &flutter::JsonMessageCodec::GetInstance())) {}

KeyEventHandler::~KeyEventHandler() = default;

void KeyEventHandler::CharHook(GLFWwindow* window, unsigned int code_point) {}

void KeyEventHandler::KeyboardHook(GLFWwindow* window,
                                   int key,
                                   int scancode,
                                   int action,
                                   int mods) {
  // TODO: Translate to a cross-platform key code system rather than passing
  // the native key code.
  rapidjson::Document event(rapidjson::kObjectType);
  auto& allocator = event.GetAllocator();
  event.AddMember(kKeyCodeKey, key, allocator);
  event.AddMember(kKeyMapKey, kLinuxKeyMap, allocator);
  event.AddMember(kScanCodeKey, scancode, allocator);
  event.AddMember(kModifiersKey, mods, allocator);
  event.AddMember(kToolkitKey, kGLFWKey, allocator);

  uint32_t unicodeInt;
  bool result = GetUTF32CodePointFromGLFWKey(key, scancode, &unicodeInt);
  if (result) {
    event.AddMember(kUnicodeScalarValues, unicodeInt, allocator);
  }

  switch (action) {
    case GLFW_PRESS:
    case GLFW_REPEAT:
      event.AddMember(kTypeKey, kKeyDown, allocator);
      break;
    case GLFW_RELEASE:
      event.AddMember(kTypeKey, kKeyUp, allocator);
      break;
    default:
      std::cerr << "Unknown key event action: " << action << std::endl;
      return;
  }
  channel_->Send(event);
}

}  // namespace flutter<|endoftext|>


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

#include "FindReferences.hpp"

#include <boost/foreach.hpp>

#include <boost/algorithm/string/split.hpp>

#include <core/FileSerializer.hpp>
#include <core/libclang/LibClang.hpp>

#include <core/system/ProcessArgs.hpp>

#include <session/SessionModuleContext.hpp>

#include "RSourceIndex.hpp"
#include "RCompilationDatabase.hpp"

using namespace rstudio::core;
using namespace rstudio::core::libclang;

namespace rstudio {
namespace session {
namespace modules {
namespace clang {

namespace {

struct FindReferencesData
{
   FindReferencesData(CXTranslationUnit tu, const std::string& USR)
      : tu(tu), USR(USR)
   {
   }
   CXTranslationUnit tu;
   std::string USR;
   std::string spelling;
   std::vector<FileRange> references;
};

CXChildVisitResult findReferencesVisitor(CXCursor cxCursor,
                                         CXCursor,
                                         CXClientData data)
{
   using namespace rstudio::core::libclang;

   // get pointer to data struct
   FindReferencesData* pData = (FindReferencesData*)data;

   // reference to the cursor (ensure valid)
   Cursor cursor(cxCursor);
   if (!cursor.isValid())
      return CXChildVisit_Continue;

   // continue with sibling if it's not from the main file
   SourceLocation location = cursor.getSourceLocation();
   if (!location.isFromMainFile())
      return CXChildVisit_Continue;

   // get referenced cursor
   Cursor referencedCursor = cursor.getReferenced();
   if (referencedCursor.isValid() && referencedCursor.isDeclaration())
   {
      // check for matching USR
      if (referencedCursor.getUSR() == pData->USR)
      {
         // tokenize to extract identifer location for cursors that
         // represent larger source constructs
         FileRange foundRange;
         libclang::Tokens tokens(pData->tu, cursor.getExtent());
         std::vector<unsigned> indexes;

         // for constructors & destructors we search backwards so that the
         // match is for the constructor identifier rather than the class
         // identifer
         unsigned numTokens = tokens.numTokens();
         if (referencedCursor.getKind() == CXCursor_Constructor ||
             referencedCursor.getKind() == CXCursor_Destructor)
         {
            for (unsigned i = 0; i < numTokens; i++)
               indexes.push_back(numTokens - i - 1);
         }
         else
         {
            for (unsigned i = 0; i < numTokens; i++)
               indexes.push_back(i);
         }

         // cycle through the tokens
         BOOST_FOREACH(unsigned i, indexes)
         {
            Token token = tokens.getToken(i);
            if (token.kind() == CXToken_Identifier &&
                token.spelling() == cursor.spelling())
            {
               foundRange = token.extent().getFileRange();
               break;
            }
         }

         // if we didn't find an identifier that matches use the
         // original match (i.e. important for constructors where
         // the 'spelling' of the invocation is the name of the
         // variable declared)
         if (foundRange.empty())
            foundRange = cursor.getExtent().getFileRange();

         // record the range if it's not a duplicate of the previous range
         if (pData->references.empty() ||
             (pData->references.back() != foundRange))
         {
            pData->references.push_back(foundRange);

            // record spelling if necessary
            if (pData->spelling.empty())
               pData->spelling = referencedCursor.spelling();
         }
      }
   }

   // recurse into namespaces, classes, etc.
   return CXChildVisit_Recurse;
}

class SourceMarkerGenerator
{
public:
   std::vector<module_context::SourceMarker> markersForCursorLocations(
              const std::vector<core::libclang::FileRange>& locations)
   {
      using namespace module_context;
      std::vector<SourceMarker> markers;

      BOOST_FOREACH(const libclang::FileRange& loc, locations)
      {
         FileLocation startLoc = loc.start;

         // get file contents and use it to create the message
         std::size_t line = startLoc.line - 1;
         std::string message;
         const std::vector<std::string>& lines = fileContents(
                                 startLoc.filePath.absolutePath());
         if (line < lines.size())
            message = htmlMessage(loc, lines[line]);

         // create marker
         SourceMarker marker(SourceMarker::Usage,
                             startLoc.filePath,
                             startLoc.line,
                             startLoc.column,
                             core::html_utils::HTML(message, true),
                             true);

         // add it to the list
         markers.push_back(marker);
      }

      return markers;
   }

private:

   static std::string htmlMessage(const libclang::FileRange& loc,
                                  const std::string& message)
   {
      FileLocation startLoc = loc.start;
      FileLocation endLoc = loc.end;

      unsigned extent = 0;
      if (startLoc.line == endLoc.line)
         extent = endLoc.column - startLoc.column;

      // attempt to highlight the location
      using namespace string_utils;
      unsigned col = startLoc.column - 1;
      if ((col + extent) < message.length())
      {
         if (extent == 0)
         {
            return "" + htmlEscape(message) + "";
         }
         else
         {
            std::ostringstream ostr;
            ostr << htmlEscape(message.substr(0, col));
            ostr << "";
            ostr << htmlEscape(message.substr(col, extent));
            ostr << "";
            ostr << htmlEscape(message.substr(col + extent));
            return ostr.str();
         }
      }
      else
      {
         return string_utils::htmlEscape(message);
      }
   }

   typedef std::map<std::string,std::vector<std::string> > SourceFileContentsMap;

   const std::vector<std::string>& fileContents(const std::string& filename)
   {
      // check cache
      SourceFileContentsMap::const_iterator it =
                                       sourceFileContents_.find(filename);
      if (it == sourceFileContents_.end())
      {
         // check unsaved files
         UnsavedFiles& unsavedFiles = rSourceIndex().unsavedFiles();
         unsigned numFiles = unsavedFiles.numUnsavedFiles();
         for (unsigned i = 0; i<numFiles; ++i)
         {
            CXUnsavedFile unsavedFile = unsavedFiles.unsavedFilesArray()[i];
            if (unsavedFile.Filename != NULL &&
                std::string(unsavedFile.Filename) == filename &&
                unsavedFile.Contents != NULL)
            {
               std::string contents(unsavedFile.Contents, unsavedFile.Length);
               std::vector<std::string> lines;
               boost::algorithm::split(lines,
                                       contents,
                                       boost::is_any_of("\n"));

               sourceFileContents_.insert(std::make_pair(filename, lines));
               it = sourceFileContents_.find(filename);
               break;
            }
         }

         // if we didn't get one then read it from disk
         if (it == sourceFileContents_.end())
         {
            std::vector<std::string> lines;
            Error error = readStringVectorFromFile(FilePath(filename),
                                                   &lines,
                                                   false);
            if (error)
               LOG_ERROR(error);

            // insert anyway to ensure it->second below works
            sourceFileContents_.insert(std::make_pair(filename, lines));
            it = sourceFileContents_.find(filename);
         }
      }

      // return reference to contents
      return it->second;
   }

private:
   SourceFileContentsMap sourceFileContents_;
};

void findReferences(std::string USR,
                    CXTranslationUnit tu,
                    std::string* pSpelling,
                    std::vector<core::libclang::FileRange>* pRefs)
{
   FindReferencesData findReferencesData(tu, USR);
   libclang::clang().visitChildren(
               libclang::clang().getTranslationUnitCursor(tu),
               findReferencesVisitor,
               (CXClientData)&findReferencesData);

   // copy the locations to the out parameter
   *pSpelling = findReferencesData.spelling;
   std::copy(findReferencesData.references.begin(),
             findReferencesData.references.end(),
             std::back_inserter(*pRefs));
}

} // anonymous namespace

core::Error findReferences(const core::libclang::FileLocation& location,
                           std::string* pSpelling,
                           std::vector<core::libclang::FileRange>* pRefs)
{
   Cursor cursor = rSourceIndex().referencedCursorForFileLocation(location);
   if (!cursor.isValid() || !cursor.isDeclaration())
      return Success();

   // get it's USR (bail if it doesn't have one)
   std::string USR = cursor.getUSR();
   if (USR.empty())
      return Success();

   // determine what translation units to look in -- if this is a package
   // then we look throughout all the source code in the package.
   if (rCompilationDatabase().hasTranslationUnit(
                                         location.filePath.absolutePath()))
   {
      // get all translation units to search
      std::vector<std::string> files = rCompilationDatabase()
                                                .translationUnits();

      // get translation units we've already indexed
      std::map<std::string,TranslationUnit> indexedUnits =
                           rSourceIndex().getIndexedTranslationUnits();

      BOOST_FOREACH(const std::string& filename, files)
      {
         // first look in already indexed translation units
         // (this will pickup unsaved files)
         std::map<std::string,TranslationUnit>::iterator it =
                                                   indexedUnits.find(filename);
         if (it != indexedUnits.end())
         {
            findReferences(USR,
                           it->second.getCXTranslationUnit(),
                           pSpelling,
                           pRefs);
         }
         else
         {
            // get the compilation arguments for this file and use them to
            // create a temporary translation unit to search
            std::vector<std::string> compileArgs =
               rCompilationDatabase().compileArgsForTranslationUnit(filename);

            if (compileArgs.empty())
               continue;

            // create temporary index
            CXIndex index = libclang::clang().createIndex(
                              1 /* Exclude PCH */,
                              (rSourceIndex().verbose() > 0) ? 1 : 0);

            // get args in form clang expects
            core::system::ProcessArgs argsArray(compileArgs);

            // parse the translation unit
            CXTranslationUnit tu = libclang::clang().parseTranslationUnit(
                                  index,
                                  filename.c_str(),
                                  argsArray.args(),
                                  argsArray.argCount(),
                                  NULL, 0, // no unsaved files
                                  CXTranslationUnit_None |
                                  CXTranslationUnit_Incomplete);

            // find references
            findReferences(USR, tu, pSpelling, pRefs);

            // dispose translation unit and index
            libclang::clang().disposeTranslationUnit(tu);
            libclang::clang().disposeIndex(index);
         }
      }
   }
   // not a package, just search locally
   else
   {
      TranslationUnit tu = rSourceIndex().getTranslationUnit(
                                             location.filePath.absolutePath(),
                                             true);
      if (!tu.empty())
         findReferences(USR, tu.getCXTranslationUnit(), pSpelling, pRefs);
   }

   return Success();

}

Error findUsages(const json::JsonRpcRequest& request,
                       json::JsonRpcResponse* pResponse)
{
   // get params
   std::string docPath;
   int line, column;
   Error error = json::readParams(request.params,
                                  &docPath,
                                  &line,
                                  &column);
   if (error)
      return error;

   // resolve the docPath if it's aliased
   FilePath filePath = module_context::resolveAliasedPath(docPath);

   // get the declaration cursor for this file location
   core::libclang::FileLocation location(filePath, line, column);

   // find the references
   std::string spelling;
   std::vector<core::libclang::FileRange> usageLocations;
   error = findReferences(location, &spelling, &usageLocations);
   if (error)
      return error;

   // produce source markers from cursor locations
   using namespace module_context;
   std::vector<SourceMarker> markers = SourceMarkerGenerator()
                                 .markersForCursorLocations(usageLocations);

   if (markers.size() > 0)
   {
      SourceMarkerSet markerSet("C++ Find Usages: " + spelling, markers);
      showSourceMarkers(markerSet, MarkerAutoSelectNone);
   }

   return Success();
}

} // namespace clang
} // namespace modules
} // namesapce session
} // namespace rstudio

<commit_msg>improved USR comparison for function declarations in find usages<commit_after>/*
 * FindReferences.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "FindReferences.hpp"

#include <boost/foreach.hpp>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>

#include <core/FileSerializer.hpp>
#include <core/libclang/LibClang.hpp>

#include <core/system/ProcessArgs.hpp>

#include <session/SessionModuleContext.hpp>

#include "RSourceIndex.hpp"
#include "RCompilationDatabase.hpp"

using namespace rstudio::core;
using namespace rstudio::core::libclang;

namespace rstudio {
namespace session {
namespace modules {
namespace clang {

namespace {

struct FindReferencesData
{
   FindReferencesData(CXTranslationUnit tu, const std::string& USR)
      : tu(tu), USR(USR)
   {
   }
   CXTranslationUnit tu;
   std::string USR;
   std::string spelling;
   std::vector<FileRange> references;
};

// if the USR's differ only by an ending # consider them equal
// we do this because references to function declarations seem to
// accue an extra # within their USRs
bool equalUSR(const std::string& USR1, const std::string& USR2)
{
   using namespace boost::algorithm;
   bool endHashUSR1 = ends_with(USR1, "#");
   bool endHashUSR2 = ends_with(USR2, "#");
   if ((endHashUSR1 && endHashUSR2) || (!endHashUSR1 && !endHashUSR2))
   {
      return USR1 == USR2;
   }
   else if (endHashUSR1)
   {
      return USR1.substr(0, USR1.length() - 1) == USR2;
   }
   else
   {
      return USR2.substr(0, USR2.length() - 1) == USR1;
   }
}

CXChildVisitResult findReferencesVisitor(CXCursor cxCursor,
                                         CXCursor,
                                         CXClientData data)
{
   using namespace rstudio::core::libclang;

   // get pointer to data struct
   FindReferencesData* pData = (FindReferencesData*)data;

   // reference to the cursor (ensure valid)
   Cursor cursor(cxCursor);
   if (!cursor.isValid())
      return CXChildVisit_Continue;

   // continue with sibling if it's not from the main file
   SourceLocation location = cursor.getSourceLocation();
   if (!location.isFromMainFile())
      return CXChildVisit_Continue;

   // get referenced cursor
   Cursor referencedCursor = cursor.getReferenced();
   if (referencedCursor.isValid() && referencedCursor.isDeclaration())
   {
      // check for matching USR
      if (equalUSR(referencedCursor.getUSR(), pData->USR))
      {
         // tokenize to extract identifer location for cursors that
         // represent larger source constructs
         FileRange foundRange;
         libclang::Tokens tokens(pData->tu, cursor.getExtent());
         std::vector<unsigned> indexes;

         // for constructors & destructors we search backwards so that the
         // match is for the constructor identifier rather than the class
         // identifer
         unsigned numTokens = tokens.numTokens();
         if (referencedCursor.getKind() == CXCursor_Constructor ||
             referencedCursor.getKind() == CXCursor_Destructor)
         {
            for (unsigned i = 0; i < numTokens; i++)
               indexes.push_back(numTokens - i - 1);
         }
         else
         {
            for (unsigned i = 0; i < numTokens; i++)
               indexes.push_back(i);
         }

         // cycle through the tokens
         BOOST_FOREACH(unsigned i, indexes)
         {
            Token token = tokens.getToken(i);
            if (token.kind() == CXToken_Identifier &&
                token.spelling() == cursor.spelling())
            {
               foundRange = token.extent().getFileRange();
               break;
            }
         }

         // if we didn't find an identifier that matches use the
         // original match (i.e. important for constructors where
         // the 'spelling' of the invocation is the name of the
         // variable declared)
         if (foundRange.empty())
            foundRange = cursor.getExtent().getFileRange();

         // record the range if it's not a duplicate of the previous range
         if (pData->references.empty() ||
             (pData->references.back() != foundRange))
         {
            pData->references.push_back(foundRange);

            // record spelling if necessary
            if (pData->spelling.empty())
               pData->spelling = referencedCursor.spelling();
         }
      }
   }

   // recurse into namespaces, classes, etc.
   return CXChildVisit_Recurse;
}

class SourceMarkerGenerator
{
public:
   std::vector<module_context::SourceMarker> markersForCursorLocations(
              const std::vector<core::libclang::FileRange>& locations)
   {
      using namespace module_context;
      std::vector<SourceMarker> markers;

      BOOST_FOREACH(const libclang::FileRange& loc, locations)
      {
         FileLocation startLoc = loc.start;

         // get file contents and use it to create the message
         std::size_t line = startLoc.line - 1;
         std::string message;
         const std::vector<std::string>& lines = fileContents(
                                 startLoc.filePath.absolutePath());
         if (line < lines.size())
            message = htmlMessage(loc, lines[line]);

         // create marker
         SourceMarker marker(SourceMarker::Usage,
                             startLoc.filePath,
                             startLoc.line,
                             startLoc.column,
                             core::html_utils::HTML(message, true),
                             true);

         // add it to the list
         markers.push_back(marker);
      }

      return markers;
   }

private:

   static std::string htmlMessage(const libclang::FileRange& loc,
                                  const std::string& message)
   {
      FileLocation startLoc = loc.start;
      FileLocation endLoc = loc.end;

      unsigned extent = 0;
      if (startLoc.line == endLoc.line)
         extent = endLoc.column - startLoc.column;

      // attempt to highlight the location
      using namespace string_utils;
      unsigned col = startLoc.column - 1;
      if ((col + extent) < message.length())
      {
         if (extent == 0)
         {
            return "" + htmlEscape(message) + "";
         }
         else
         {
            std::ostringstream ostr;
            ostr << htmlEscape(message.substr(0, col));
            ostr << "";
            ostr << htmlEscape(message.substr(col, extent));
            ostr << "";
            ostr << htmlEscape(message.substr(col + extent));
            return ostr.str();
         }
      }
      else
      {
         return string_utils::htmlEscape(message);
      }
   }

   typedef std::map<std::string,std::vector<std::string> > SourceFileContentsMap;

   const std::vector<std::string>& fileContents(const std::string& filename)
   {
      // check cache
      SourceFileContentsMap::const_iterator it =
                                       sourceFileContents_.find(filename);
      if (it == sourceFileContents_.end())
      {
         // check unsaved files
         UnsavedFiles& unsavedFiles = rSourceIndex().unsavedFiles();
         unsigned numFiles = unsavedFiles.numUnsavedFiles();
         for (unsigned i = 0; i<numFiles; ++i)
         {
            CXUnsavedFile unsavedFile = unsavedFiles.unsavedFilesArray()[i];
            if (unsavedFile.Filename != NULL &&
                std::string(unsavedFile.Filename) == filename &&
                unsavedFile.Contents != NULL)
            {
               std::string contents(unsavedFile.Contents, unsavedFile.Length);
               std::vector<std::string> lines;
               boost::algorithm::split(lines,
                                       contents,
                                       boost::is_any_of("\n"));

               sourceFileContents_.insert(std::make_pair(filename, lines));
               it = sourceFileContents_.find(filename);
               break;
            }
         }

         // if we didn't get one then read it from disk
         if (it == sourceFileContents_.end())
         {
            std::vector<std::string> lines;
            Error error = readStringVectorFromFile(FilePath(filename),
                                                   &lines,
                                                   false);
            if (error)
               LOG_ERROR(error);

            // insert anyway to ensure it->second below works
            sourceFileContents_.insert(std::make_pair(filename, lines));
            it = sourceFileContents_.find(filename);
         }
      }

      // return reference to contents
      return it->second;
   }

private:
   SourceFileContentsMap sourceFileContents_;
};

void findReferences(std::string USR,
                    CXTranslationUnit tu,
                    std::string* pSpelling,
                    std::vector<core::libclang::FileRange>* pRefs)
{
   FindReferencesData findReferencesData(tu, USR);
   libclang::clang().visitChildren(
               libclang::clang().getTranslationUnitCursor(tu),
               findReferencesVisitor,
               (CXClientData)&findReferencesData);

   // copy the locations to the out parameter
   *pSpelling = findReferencesData.spelling;
   std::copy(findReferencesData.references.begin(),
             findReferencesData.references.end(),
             std::back_inserter(*pRefs));
}

} // anonymous namespace

core::Error findReferences(const core::libclang::FileLocation& location,
                           std::string* pSpelling,
                           std::vector<core::libclang::FileRange>* pRefs)
{
   Cursor cursor = rSourceIndex().referencedCursorForFileLocation(location);
   if (!cursor.isValid() || !cursor.isDeclaration())
      return Success();

   // get it's USR (bail if it doesn't have one)
   std::string USR = cursor.getUSR();
   if (USR.empty())
      return Success();

   // determine what translation units to look in -- if this is a package
   // then we look throughout all the source code in the package.
   if (rCompilationDatabase().hasTranslationUnit(
                                         location.filePath.absolutePath()))
   {
      // get all translation units to search
      std::vector<std::string> files = rCompilationDatabase()
                                                .translationUnits();

      // get translation units we've already indexed
      std::map<std::string,TranslationUnit> indexedUnits =
                           rSourceIndex().getIndexedTranslationUnits();

      BOOST_FOREACH(const std::string& filename, files)
      {
         // first look in already indexed translation units
         // (this will pickup unsaved files)
         std::map<std::string,TranslationUnit>::iterator it =
                                                   indexedUnits.find(filename);
         if (it != indexedUnits.end())
         {
            findReferences(USR,
                           it->second.getCXTranslationUnit(),
                           pSpelling,
                           pRefs);
         }
         else
         {
            // get the compilation arguments for this file and use them to
            // create a temporary translation unit to search
            std::vector<std::string> compileArgs =
               rCompilationDatabase().compileArgsForTranslationUnit(filename);

            if (compileArgs.empty())
               continue;

            // create temporary index
            CXIndex index = libclang::clang().createIndex(
                              1 /* Exclude PCH */,
                              (rSourceIndex().verbose() > 0) ? 1 : 0);

            // get args in form clang expects
            core::system::ProcessArgs argsArray(compileArgs);

            // parse the translation unit
            CXTranslationUnit tu = libclang::clang().parseTranslationUnit(
                                  index,
                                  filename.c_str(),
                                  argsArray.args(),
                                  argsArray.argCount(),
                                  NULL, 0, // no unsaved files
                                  CXTranslationUnit_None |
                                  CXTranslationUnit_Incomplete);

            // find references
            findReferences(USR, tu, pSpelling, pRefs);

            // dispose translation unit and index
            libclang::clang().disposeTranslationUnit(tu);
            libclang::clang().disposeIndex(index);
         }
      }
   }
   // not a package, just search locally
   else
   {
      TranslationUnit tu = rSourceIndex().getTranslationUnit(
                                             location.filePath.absolutePath(),
                                             true);
      if (!tu.empty())
         findReferences(USR, tu.getCXTranslationUnit(), pSpelling, pRefs);
   }

   return Success();

}

Error findUsages(const json::JsonRpcRequest& request,
                       json::JsonRpcResponse* pResponse)
{
   // get params
   std::string docPath;
   int line, column;
   Error error = json::readParams(request.params,
                                  &docPath,
                                  &line,
                                  &column);
   if (error)
      return error;

   // resolve the docPath if it's aliased
   FilePath filePath = module_context::resolveAliasedPath(docPath);

   // get the declaration cursor for this file location
   core::libclang::FileLocation location(filePath, line, column);

   // find the references
   std::string spelling;
   std::vector<core::libclang::FileRange> usageLocations;
   error = findReferences(location, &spelling, &usageLocations);
   if (error)
      return error;

   // produce source markers from cursor locations
   using namespace module_context;
   std::vector<SourceMarker> markers = SourceMarkerGenerator()
                                 .markersForCursorLocations(usageLocations);

   if (markers.size() > 0)
   {
      SourceMarkerSet markerSet("C++ Find Usages: " + spelling, markers);
      showSourceMarkers(markerSet, MarkerAutoSelectNone);
   }

   return Success();
}

} // namespace clang
} // namespace modules
} // namesapce session
} // namespace rstudio

<|endoftext|>


<commit_before>/*
 * Copyright (C) 20011 Francesco Nwokeka <francesco.nwokeka@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License version 2 as
 * published by the Free Software Foundation
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "../common/global-presence.h"
#include "globalpresenceservice.h"
#include "globalpresencesource.h"

GlobalPresenceSource::GlobalPresenceSource(QObject* parent)
    : DataContainer(parent)
    , m_globalPresence(new GlobalPresence(parent))
{
    // name of the source
    setObjectName("GlobalPresence");

    // global presence source data
    setData("currentPresence", "");
    setData("requestedPresence", "");
}

GlobalPresenceSource::~GlobalPresenceSource()
{
}

Plasma::Service* GlobalPresenceSource::createService()
{
    return new GlobalPresenceService(this);
}

GlobalPresence *GlobalPresenceSource::globalPresence() const
{
    return m_globalPresence;
}

void GlobalPresenceSource::onCurrentPresenceChanged(Tp::Presence newPresence)
{
    switch (newPresence.type()) {
        case Tp::ConnectionPresenceTypeAvailable:
            setData("currentPresence", "online");
            break;
        case Tp::ConnectionPresenceTypeAway:
            setData("currentPresence", "away");
            break;
        case Tp::ConnectionPresenceTypeExtendedAway:
            setData("currentPresence", "away-extended");
            break;
        case Tp::ConnectionPresenceTypeBusy:
            setData("currentPresence", "busy");
            break;
        case Tp::ConnectionPresenceTypeHidden:
            setData("currentPresence", "invisible");
            break;
        case Tp::ConnectionPresenceTypeOffline:
            setData("currentPresence", "offline");
            break;
        default:
            setData("currentPresence", "offline");
            break;
    }
}

void GlobalPresenceSource::setGlobalPresenceAccountManager(const Tp::AccountManagerPtr& accountMgr)
{
    if (!accountMgr || !accountMgr->isValid()) {
        kWarning() << "GlobalPresenceSource::setGlobalPresenceAccountManager Invalid account manager pointer";
        return;
    }

    m_globalPresence->setAccountManager(accountMgr);

    // setup connections and initialise with current data.
    connect(m_globalPresence, SIGNAL(currentPresenceChanged(Tp::Presence)), this, SLOT(onCurrentPresenceChanged(Tp::Presence)));
    onCurrentPresenceChanged(m_globalPresence->currentPresence());
}<commit_msg>add global presence message<commit_after>/*
 * Copyright (C) 20011 Francesco Nwokeka <francesco.nwokeka@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License version 2 as
 * published by the Free Software Foundation
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "../common/global-presence.h"
#include "globalpresenceservice.h"
#include "globalpresencesource.h"

GlobalPresenceSource::GlobalPresenceSource(QObject* parent)
    : DataContainer(parent)
    , m_globalPresence(new GlobalPresence(parent))
{
    // name of the source
    setObjectName("GlobalPresence");

    // global presence source data
    setData("currentPresence", "");
    setData("requestedPresence", "");
    setData("presenceMessage", "");
}

GlobalPresenceSource::~GlobalPresenceSource()
{
}

Plasma::Service* GlobalPresenceSource::createService()
{
    return new GlobalPresenceService(this);
}

GlobalPresence *GlobalPresenceSource::globalPresence() const
{
    return m_globalPresence;
}

void GlobalPresenceSource::onCurrentPresenceChanged(Tp::Presence newPresence)
{
    switch (newPresence.type()) {
        case Tp::ConnectionPresenceTypeAvailable:
            setData("currentPresence", "online");
            break;
        case Tp::ConnectionPresenceTypeAway:
            setData("currentPresence", "away");
            break;
        case Tp::ConnectionPresenceTypeExtendedAway:
            setData("currentPresence", "away-extended");
            break;
        case Tp::ConnectionPresenceTypeBusy:
            setData("currentPresence", "busy");
            break;
        case Tp::ConnectionPresenceTypeHidden:
            setData("currentPresence", "invisible");
            break;
        case Tp::ConnectionPresenceTypeOffline:
            setData("currentPresence", "offline");
            break;
        default:
            setData("currentPresence", "offline");
            break;
    }

    setData("presenceMessage", newPresence.statusMessage());
}

void GlobalPresenceSource::setGlobalPresenceAccountManager(const Tp::AccountManagerPtr& accountMgr)
{
    if (!accountMgr || !accountMgr->isValid()) {
        kWarning() << "GlobalPresenceSource::setGlobalPresenceAccountManager Invalid account manager pointer";
        return;
    }

    m_globalPresence->setAccountManager(accountMgr);

    // setup connections and initialise with current data.
    connect(m_globalPresence, SIGNAL(currentPresenceChanged(Tp::Presence)), this, SLOT(onCurrentPresenceChanged(Tp::Presence)));
    onCurrentPresenceChanged(m_globalPresence->currentPresence());
}<|endoftext|>


<commit_before>// Copyright 2020 Stanford University
//
// 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.
//

// test for Realm's serializing code

#include "realm/serialize.h"

#include <sys/resource.h>
#include <string.h>

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <map>
#include <list>
#include <set>

static bool verbose = false;
static int error_count = 0;

static void parse_args(int argc, const char *argv[])
{
  for(int i = 1; i < argc; i++) {
    if(!strcmp(argv[i], "-v")) {
      verbose = true;
      continue;
    }
  }
}

// helper functions to print out containers
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
{
  os << '[' << v.size() << ']';
  for(typename std::vector<T>::const_iterator it = v.begin();
      it != v.end();
      it++)
    os << ' ' << *it;
  return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::list<T>& l)
{
  os << '[' << l.size() << ']';
  for(typename std::list<T>::const_iterator it = l.begin();
      it != l.end();
      it++)
    os << ' ' << *it;
  return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::set<T>& s)
{
  os << '[' << s.size() << ']';
  for(typename std::set<T>::const_iterator it = s.begin();
      it != s.end();
      it++)
    os << ' ' << *it;
  return os;
}

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::map<T1, T2>& m)
{
  os << '[' << m.size() << ']';
  for(typename std::map<T1, T2>::const_iterator it = m.begin();
      it != m.end();
      it++)
    os << ' ' << it->first << '=' << it->second;
  return os;
}

template <typename T>
size_t test_dynamic(const char *name, const T& input, size_t exp_size = 0)
{
  // first serialize and check size
  Realm::Serialization::DynamicBufferSerializer dbs(0);

  bool ok1 = dbs << input;
  if(!ok1) {
    std::cout << "ERROR: " << name << "dynamic serialization failed!" << std::endl;
    error_count++;
  }

  size_t act_size = dbs.bytes_used();

  if(exp_size > 0) {
    if(act_size != exp_size) {
      std::cout << "ERROR: " << name << "dynamic size = " << act_size << " (should be " << exp_size << ")" << std::endl;
      error_count++;
    } else {
      if(verbose)
	std::cout << "OK: " << name << " dynamic size = " << act_size << std::endl;
    }
  }

  void *buffer = dbs.detach_buffer();

  // now deserialize into a new object and test for equality
  Realm::Serialization::FixedBufferDeserializer fbd(buffer, act_size);
  T output;

  bool ok2 = fbd >> output;
  if(!ok2) {
    std::cout << "ERROR: " << name << " dynamic deserialization failed!" << std::endl;
    error_count++;
  }

  ptrdiff_t leftover = fbd.bytes_left();
  if(leftover != 0) {
    std::cout << "ERROR: " << name << " dynamic leftover = " << leftover << std::endl;
    error_count++;
  }

  bool ok3 = (input == output);
  if(ok3) {
    if(verbose)
      std::cout << "OK: " << name << " dynamic output matches" << std::endl;
  } else {
    std::cout << "ERROR: " << name << " dynamic output mismatch:" << std::endl;
    std::cout << "Input:  " << input << std::endl;
    std::cout << "Buffer: [" << act_size << "]";
    std::cout << std::hex;
    for(size_t i = 0; i < act_size; i++)
      std::cout << ' ' << std::setfill('0') << std::setw(2) << (int)((unsigned char *)buffer)[i];
    std::cout << std::dec << std::endl;
#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wuninitialized"
#else
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
    std::cout << "Output: " << output << std::endl;
#pragma GCC diagnostic pop
    error_count++;
  }

  free(buffer);

  return act_size;
}

template <typename T>
void test_size(const char *name, const T& input, size_t exp_size)
{
  Realm::Serialization::ByteCountSerializer bcs;

  bool ok = bcs << input;
  if(!ok) {
    std::cout << "ERROR: " << name << "byetcount serialization failed!" << std::endl;
    error_count++;
  }

  size_t act_size = bcs.bytes_used();
  if(act_size != exp_size) {
    std::cout << "ERROR: " << name << "bytecount size = " << act_size << " (should be " << exp_size << ")" << std::endl;
    error_count++;
  } else {
    if(verbose)
      std::cout << "OK: " << name << " bytecount size = " << act_size << std::endl;
  }
}

template <typename T>
void test_fixed(const char *name, const T& input, size_t exp_size)
{
  // first serialize and check size
  void *buffer = malloc(exp_size);
  Realm::Serialization::FixedBufferSerializer fbs(buffer, exp_size);

  bool ok1 = fbs << input;
  if(!ok1) {
    std::cout << "ERROR: " << name << "fixed serialization failed!" << std::endl;
    error_count++;
  }

  ptrdiff_t leftover = fbs.bytes_left();

  if(leftover != 0) {
    std::cout << "ERROR: " << name << "fixed leftover = " << leftover << std::endl;
    error_count++;
  } else {
    if(verbose)
      std::cout << "OK: " << name << " fixed leftover = " << leftover << std::endl;
  }

  // now deserialize into a new object and test for equality
  Realm::Serialization::FixedBufferDeserializer fbd(buffer, exp_size);
  T output;

  bool ok2 = fbd >> output;
  if(!ok2) {
    std::cout << "ERROR: " << name << " fixed deserialization failed!" << std::endl;
    error_count++;
  }

  leftover = fbd.bytes_left();
  if(leftover != 0) {
    std::cout << "ERROR: " << name << " fixed leftover = " << leftover << std::endl;
    error_count++;
  }

  bool ok3 = (input == output);
  if(ok3) {
    if(verbose)
      std::cout << "OK: " << name << " fixed output matches" << std::endl;
  } else {
    std::cout << "ERROR: " << name << " fixed output mismatch:" << std::endl;
    std::cout << "Input:  " << input << std::endl;
    std::cout << "Buffer: [" << exp_size << "]";
    std::cout << std::hex;
    for(size_t i = 0; i < exp_size; i++)
      std::cout << ' ' << std::setfill('0') << std::setw(2) << (int)((unsigned char *)buffer)[i];
    std::cout << std::dec << std::endl;
#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wuninitialized"
#else
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
    std::cout << "Output: " << output << std::endl;
#pragma GCC diagnostic pop
    error_count++;
  }

  free(buffer);
}

template <typename T>
void do_test(const char *name, const T& input, size_t exp_size = 0)
{
  exp_size = test_dynamic(name, input, exp_size);
  test_size(name, input, exp_size);
  test_fixed(name, input, exp_size);
}

template <typename T1, typename T2>
struct Pair {
  T1 x;
  T2 y;

  Pair(void) : x(), y() {}
  Pair(T1 _x, T2 _y) : x(_x), y(_y) {}

  bool operator==(const Pair<T1,T2>& rhs) const
  {
    return (x == rhs.x) && (y == rhs.y);
  }

  friend std::ostream& operator<<(std::ostream& os, const Pair<T1, T2>& p)
  {
    return os << '<' << p.x << ',' << p.y << '>';
  }
};

#if 0
template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const Pair<T1, T2>& p)
{
  return os << '<' << p.x << ',' << p.y << '>';
}
#endif

typedef Pair<double, int> PODStruct;
TYPE_IS_SERIALIZABLE(PODStruct);

typedef Pair<double, float> PODPacked;
template <typename S>
bool serialize(S& s, const PODPacked& p) { return (s << p.x) && (s << p.y); }
template <typename S>
bool deserialize(S& s, PODPacked& p) { return (s >> p.x) && (s >> p.y); }

typedef Pair<double, char> PODPacked2;
template <typename S>
bool serdez(S& s, const PODPacked2& p) { return (s & p.x) && (s & p.y); }

typedef Pair<PODPacked, int> PP2;
template <typename S>
bool serdez(S& s, const PP2& p) { return (s & p.x) && (s & p.y); }

int main(int argc, const char *argv[])
{
  parse_args(argc, argv);

  {
    // a common failure mode for the serialization logic is infinite recursion,
    //  so set very tight bounds on our stack size and run time
    struct rlimit rl;
    int ret;
    rl.rlim_cur = rl.rlim_max = 16384;  // 16KB
    ret = setrlimit(RLIMIT_STACK, &rl);
    assert(ret == 0);
    rl.rlim_cur = rl.rlim_max = 5;  // 5 seconds
    ret = setrlimit(RLIMIT_CPU, &rl);
    assert(ret == 0);
  }

  int x = 5;
  do_test("int", x, sizeof(int));

  do_test("double", double(4.5), sizeof(double));

  //void *f = &x;
  //do_test("void*", f, sizeof(void *));

  do_test("pod struct", PODStruct(6.5, 7), sizeof(PODStruct));

  do_test("pod packed", PODPacked(8.5, 9.1), 12 /* not sizeof(PODPacked)*/);

  do_test("pod packed2", PODPacked2(10.5, 'z'), 9 /* not sizeof(PODPacked2)*/);

  do_test("pp2", PP2(PODPacked(44.3, 1), 9), 16 /* not sizeof(PP2) */);

  std::vector<int> a(3);
  a[0] = 1;
  a[1] = 2;
  a[2] = 3;
  do_test("vector<int>", a, sizeof(size_t) + a.size() * sizeof(int));

  std::vector<PODStruct> a2(1);
  a2[0] = PODStruct(3, 4);
  do_test("vector<PODStruct>", a2, (std::max(sizeof(size_t),
					     __alignof__(PODStruct)) +
				    a2.size() * sizeof(PODStruct)));

  std::vector<PODPacked> a3(1);
  a3[0] = PODPacked(3, 4);
  do_test("vector<PODPacked>", a3, (std::max(sizeof(size_t),
					     __alignof__(double)) +
				    12 /* not sizeof(PODPacked)*/));

  std::vector<PODPacked2> a4(1);
  a4[0] = PODPacked2(3, 4);
  do_test("vector<PODPacked2>", a4, (std::max(sizeof(size_t),
					      __alignof__(double)) +
				     9 /* not sizeof(PODPacked2)*/));

  std::list<int> b;
  b.push_back(4);
  b.push_back(5);
  b.push_back(6);
  b.push_back(7);
  do_test("list<int>", b, sizeof(size_t) + b.size() * sizeof(int));

  std::map<int, double> c;
  c[8] = 1.1;
  c[9] = 2.2;
  c[10] = 3.3;
  // in a 32-bit build, the size is "free" because it packs with the first
  //  int key
  do_test("map<int,double>", c, (sizeof(size_t) +
				 ((!c.empty() && (sizeof(size_t) ==
						  sizeof(int))) ? -4 : 0) +
				 c.size() * 16 /*alignment*/));

  std::vector<std::string> ss;
  ss.push_back("Hello");
  ss.push_back("World");
  do_test("vector<string>", ss, sizeof(size_t) + 12 + 9);

  std::set<int> s;
  s.insert(4);
  s.insert(2);
  s.insert(11);
  do_test("set<int>", s, sizeof(size_t) + s.size() * sizeof(int));

  if(error_count > 0) {
    std::cout << "ERRORS FOUND" << std::endl;
    exit(1);
  } else {
    std::cout << "all tests passed" << std::endl;
    exit(0);
  }
}
<commit_msg>test: be consistent with realm serialization aligner<commit_after>// Copyright 2020 Stanford University
//
// 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.
//

// test for Realm's serializing code

#include "realm/serialize.h"

#include <sys/resource.h>
#include <string.h>

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <map>
#include <list>
#include <set>

static bool verbose = false;
static int error_count = 0;

static void parse_args(int argc, const char *argv[])
{
  for(int i = 1; i < argc; i++) {
    if(!strcmp(argv[i], "-v")) {
      verbose = true;
      continue;
    }
  }
}

// helper functions to print out containers
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
{
  os << '[' << v.size() << ']';
  for(typename std::vector<T>::const_iterator it = v.begin();
      it != v.end();
      it++)
    os << ' ' << *it;
  return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::list<T>& l)
{
  os << '[' << l.size() << ']';
  for(typename std::list<T>::const_iterator it = l.begin();
      it != l.end();
      it++)
    os << ' ' << *it;
  return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::set<T>& s)
{
  os << '[' << s.size() << ']';
  for(typename std::set<T>::const_iterator it = s.begin();
      it != s.end();
      it++)
    os << ' ' << *it;
  return os;
}

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::map<T1, T2>& m)
{
  os << '[' << m.size() << ']';
  for(typename std::map<T1, T2>::const_iterator it = m.begin();
      it != m.end();
      it++)
    os << ' ' << it->first << '=' << it->second;
  return os;
}

template <typename T>
size_t test_dynamic(const char *name, const T& input, size_t exp_size = 0)
{
  // first serialize and check size
  Realm::Serialization::DynamicBufferSerializer dbs(0);

  bool ok1 = dbs << input;
  if(!ok1) {
    std::cout << "ERROR: " << name << "dynamic serialization failed!" << std::endl;
    error_count++;
  }

  size_t act_size = dbs.bytes_used();

  if(exp_size > 0) {
    if(act_size != exp_size) {
      std::cout << "ERROR: " << name << "dynamic size = " << act_size << " (should be " << exp_size << ")" << std::endl;
      error_count++;
    } else {
      if(verbose)
	std::cout << "OK: " << name << " dynamic size = " << act_size << std::endl;
    }
  }

  void *buffer = dbs.detach_buffer();

  // now deserialize into a new object and test for equality
  Realm::Serialization::FixedBufferDeserializer fbd(buffer, act_size);
  T output;

  bool ok2 = fbd >> output;
  if(!ok2) {
    std::cout << "ERROR: " << name << " dynamic deserialization failed!" << std::endl;
    error_count++;
  }

  ptrdiff_t leftover = fbd.bytes_left();
  if(leftover != 0) {
    std::cout << "ERROR: " << name << " dynamic leftover = " << leftover << std::endl;
    error_count++;
  }

  bool ok3 = (input == output);
  if(ok3) {
    if(verbose)
      std::cout << "OK: " << name << " dynamic output matches" << std::endl;
  } else {
    std::cout << "ERROR: " << name << " dynamic output mismatch:" << std::endl;
    std::cout << "Input:  " << input << std::endl;
    std::cout << "Buffer: [" << act_size << "]";
    std::cout << std::hex;
    for(size_t i = 0; i < act_size; i++)
      std::cout << ' ' << std::setfill('0') << std::setw(2) << (int)((unsigned char *)buffer)[i];
    std::cout << std::dec << std::endl;
#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wuninitialized"
#else
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
    std::cout << "Output: " << output << std::endl;
#pragma GCC diagnostic pop
    error_count++;
  }

  free(buffer);

  return act_size;
}

template <typename T>
void test_size(const char *name, const T& input, size_t exp_size)
{
  Realm::Serialization::ByteCountSerializer bcs;

  bool ok = bcs << input;
  if(!ok) {
    std::cout << "ERROR: " << name << "byetcount serialization failed!" << std::endl;
    error_count++;
  }

  size_t act_size = bcs.bytes_used();
  if(act_size != exp_size) {
    std::cout << "ERROR: " << name << "bytecount size = " << act_size << " (should be " << exp_size << ")" << std::endl;
    error_count++;
  } else {
    if(verbose)
      std::cout << "OK: " << name << " bytecount size = " << act_size << std::endl;
  }
}

template <typename T>
void test_fixed(const char *name, const T& input, size_t exp_size)
{
  // first serialize and check size
  void *buffer = malloc(exp_size);
  Realm::Serialization::FixedBufferSerializer fbs(buffer, exp_size);

  bool ok1 = fbs << input;
  if(!ok1) {
    std::cout << "ERROR: " << name << "fixed serialization failed!" << std::endl;
    error_count++;
  }

  ptrdiff_t leftover = fbs.bytes_left();

  if(leftover != 0) {
    std::cout << "ERROR: " << name << "fixed leftover = " << leftover << std::endl;
    error_count++;
  } else {
    if(verbose)
      std::cout << "OK: " << name << " fixed leftover = " << leftover << std::endl;
  }

  // now deserialize into a new object and test for equality
  Realm::Serialization::FixedBufferDeserializer fbd(buffer, exp_size);
  T output;

  bool ok2 = fbd >> output;
  if(!ok2) {
    std::cout << "ERROR: " << name << " fixed deserialization failed!" << std::endl;
    error_count++;
  }

  leftover = fbd.bytes_left();
  if(leftover != 0) {
    std::cout << "ERROR: " << name << " fixed leftover = " << leftover << std::endl;
    error_count++;
  }

  bool ok3 = (input == output);
  if(ok3) {
    if(verbose)
      std::cout << "OK: " << name << " fixed output matches" << std::endl;
  } else {
    std::cout << "ERROR: " << name << " fixed output mismatch:" << std::endl;
    std::cout << "Input:  " << input << std::endl;
    std::cout << "Buffer: [" << exp_size << "]";
    std::cout << std::hex;
    for(size_t i = 0; i < exp_size; i++)
      std::cout << ' ' << std::setfill('0') << std::setw(2) << (int)((unsigned char *)buffer)[i];
    std::cout << std::dec << std::endl;
#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wuninitialized"
#else
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
    std::cout << "Output: " << output << std::endl;
#pragma GCC diagnostic pop
    error_count++;
  }

  free(buffer);
}

template <typename T>
void do_test(const char *name, const T& input, size_t exp_size = 0)
{
  exp_size = test_dynamic(name, input, exp_size);
  test_size(name, input, exp_size);
  test_fixed(name, input, exp_size);
}

template <typename T1, typename T2>
struct Pair {
  T1 x;
  T2 y;

  Pair(void) : x(), y() {}
  Pair(T1 _x, T2 _y) : x(_x), y(_y) {}

  bool operator==(const Pair<T1,T2>& rhs) const
  {
    return (x == rhs.x) && (y == rhs.y);
  }

  friend std::ostream& operator<<(std::ostream& os, const Pair<T1, T2>& p)
  {
    return os << '<' << p.x << ',' << p.y << '>';
  }
};

#if 0
template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const Pair<T1, T2>& p)
{
  return os << '<' << p.x << ',' << p.y << '>';
}
#endif

typedef Pair<double, int> PODStruct;
TYPE_IS_SERIALIZABLE(PODStruct);

typedef Pair<double, float> PODPacked;
template <typename S>
bool serialize(S& s, const PODPacked& p) { return (s << p.x) && (s << p.y); }
template <typename S>
bool deserialize(S& s, PODPacked& p) { return (s >> p.x) && (s >> p.y); }

typedef Pair<double, char> PODPacked2;
template <typename S>
bool serdez(S& s, const PODPacked2& p) { return (s & p.x) && (s & p.y); }

typedef Pair<PODPacked, int> PP2;
template <typename S>
bool serdez(S& s, const PP2& p) { return (s & p.x) && (s & p.y); }

int main(int argc, const char *argv[])
{
  parse_args(argc, argv);

  {
    // a common failure mode for the serialization logic is infinite recursion,
    //  so set very tight bounds on our stack size and run time
    struct rlimit rl;
    int ret;
    rl.rlim_cur = rl.rlim_max = 16384;  // 16KB
    ret = setrlimit(RLIMIT_STACK, &rl);
    assert(ret == 0);
    rl.rlim_cur = rl.rlim_max = 5;  // 5 seconds
    ret = setrlimit(RLIMIT_CPU, &rl);
    assert(ret == 0);
  }

  int x = 5;
  do_test("int", x, sizeof(int));

  do_test("double", double(4.5), sizeof(double));

  //void *f = &x;
  //do_test("void*", f, sizeof(void *));

  do_test("pod struct", PODStruct(6.5, 7), sizeof(PODStruct));

  do_test("pod packed", PODPacked(8.5, 9.1), 12 /* not sizeof(PODPacked)*/);

  do_test("pod packed2", PODPacked2(10.5, 'z'), 9 /* not sizeof(PODPacked2)*/);

  do_test("pp2", PP2(PODPacked(44.3, 1), 9), 16 /* not sizeof(PP2) */);

  std::vector<int> a(3);
  a[0] = 1;
  a[1] = 2;
  a[2] = 3;
  do_test("vector<int>", a, sizeof(size_t) + a.size() * sizeof(int));

  std::vector<PODStruct> a2(1);
  a2[0] = PODStruct(3, 4);
  do_test("vector<PODStruct>", a2, (std::max(sizeof(size_t),
					     REALM_ALIGNOF(PODStruct)) +
				    a2.size() * sizeof(PODStruct)));

  std::vector<PODPacked> a3(1);
  a3[0] = PODPacked(3, 4);
  do_test("vector<PODPacked>", a3, (std::max(sizeof(size_t),
					     REALM_ALIGNOF(double)) +
				    12 /* not sizeof(PODPacked)*/));

  std::vector<PODPacked2> a4(1);
  a4[0] = PODPacked2(3, 4);
  do_test("vector<PODPacked2>", a4, (std::max(sizeof(size_t),
					      REALM_ALIGNOF(double)) +
				     9 /* not sizeof(PODPacked2)*/));

  std::list<int> b;
  b.push_back(4);
  b.push_back(5);
  b.push_back(6);
  b.push_back(7);
  do_test("list<int>", b, sizeof(size_t) + b.size() * sizeof(int));

  std::map<int, double> c;
  c[8] = 1.1;
  c[9] = 2.2;
  c[10] = 3.3;
  // in a 32-bit build, the size is "free" because it packs with the first
  //  int key
  do_test("map<int,double>", c, (sizeof(size_t) -
                                 (c.empty() ? 0 :
                                              (REALM_ALIGNOF(double) -
                                               std::max(REALM_ALIGNOF(size_t),
                                                        REALM_ALIGNOF(int)))) +
                                 c.size() * (std::max(sizeof(int),
                                                      REALM_ALIGNOF(double)) +
                                             sizeof(double))));

  std::vector<std::string> ss;
  ss.push_back("Hello");
  ss.push_back("World");
  do_test("vector<string>", ss, sizeof(size_t) + 12 + 9);

  std::set<int> s;
  s.insert(4);
  s.insert(2);
  s.insert(11);
  do_test("set<int>", s, sizeof(size_t) + s.size() * sizeof(int));

  if(error_count > 0) {
    std::cout << "ERRORS FOUND" << std::endl;
    exit(1);
  } else {
    std::cout << "all tests passed" << std::endl;
    exit(0);
  }
}
<|endoftext|>