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

  Program:   Visualization Toolkit
  Module:    vtkMultiGroupDataSet.cxx

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

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

=========================================================================*/
#include "vtkMultiGroupDataSet.h"

#include "vtkDataSet.h"
#include "vtkMultiGroupDataInformation.h"
#include "vtkMultiGroupDataIterator.h"
#include "vtkMultiGroupDataSetInternal.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkInformationIntegerKey.h"

#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkMultiGroupDataSet, "1.2");
vtkStandardNewMacro(vtkMultiGroupDataSet);

vtkCxxSetObjectMacro(vtkMultiGroupDataSet,MultiGroupDataInformation,vtkMultiGroupDataInformation);

vtkInformationKeyMacro(vtkMultiGroupDataSet,GROUP,Integer);

//----------------------------------------------------------------------------
vtkMultiGroupDataSet::vtkMultiGroupDataSet()
{
  this->Internal = new vtkMultiGroupDataSetInternal;
  this->MultiGroupDataInformation = vtkMultiGroupDataInformation::New();
}

//----------------------------------------------------------------------------
vtkMultiGroupDataSet::~vtkMultiGroupDataSet()
{
  this->InitializeDataSets();
  delete this->Internal;
  this->SetMultiGroupDataInformation(0);
}

//----------------------------------------------------------------------------
vtkCompositeDataIterator* vtkMultiGroupDataSet::NewIterator()
{
  vtkMultiGroupDataIterator* iter = vtkMultiGroupDataIterator::New();
  iter->SetDataSet(this);
  return iter;
}

//----------------------------------------------------------------------------
vtkMGDSNode* vtkMultiGroupDataSet::NewNode()
{
  return new vtkMGDSNode;
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::InitializeDataSets()
{
  this->Internal->DataSets.clear();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::Initialize()
{
  this->Superclass::Initialize();
  this->InitializeDataSets();
  this->SetMultiGroupDataInformation(0);
  this->MultiGroupDataInformation = vtkMultiGroupDataInformation::New();
}

//----------------------------------------------------------------------------
unsigned int vtkMultiGroupDataSet::GetNumberOfGroups()
{
  return this->Internal->DataSets.size();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::SetNumberOfGroups(unsigned int numGroups)
{
  this->MultiGroupDataInformation->SetNumberOfGroups(numGroups);
  if (numGroups == this->GetNumberOfGroups())
    {
    return;
    }
  this->Internal->DataSets.resize(numGroups);
  this->Modified();
}

//----------------------------------------------------------------------------
unsigned int vtkMultiGroupDataSet::GetNumberOfDataSets(unsigned int group)
{
  if (this->Internal->DataSets.size() <= group)
    {
    return 0;
    }

  vtkMultiGroupDataSetInternal::GroupDataSetsType& ldataSets =
    this->Internal->DataSets[group];

  return ldataSets.size();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::SetNumberOfDataSets(unsigned int group,
                                                 unsigned int numDataSets)
{
  this->MultiGroupDataInformation->SetNumberOfDataSets(group, numDataSets);
  if (numDataSets == this->GetNumberOfDataSets(group))
    {
    return;
    }
  // Make sure that there is a vector allocated for this group
  if (this->Internal->DataSets.size() <= group)
    {
    this->SetNumberOfGroups(group+1);
    }

  vtkMultiGroupDataSetInternal::GroupDataSetsType& ldataSets =
    this->Internal->DataSets[group];

  // We need to delete all extra nodes since we manage memory for them.
  unsigned int curNumDataSets = ldataSets.size();
  ldataSets.resize(numDataSets);

  // Assign NULL to all new pointers. We use this later to figure out
  // whether a node allocated for a particular entry.
  if (curNumDataSets < numDataSets)
    {
    for (unsigned int i=curNumDataSets; i<numDataSets; i++)
      {
      ldataSets[i] = 0;
      }
    }
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::InitializeNode(unsigned int group,
                                            unsigned int id)
{

  // Make sure that there is a vector allocated for this group
  if (this->Internal->DataSets.size() <= group)
    {
    this->SetNumberOfGroups(group+1);
    }

  vtkMultiGroupDataSetInternal::GroupDataSetsType& ldataSets =
    this->Internal->DataSets[group];

  // Make sure that the size of the vector for this group is big enough.
  if (ldataSets.size() <= id)
    {
    this->SetNumberOfDataSets(group, id+1);
    }

  ldataSets[id] = 0;

  this->Modified();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::SetDataSet(unsigned int group,
                                        unsigned int id,
                                        vtkDataObject* ds)
{
  // Make sure that there is a vector allocated for this group
  if (this->Internal->DataSets.size() <= group)
    {
    this->SetNumberOfGroups(group+1);
    }

  vtkMultiGroupDataSetInternal::GroupDataSetsType& ldataSets =
    this->Internal->DataSets[group];

  // Make sure that the size of the vector for this group is big enough.
  if (ldataSets.size() <= id)
    {
    this->SetNumberOfDataSets(group, id+1);
    }

  ldataSets[id] = ds;
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::AddDataSet(vtkInformation* index, vtkDataObject* dobj)
{
  if (index->Has(INDEX()) && index->Has(GROUP()))
    {
    this->SetDataSet(index->Get(GROUP()), index->Get(INDEX()), dobj);
    }
}

//----------------------------------------------------------------------------
vtkDataObject* vtkMultiGroupDataSet::GetDataSet(unsigned int group,
                                                  unsigned int id)
{
  if (this->Internal->DataSets.size() <= group)
    {
    return 0;
    }

  vtkMultiGroupDataSetInternal::GroupDataSetsType& ldataSets =
    this->Internal->DataSets[group];
  if (ldataSets.size() <= id)
    {
    return 0;
    }

  if (!ldataSets[id])
    {
    return 0;
    }

  return ldataSets[id];
}

//----------------------------------------------------------------------------
vtkDataObject* vtkMultiGroupDataSet::GetDataSet(vtkInformation* index)
{
  if (index->Has(INDEX()) && index->Has(GROUP()))
    {
    return this->GetDataSet(index->Get(GROUP()), index->Get(INDEX()));
    }
  return 0;
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::ShallowCopy(vtkDataObject *src)
{
  if (src == this)
    {
    return;
    }
  this->InitializeDataSets();
  this->Superclass::ShallowCopy(src);

  vtkMultiGroupDataSet* from = vtkMultiGroupDataSet::SafeDownCast(src);
  if (from)
    {
    this->SetMultiGroupDataInformation(from->MultiGroupDataInformation);
    unsigned int numGroups = from->GetNumberOfGroups();
    this->SetNumberOfGroups(numGroups);
    for (unsigned int i=0; i<numGroups; i++)
      {
      unsigned int numDataSets = from->GetNumberOfDataSets(i);
      this->SetNumberOfDataSets(i, numDataSets);
      for (unsigned int j=0; j<numDataSets; j++)
        {
        this->SetDataSet(i, j, from->GetDataSet(i,j));
        }
      }
    }

  this->Modified();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::DeepCopy(vtkDataObject *src)
{
  if (src == this)
    {
    return;
    }
  this->InitializeDataSets();
  this->Superclass::ShallowCopy(src);
  this->SetMultiGroupDataInformation(0);
  this->MultiGroupDataInformation = vtkMultiGroupDataInformation::New();

  vtkMultiGroupDataSet* from = vtkMultiGroupDataSet::SafeDownCast(src);
  if (from)
    {
    this->MultiGroupDataInformation->DeepCopy(
      from->MultiGroupDataInformation);
    unsigned int numGroups = from->GetNumberOfGroups();
    this->SetNumberOfGroups(numGroups);
    for (unsigned int i=0; i<numGroups; i++)
      {
      unsigned int numDataSets = from->GetNumberOfDataSets(i);
      this->SetNumberOfDataSets(i, numDataSets);
      for (unsigned int j=0; j<numDataSets; j++)
        {
        vtkDataObject* ds = from->GetDataSet(i,j);
        if (ds)
          {
          vtkDataObject* copy = ds->NewInstance();
          copy->DeepCopy(ds);
          this->SetDataSet(i, j, copy);
          }
        }
      }
    }

  this->Modified();
}

//----------------------------------------------------------------------------
vtkIdType vtkMultiGroupDataSet::GetNumberOfPoints()
{
  vtkIdType numPts = 0;

  vtkCompositeDataIterator* iterator = this->NewIterator();
  iterator->InitTraversal();
  while (!iterator->IsDoneWithTraversal())
    {
    vtkDataObject* dObj = iterator->GetCurrentDataObject();
    if (dObj)
      {
      vtkDataSet* ds = vtkDataSet::SafeDownCast(dObj);
      if (ds)
        {
        numPts += ds->GetNumberOfPoints();
        }
      else
        {
        vtkMultiGroupDataSet* hds =
          vtkMultiGroupDataSet::SafeDownCast(dObj);
        if (hds)
          {
          numPts += hds->GetNumberOfPoints();
          }
        }
      }
    iterator->GoToNextItem();
    }
  iterator->Delete();

  return numPts;
}

//----------------------------------------------------------------------------
vtkMultiGroupDataSet* vtkMultiGroupDataSet::GetData(vtkInformation* info)
{
  return
    info? vtkMultiGroupDataSet::SafeDownCast(info->Get(DATA_OBJECT())) : 0;
}

//----------------------------------------------------------------------------
vtkMultiGroupDataSet* vtkMultiGroupDataSet::GetData(vtkInformationVector* v,
                                                    int i)
{
  return vtkMultiGroupDataSet::GetData(v->GetInformationObject(i));
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "MultiGroupDataInformation: ";
  if (this->MultiGroupDataInformation)
    {
    os << endl;
    this->MultiGroupDataInformation->PrintSelf(os, indent.GetNextIndent());
    }
  else
    {
    os << "(none)" << endl;
    }
}

<commit_msg>BUG: ungroup was segfaulting because from did not yet have complete information. Addresses bug# 4784<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMultiGroupDataSet.cxx

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

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

=========================================================================*/
#include "vtkMultiGroupDataSet.h"

#include "vtkDataSet.h"
#include "vtkMultiGroupDataInformation.h"
#include "vtkMultiGroupDataIterator.h"
#include "vtkMultiGroupDataSetInternal.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkInformationIntegerKey.h"

#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkMultiGroupDataSet, "1.3");
vtkStandardNewMacro(vtkMultiGroupDataSet);

vtkCxxSetObjectMacro(vtkMultiGroupDataSet,MultiGroupDataInformation,vtkMultiGroupDataInformation);

vtkInformationKeyMacro(vtkMultiGroupDataSet,GROUP,Integer);

//----------------------------------------------------------------------------
vtkMultiGroupDataSet::vtkMultiGroupDataSet()
{
  this->Internal = new vtkMultiGroupDataSetInternal;
  this->MultiGroupDataInformation = vtkMultiGroupDataInformation::New();
}

//----------------------------------------------------------------------------
vtkMultiGroupDataSet::~vtkMultiGroupDataSet()
{
  this->InitializeDataSets();
  delete this->Internal;
  this->SetMultiGroupDataInformation(0);
}

//----------------------------------------------------------------------------
vtkCompositeDataIterator* vtkMultiGroupDataSet::NewIterator()
{
  vtkMultiGroupDataIterator* iter = vtkMultiGroupDataIterator::New();
  iter->SetDataSet(this);
  return iter;
}

//----------------------------------------------------------------------------
vtkMGDSNode* vtkMultiGroupDataSet::NewNode()
{
  return new vtkMGDSNode;
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::InitializeDataSets()
{
  this->Internal->DataSets.clear();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::Initialize()
{
  this->Superclass::Initialize();
  this->InitializeDataSets();
  this->SetMultiGroupDataInformation(0);
  this->MultiGroupDataInformation = vtkMultiGroupDataInformation::New();
}

//----------------------------------------------------------------------------
unsigned int vtkMultiGroupDataSet::GetNumberOfGroups()
{
  return this->Internal->DataSets.size();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::SetNumberOfGroups(unsigned int numGroups)
{
  this->MultiGroupDataInformation->SetNumberOfGroups(numGroups);
  if (numGroups == this->GetNumberOfGroups())
    {
    return;
    }
  this->Internal->DataSets.resize(numGroups);
  this->Modified();
}

//----------------------------------------------------------------------------
unsigned int vtkMultiGroupDataSet::GetNumberOfDataSets(unsigned int group)
{
  if (this->Internal->DataSets.size() <= group)
    {
    return 0;
    }

  vtkMultiGroupDataSetInternal::GroupDataSetsType& ldataSets =
    this->Internal->DataSets[group];

  return ldataSets.size();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::SetNumberOfDataSets(unsigned int group,
                                                 unsigned int numDataSets)
{
  this->MultiGroupDataInformation->SetNumberOfDataSets(group, numDataSets);
  if (numDataSets == this->GetNumberOfDataSets(group))
    {
    return;
    }
  // Make sure that there is a vector allocated for this group
  if (this->Internal->DataSets.size() <= group)
    {
    this->SetNumberOfGroups(group+1);
    }

  vtkMultiGroupDataSetInternal::GroupDataSetsType& ldataSets =
    this->Internal->DataSets[group];

  // We need to delete all extra nodes since we manage memory for them.
  unsigned int curNumDataSets = ldataSets.size();
  ldataSets.resize(numDataSets);

  // Assign NULL to all new pointers. We use this later to figure out
  // whether a node allocated for a particular entry.
  if (curNumDataSets < numDataSets)
    {
    for (unsigned int i=curNumDataSets; i<numDataSets; i++)
      {
      ldataSets[i] = 0;
      }
    }
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::InitializeNode(unsigned int group,
                                            unsigned int id)
{

  // Make sure that there is a vector allocated for this group
  if (this->Internal->DataSets.size() <= group)
    {
    this->SetNumberOfGroups(group+1);
    }

  vtkMultiGroupDataSetInternal::GroupDataSetsType& ldataSets =
    this->Internal->DataSets[group];

  // Make sure that the size of the vector for this group is big enough.
  if (ldataSets.size() <= id)
    {
    this->SetNumberOfDataSets(group, id+1);
    }

  ldataSets[id] = 0;

  this->Modified();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::SetDataSet(unsigned int group,
                                        unsigned int id,
                                        vtkDataObject* ds)
{
  // Make sure that there is a vector allocated for this group
  if (this->Internal->DataSets.size() <= group)
    {
    this->SetNumberOfGroups(group+1);
    }

  vtkMultiGroupDataSetInternal::GroupDataSetsType& ldataSets =
    this->Internal->DataSets[group];

  // Make sure that the size of the vector for this group is big enough.
  if (ldataSets.size() <= id)
    {
    this->SetNumberOfDataSets(group, id+1);
    }

  ldataSets[id] = ds;
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::AddDataSet(vtkInformation* index, vtkDataObject* dobj)
{
  if (index->Has(INDEX()) && index->Has(GROUP()))
    {
    this->SetDataSet(index->Get(GROUP()), index->Get(INDEX()), dobj);
    }
}

//----------------------------------------------------------------------------
vtkDataObject* vtkMultiGroupDataSet::GetDataSet(unsigned int group,
                                                  unsigned int id)
{
  if (this->Internal->DataSets.size() <= group)
    {
    return 0;
    }

  vtkMultiGroupDataSetInternal::GroupDataSetsType& ldataSets =
    this->Internal->DataSets[group];
  if (ldataSets.size() <= id)
    {
    return 0;
    }

  if (!ldataSets[id])
    {
    return 0;
    }

  return ldataSets[id];
}

//----------------------------------------------------------------------------
vtkDataObject* vtkMultiGroupDataSet::GetDataSet(vtkInformation* index)
{
  if (index->Has(INDEX()) && index->Has(GROUP()))
    {
    return this->GetDataSet(index->Get(GROUP()), index->Get(INDEX()));
    }
  return 0;
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::ShallowCopy(vtkDataObject *src)
{
  if (src == this)
    {
    return;
    }
  this->InitializeDataSets();
  this->Superclass::ShallowCopy(src);

  vtkMultiGroupDataSet* from = vtkMultiGroupDataSet::SafeDownCast(src);
  if (from)
    {
    if (from->MultiGroupDataInformation)
      {
      this->SetMultiGroupDataInformation(from->MultiGroupDataInformation);
      }
    unsigned int numGroups = from->GetNumberOfGroups();
    this->SetNumberOfGroups(numGroups);
    for (unsigned int i=0; i<numGroups; i++)
      {
      unsigned int numDataSets = from->GetNumberOfDataSets(i);
      this->SetNumberOfDataSets(i, numDataSets);
      for (unsigned int j=0; j<numDataSets; j++)
        {
        this->SetDataSet(i, j, from->GetDataSet(i,j));
        }
      }
    }

  this->Modified();
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::DeepCopy(vtkDataObject *src)
{
  if (src == this)
    {
    return;
    }
  this->InitializeDataSets();
  this->Superclass::ShallowCopy(src);
  this->SetMultiGroupDataInformation(0);
  this->MultiGroupDataInformation = vtkMultiGroupDataInformation::New();

  vtkMultiGroupDataSet* from = vtkMultiGroupDataSet::SafeDownCast(src);
  if (from)
    {
    this->MultiGroupDataInformation->DeepCopy(
      from->MultiGroupDataInformation);
    unsigned int numGroups = from->GetNumberOfGroups();
    this->SetNumberOfGroups(numGroups);
    for (unsigned int i=0; i<numGroups; i++)
      {
      unsigned int numDataSets = from->GetNumberOfDataSets(i);
      this->SetNumberOfDataSets(i, numDataSets);
      for (unsigned int j=0; j<numDataSets; j++)
        {
        vtkDataObject* ds = from->GetDataSet(i,j);
        if (ds)
          {
          vtkDataObject* copy = ds->NewInstance();
          copy->DeepCopy(ds);
          this->SetDataSet(i, j, copy);
          }
        }
      }
    }

  this->Modified();
}

//----------------------------------------------------------------------------
vtkIdType vtkMultiGroupDataSet::GetNumberOfPoints()
{
  vtkIdType numPts = 0;

  vtkCompositeDataIterator* iterator = this->NewIterator();
  iterator->InitTraversal();
  while (!iterator->IsDoneWithTraversal())
    {
    vtkDataObject* dObj = iterator->GetCurrentDataObject();
    if (dObj)
      {
      vtkDataSet* ds = vtkDataSet::SafeDownCast(dObj);
      if (ds)
        {
        numPts += ds->GetNumberOfPoints();
        }
      else
        {
        vtkMultiGroupDataSet* hds =
          vtkMultiGroupDataSet::SafeDownCast(dObj);
        if (hds)
          {
          numPts += hds->GetNumberOfPoints();
          }
        }
      }
    iterator->GoToNextItem();
    }
  iterator->Delete();

  return numPts;
}

//----------------------------------------------------------------------------
vtkMultiGroupDataSet* vtkMultiGroupDataSet::GetData(vtkInformation* info)
{
  return
    info? vtkMultiGroupDataSet::SafeDownCast(info->Get(DATA_OBJECT())) : 0;
}

//----------------------------------------------------------------------------
vtkMultiGroupDataSet* vtkMultiGroupDataSet::GetData(vtkInformationVector* v,
                                                    int i)
{
  return vtkMultiGroupDataSet::GetData(v->GetInformationObject(i));
}

//----------------------------------------------------------------------------
void vtkMultiGroupDataSet::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "MultiGroupDataInformation: ";
  if (this->MultiGroupDataInformation)
    {
    os << endl;
    this->MultiGroupDataInformation->PrintSelf(os, indent.GetNextIndent());
    }
  else
    {
    os << "(none)" << endl;
    }
}

<|endoftext|>


<commit_before>#include "from_json.h"

#include <unordered_map>
#include <stack>

#include <asdf_multiplat/utilities/utilities.h>

using namespace asdf;
using namespace asdf::util;

namespace tired_of_build_issues
{
    std::string read_text_file(std::string const& filepath) {
        //if(!is_file(filepath))
        //{
        //    //throw file_open_exception(filepath);
        //    EXPLODE("C'est une probleme");
        //}

        std::string outputstring;
        std::ifstream ifs(filepath, std::ifstream::in);
        ifs.exceptions( std::ios::failbit );

        // ASSERT(ifs.good(), "Error loading text file %s", filepath.c_str());
        if(!ifs.good())
        {
            //throw file_open_exception(filepath);
            EXPLODE("C'est une probleme");
        }

        ifs.seekg(0, std::ios::end);		//seek to the end to get the size the output string should be
        outputstring.reserve(size_t(ifs.tellg()));	//reserve necessary memory up front
        ifs.seekg(0, std::ios::beg);		//seek back to the start

        outputstring.assign((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

        ifs.close();

        return outputstring;
    }
}

// custom hash function for std::path so that I can use it as
// a key in unordered_map
namespace std
{
template<>
struct hash<stdfs::path> {
    size_t operator()(const stdfs::path &p) const {
        return std::hash<std::string>()(canonical(p).string());
    }
};
}

namespace plantgen
{
    // global stack used for resolving relative filepaths
    // when including other json files as node properties / values
    // I should probably devise a better method of doing this, since
    // I don't think this will handle more than one level of inclusion
    // if the JSON files are not all in the same directory

    //FIXME make this not global
    std::stack<stdfs::path> include_dir_stack;
    std::unordered_map<stdfs::path, pregen_node_t> include_cache;

    std::vector<std::string> value_string_list_from_json_array(cJSON* json_array)
    {
        ASSERT(json_array, "");
        ASSERT(json_array->type == cJSON_Array, "json_array is not actually a JSON array");
        std::vector<std::string> values;

        cJSON* j = json_array->child;
        while(j)
        {
            if(j->type != cJSON_String)
            {
                throw json_type_exception(include_dir_stack.top(), *j, cJSON_String);
            }

            values.emplace_back(j->valuestring);
            j = j->next;
        }

        return values;
    }

    multi_value_t multi_value_from_json(cJSON* json)
    {
        ASSERT(str_eq(json->child->string, "Multi"), "Expected a \"Multi\" json_obj");
        ASSERT(json->child->type == cJSON_Number, "JSON Value of \"Multi\" should be an integer");

        multi_value_t v;
        v.num_to_pick = json->child->valueint;

        try {
            v.values = std::move(value_string_list_from_json_array(json->child->next));
        }
        catch (json_type_exception& je)
        {

            std::string s = "json type error: \"Multi\" only supports a value list of strings, not " + std::string(cJSON_type_strings[je.json_type_found]);
            throw std::runtime_error(std::move(s));
        }

        return v;
    }

    range_value_t range_value_from_json(cJSON* json)
    {
        ASSERT(str_eq(json->string, "Range"), "Expected a \"Range\" json_obj");
        return value_string_list_from_json_array(json);
    }

    weighted_value_t value_from_string(std::string const& value_string)
    {
        weighted_value_t v = value_string;

        if(value_string[0] == '%')
        {
            auto space_pos = value_string.find_first_of(' ');

            if(space_pos > 1)
            {
                v = value_string.substr(space_pos+1, std::string::npos);
                v.weight = std::stoi(value_string.substr(1, space_pos));
            }
            else
            {
                //TODO: better error message
                std::cout << "Invalid Weight Specifier for \"" << value_string << "\"\n";
            }
        }

        return v;
    }

    weighted_value_t value_type_from_json(cJSON* json)
    {
        if(json->type == cJSON_String)
        {
            return value_from_string(std::string(json->valuestring));
        }
        else if(!json->child)
        {
            EXPLODE("invalid value object %s", json->string);
            return null_value_t();
        }
        else if(str_eq(json->child->string, "Multi"))
        {
            return multi_value_from_json(json);
        }
        else if(str_eq(json->child->string, "Range"))
        {
            return range_value_from_json(json->child);
        }
        else
        {
            EXPLODE("unrecognized value object %s", json->child->string);
            return weighted_value_t(null_value_t());
        }
    }

    user_value_t user_value_from_json(cJSON const& json)
    {
        switch(json.type)
        {
            case cJSON_True:
                return user_value_t(bool(true));

            case cJSON_False:
                return user_value_t(bool(false));

            case cJSON_Number:
                return user_value_t(json.valuedouble);

            case cJSON_String:
                return user_value_t(std::string(json.valuestring));

            default:
                throw json_type_exception(include_dir_stack.top(), json,
                    {cJSON_True, cJSON_False, cJSON_Number, cJSON_String});
                break;
        };

        return nullptr;
    }

    user_data_node_t user_node_from_json(cJSON const& json)
    {
        user_data_node_t node;

        if(json.string)
            node.name = json.string;

        switch(json.type)
        {
            case cJSON_Object:
            case cJSON_Array:
            {
                cJSON* cur_child = json.child;
                while(cur_child)
                {
                    node.add_child(user_node_from_json(*cur_child));

                    cur_child = cur_child->next;
                }

                break;
            }

            default:
                node.value = user_value_from_json(json);
                break;
        }

        return node;
    }

    int weight_from_string(std::string const& weight_str)
    {
        if(weight_str[0] == '%')
        {
            if(weight_str.size() == 1)
            {
                return weight_inherit_code;
            }

            auto space_pos = weight_str.find_first_of(' ');

            if(space_pos > 1)
            {
                return std::stoi(weight_str.substr(1, space_pos));
            }
            else
            {
                //TODO: better error message
                std::cout << "Invalid Weight Specifier for \"" << weight_str << "\"\n";
            }
        }

        return -1;
    }

    pregen_node_t node_from_json(cJSON* json_node)
    {
        pregen_node_t node;

        cJSON* cur_child = json_node->child;
        while(cur_child)
        {
            if(str_eq(cur_child->string, "Name"))
            {
                node.name = cur_child->valuestring;
            }
            else if(str_eq(cur_child->string, "Properties"))
            {
                cJSON* property_json = cur_child->child;
                while(property_json)
                {
                    node.add_child(node_from_json(property_json));
                    property_json = property_json->next;
                }
            }
            else if(str_eq(cur_child->string, "Values"))
            {
                cJSON* value_json = cur_child->child;
                while(value_json)
                {
                    // if the value is a node, load it differently
                    // since we can't return a node as part of the variant

                    //if the value is an object starting with a child named "Name", it's a node
                    if(value_json->type == cJSON_Object
                    && value_json->child
                    && str_eq(value_json->child->string, "Name"))
                    {
                        node.value_nodes.push_back(std::move(node_from_json(value_json)));
                    }
                    else
                    {
                        node.value_nodes.emplace_back(value_type_from_json(value_json));
                    }

                    value_json = value_json->next;
                }
            }
            else if(str_eq(cur_child->string, "Include"))
            {
                ASSERT(cur_child->type == cJSON_String, "Include filepath must be a string");

                stdfs::path relpath(cur_child->valuestring);

                if(relpath.empty())
                {
                    throw std::runtime_error("Include path is empty for \"" + node.name + "\"");
                }

                auto parent_path = include_dir_stack.top().parent_path();
                stdfs::path fullpath = parent_path / relpath;

                try{
                    auto included_node = node_from_json(fullpath);

                    // if(included_node.name == node.name)
                    // {
                        auto prev_weight = node.weight;
                        node.merge_with(std::move(included_node));
                        node.weight = prev_weight;
                    // }
                    // else
                    // {
                    //     node.add_child(std::move(included_node));
                    // }
                }
                catch(file_not_found_exception const&)
                {
                    throw include_exception{include_dir_stack.top(), fullpath};
                }
            }
            else if(str_eq(cur_child->string, "Weight"))
            {
                switch(cur_child->type)
                {
                case cJSON_Number:
                    node.weight = cur_child->valueint;
                    break;

                case cJSON_String:
                {
                    int weight = weight_from_string(std::string(cur_child->valuestring));
                    if(weight >= 0 || weight == weight_inherit_code)
                    {
                        node.weight = weight;
                    }
                    else
                        std::cout << "Invalid Weight Specifier for \"" << node.name << "\"\n";

                    break;
                }

                default:
                    throw json_type_exception(include_dir_stack.top(), *cur_child,
                        {cJSON_Number, cJSON_String});
                }
            }
            else
            {
                node.user_data.add_child(user_node_from_json(*cur_child));
            }

            cur_child = cur_child->next;
        }

        //handle weight inhereit
        if(node.weight == weight_inherit_code)
        {
            node.weight = total_weight(node.value_nodes);
        }

        return node;
    }

    pregen_node_t node_from_json(stdfs::path const& _filepath)
    {
        auto filepath = stdfs::canonical(_filepath);

        if(!stdfs::is_regular_file(filepath))
            throw file_not_found_exception{filepath};

        auto canonical_path = stdfs::canonical(filepath);

        auto cached_node_entry = include_cache.find(canonical_path);
        if(cached_node_entry != include_cache.end())
        {
            return cached_node_entry->second;
        }
        else
        {
            //std::string json_str = asdf::util::read_text_file(filepath);
            std::string json_str = tired_of_build_issues::read_text_file(canonical_path.string());
            cJSON* json_root = cJSON_Parse(json_str.c_str());

            if(!json_root)
            {
                throw json_parse_exception(filepath, cJSON_GetErrorPtr());
            }

            include_dir_stack.push(canonical_path);
            auto node = node_from_json(json_root);
            cJSON_Delete(json_root);
            include_dir_stack.pop();

            include_cache.insert({canonical_path, node});

            return node;
        }
    }

    generated_node_t generate_node_from_json(stdfs::path const& filepath)
    {
        auto node = node_from_json(filepath);
        return generate_node(node);
    }

}<commit_msg>a nameless node will now inherit the name of an included node (so you can have a node with just an include line and use it's name)<commit_after>#include "from_json.h"

#include <unordered_map>
#include <stack>

#include <asdf_multiplat/utilities/utilities.h>

using namespace asdf;
using namespace asdf::util;

namespace tired_of_build_issues
{
    std::string read_text_file(std::string const& filepath) {
        //if(!is_file(filepath))
        //{
        //    //throw file_open_exception(filepath);
        //    EXPLODE("C'est une probleme");
        //}

        std::string outputstring;
        std::ifstream ifs(filepath, std::ifstream::in);
        ifs.exceptions( std::ios::failbit );

        // ASSERT(ifs.good(), "Error loading text file %s", filepath.c_str());
        if(!ifs.good())
        {
            //throw file_open_exception(filepath);
            EXPLODE("C'est une probleme");
        }

        ifs.seekg(0, std::ios::end);		//seek to the end to get the size the output string should be
        outputstring.reserve(size_t(ifs.tellg()));	//reserve necessary memory up front
        ifs.seekg(0, std::ios::beg);		//seek back to the start

        outputstring.assign((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

        ifs.close();

        return outputstring;
    }
}

// custom hash function for std::path so that I can use it as
// a key in unordered_map
namespace std
{
template<>
struct hash<stdfs::path> {
    size_t operator()(const stdfs::path &p) const {
        return std::hash<std::string>()(canonical(p).string());
    }
};
}

namespace plantgen
{
    // global stack used for resolving relative filepaths
    // when including other json files as node properties / values
    // I should probably devise a better method of doing this, since
    // I don't think this will handle more than one level of inclusion
    // if the JSON files are not all in the same directory

    //FIXME make this not global
    std::stack<stdfs::path> include_dir_stack;
    std::unordered_map<stdfs::path, pregen_node_t> include_cache;

    std::vector<std::string> value_string_list_from_json_array(cJSON* json_array)
    {
        ASSERT(json_array, "");
        ASSERT(json_array->type == cJSON_Array, "json_array is not actually a JSON array");
        std::vector<std::string> values;

        cJSON* j = json_array->child;
        while(j)
        {
            if(j->type != cJSON_String)
            {
                throw json_type_exception(include_dir_stack.top(), *j, cJSON_String);
            }

            values.emplace_back(j->valuestring);
            j = j->next;
        }

        return values;
    }

    multi_value_t multi_value_from_json(cJSON* json)
    {
        ASSERT(str_eq(json->child->string, "Multi"), "Expected a \"Multi\" json_obj");
        ASSERT(json->child->type == cJSON_Number, "JSON Value of \"Multi\" should be an integer");

        multi_value_t v;
        v.num_to_pick = json->child->valueint;

        try {
            v.values = std::move(value_string_list_from_json_array(json->child->next));
        }
        catch (json_type_exception& je)
        {

            std::string s = "json type error: \"Multi\" only supports a value list of strings, not " + std::string(cJSON_type_strings[je.json_type_found]);
            throw std::runtime_error(std::move(s));
        }

        return v;
    }

    range_value_t range_value_from_json(cJSON* json)
    {
        ASSERT(str_eq(json->string, "Range"), "Expected a \"Range\" json_obj");
        return value_string_list_from_json_array(json);
    }

    weighted_value_t value_from_string(std::string const& value_string)
    {
        weighted_value_t v = value_string;

        if(value_string[0] == '%')
        {
            auto space_pos = value_string.find_first_of(' ');

            if(space_pos > 1)
            {
                v = value_string.substr(space_pos+1, std::string::npos);
                v.weight = std::stoi(value_string.substr(1, space_pos));
            }
            else
            {
                //TODO: better error message
                std::cout << "Invalid Weight Specifier for \"" << value_string << "\"\n";
            }
        }

        return v;
    }

    weighted_value_t value_type_from_json(cJSON* json)
    {
        if(json->type == cJSON_String)
        {
            return value_from_string(std::string(json->valuestring));
        }
        else if(!json->child)
        {
            EXPLODE("invalid value object %s", json->string);
            return null_value_t();
        }
        else if(str_eq(json->child->string, "Multi"))
        {
            return multi_value_from_json(json);
        }
        else if(str_eq(json->child->string, "Range"))
        {
            return range_value_from_json(json->child);
        }
        else
        {
            EXPLODE("unrecognized value object %s", json->child->string);
            return weighted_value_t(null_value_t());
        }
    }

    user_value_t user_value_from_json(cJSON const& json)
    {
        switch(json.type)
        {
            case cJSON_True:
                return user_value_t(bool(true));

            case cJSON_False:
                return user_value_t(bool(false));

            case cJSON_Number:
                return user_value_t(json.valuedouble);

            case cJSON_String:
                return user_value_t(std::string(json.valuestring));

            default:
                throw json_type_exception(include_dir_stack.top(), json,
                    {cJSON_True, cJSON_False, cJSON_Number, cJSON_String});
                break;
        };

        return nullptr;
    }

    user_data_node_t user_node_from_json(cJSON const& json)
    {
        user_data_node_t node;

        if(json.string)
            node.name = json.string;

        switch(json.type)
        {
            case cJSON_Object:
            case cJSON_Array:
            {
                cJSON* cur_child = json.child;
                while(cur_child)
                {
                    node.add_child(user_node_from_json(*cur_child));

                    cur_child = cur_child->next;
                }

                break;
            }

            default:
                node.value = user_value_from_json(json);
                break;
        }

        return node;
    }

    int weight_from_string(std::string const& weight_str)
    {
        if(weight_str[0] == '%')
        {
            if(weight_str.size() == 1)
            {
                return weight_inherit_code;
            }

            auto space_pos = weight_str.find_first_of(' ');

            if(space_pos > 1)
            {
                return std::stoi(weight_str.substr(1, space_pos));
            }
            else
            {
                //TODO: better error message
                std::cout << "Invalid Weight Specifier for \"" << weight_str << "\"\n";
            }
        }

        return -1;
    }

    pregen_node_t node_from_json(cJSON* json_node)
    {
        pregen_node_t node;

        cJSON* cur_child = json_node->child;
        while(cur_child)
        {
            if(str_eq(cur_child->string, "Name"))
            {
                node.name = cur_child->valuestring;
            }
            else if(str_eq(cur_child->string, "Properties"))
            {
                cJSON* property_json = cur_child->child;
                while(property_json)
                {
                    node.add_child(node_from_json(property_json));
                    property_json = property_json->next;
                }
            }
            else if(str_eq(cur_child->string, "Values"))
            {
                cJSON* value_json = cur_child->child;
                while(value_json)
                {
                    // if the value is a node, load it differently
                    // since we can't return a node as part of the variant

                    // is range or multi
                    bool is_value_type_node = value_json->type == cJSON_Object
                                           && value_json->child
                                           &&  (str_eq(value_json->child->string, "Range")
                                             || str_eq(value_json->child->string, "Multi"))
                                           ;

                    if(is_value_type_node || value_json->type != cJSON_Object)
                    {
                        node.value_nodes.emplace_back(value_type_from_json(value_json));
                    }
                    else
                    {
                        node.value_nodes.push_back(std::move(node_from_json(value_json)));
                    }

                    value_json = value_json->next;
                }
            }
            else if(str_eq(cur_child->string, "Include"))
            {
                ASSERT(cur_child->type == cJSON_String, "Include filepath must be a string");

                stdfs::path relpath(cur_child->valuestring);

                if(relpath.empty())
                {
                    throw std::runtime_error("Include path is empty for \"" + node.name + "\"");
                }

                auto parent_path = include_dir_stack.top().parent_path();
                stdfs::path fullpath = parent_path / relpath;

                try{
                    auto included_node = node_from_json(fullpath);

                    // if(included_node.name == node.name)
                    // {
                        auto prev_weight = node.weight;
                        node.merge_with(std::move(included_node));
                        node.weight = prev_weight;

                        /// TODO: check for existance of name value?
                        ///       as opposed to just checking for an empty name
                        if(node.name == "")
                        {
                            node.name = included_node.name;
                            node.sub_name = "";
                        }
                    // }
                    // else
                    // {
                    //     node.add_child(std::move(included_node));
                    // }
                }
                catch(file_not_found_exception const&)
                {
                    throw include_exception{include_dir_stack.top(), fullpath};
                }
            }
            else if(str_eq(cur_child->string, "Weight"))
            {
                switch(cur_child->type)
                {
                case cJSON_Number:
                    node.weight = cur_child->valueint;
                    break;

                case cJSON_String:
                {
                    int weight = weight_from_string(std::string(cur_child->valuestring));
                    if(weight >= 0 || weight == weight_inherit_code)
                    {
                        node.weight = weight;
                    }
                    else
                        std::cout << "Invalid Weight Specifier for \"" << node.name << "\"\n";

                    break;
                }

                default:
                    throw json_type_exception(include_dir_stack.top(), *cur_child,
                        {cJSON_Number, cJSON_String});
                }
            }
            else
            {
                node.user_data.add_child(user_node_from_json(*cur_child));
            }

            cur_child = cur_child->next;
        }

        //handle weight inhereit
        if(node.weight == weight_inherit_code)
        {
            node.weight = total_weight(node.value_nodes);
        }

        return node;
    }

    pregen_node_t node_from_json(stdfs::path const& _filepath)
    {
        auto filepath = stdfs::canonical(_filepath);

        if(!stdfs::is_regular_file(filepath))
            throw file_not_found_exception{filepath};

        auto canonical_path = stdfs::canonical(filepath);

        auto cached_node_entry = include_cache.find(canonical_path);
        if(cached_node_entry != include_cache.end())
        {
            return cached_node_entry->second;
        }
        else
        {
            //std::string json_str = asdf::util::read_text_file(filepath);
            std::string json_str = tired_of_build_issues::read_text_file(canonical_path.string());
            cJSON* json_root = cJSON_Parse(json_str.c_str());

            if(!json_root)
            {
                throw json_parse_exception(filepath, cJSON_GetErrorPtr());
            }

            include_dir_stack.push(canonical_path);
            auto node = node_from_json(json_root);
            cJSON_Delete(json_root);
            include_dir_stack.pop();

            include_cache.insert({canonical_path, node});

            return node;
        }
    }

    generated_node_t generate_node_from_json(stdfs::path const& filepath)
    {
        auto node = node_from_json(filepath);
        return generate_node(node);
    }

}<|endoftext|>


<commit_before>// Copyright eeGeo Ltd (2012-2015), All Rights Reserved

#include "AboutPageViewModel.h"

#include <sstream>
#include <iomanip>

namespace ExampleApp
{
    namespace AboutPage
    {
        namespace View
        {
            AboutPageViewModel::AboutPageViewModel(
                Eegeo::Helpers::TIdentity identity,
                Reaction::View::IReactionControllerModel& reactionControllerModel,
                const std::string& buildVersion,
                const std::string& platformVersion,
                const std::string& platformHash,
                const std::string& platformArchitecture,
                const std::string& aboutText,
                const std::string& appName)
                : m_openable(identity, reactionControllerModel)
                , m_buildVersion(buildVersion)
                , m_platformVersion(platformVersion)
                , m_platformHash(platformHash)
                , m_platformArchitecture(platformArchitecture)
                , m_aboutText(aboutText)
                , m_appName(appName)
                , m_indoorPositioningType("")
            {

            }

            AboutPageViewModel::~AboutPageViewModel()
            {

            }

            bool AboutPageViewModel::TryAcquireReactorControl()
            {
                return m_openable.TryAcquireReactorControl();
            }

            bool AboutPageViewModel::IsOpen() const
            {
                return m_openable.IsFullyOpen();
            }

            const std::string AboutPageViewModel::GetContent() const
            {
                std::stringstream content;

                content << m_aboutText
                        << "\n\nApplication build version: " + m_buildVersion
                        << "\n\nPlatform version: " + m_platformVersion
                        << "\nPlatform hash: " + m_platformHash
                        << "\nPlatform runtime arch: " + m_platformArchitecture
                        << "\nApplication Name: " + m_appName
                        << m_indoorPositioningType
                        << "\n";

                if(m_indoorPositioningType == "\nIndoor positioning type: Senion")
                {
                    content << "\n eeGeo Floor number: " << m_eegeoFloorNumber
                            << "\n Senion Floor number: " << m_senionFloorNumber
                            << "\n Latitude: " << std::setprecision(10) << m_senionLatitude
                            << "\n Longitude: " << m_senionLongitude
                            << "\n SenionApiKey: " << m_senionApiKey
                            << "\n SenionApiSecret: " << m_senionApiSecret
                            << "\n SenionFloorMap: " << m_senionFloorMapString.str()
                            << "\n SenionInteriorId: " << m_senionInteriorId
                            << "\n";
                }

                return content.str();
            }

            void AboutPageViewModel::Open()
            {
                if(!IsOpen())
                {
                    if(m_openable.Open())
                    {
                        m_openedCallbacks.ExecuteCallbacks();
                    }
                }
            }

            void AboutPageViewModel::Close()
            {
                if(IsOpen())
                {
                    {
                        const bool closed = m_openable.Close();
                        Eegeo_ASSERT(closed, "Failed to close");
                    }

                    m_closedCallbacks.ExecuteCallbacks();
                }
            }

            void AboutPageViewModel::UpdateApplicationName(const std::string& appName)
            {
                m_appName = appName;
            }

            OpenableControl::View::IOpenableControlViewModel& AboutPageViewModel::GetOpenableControl()
            {
                return m_openable;
            }

            void AboutPageViewModel::InsertOpenedCallback(Eegeo::Helpers::ICallback0& openedCallback)
            {
                m_openedCallbacks.AddCallback(openedCallback);
            }

            void AboutPageViewModel::RemoveOpenedCallback(Eegeo::Helpers::ICallback0& openedCallback)
            {
                m_openedCallbacks.RemoveCallback(openedCallback);
            }

            void AboutPageViewModel::InsertClosedCallback(Eegeo::Helpers::ICallback0& closedCallback)
            {
                m_closedCallbacks.AddCallback(closedCallback);
            }

            void AboutPageViewModel::RemoveClosedCallback(Eegeo::Helpers::ICallback0& closedCallback)
            {
                m_closedCallbacks.RemoveCallback(closedCallback);
            }

            void AboutPageViewModel::SetIndoorPositioningType(const std::string& indoorPositioningType)
            {
                m_indoorPositioningType = indoorPositioningType;
            }

            void AboutPageViewModel::SetSenionDataType(const int32_t& eegeoFloorNumber, const int& senionFloorNumber, const double& latitude, const double& longitude)
            {
                m_eegeoFloorNumber = eegeoFloorNumber;
                m_senionFloorNumber = senionFloorNumber;
                m_senionLatitude = latitude;
                m_senionLongitude = longitude;
            }

            void AboutPageViewModel::SetSenionSettingsType(const std::string& apiKey, const std::string& apiSecret, const std::map<int, std::string>& floorMap, const std::string& interiorId)
            {
                m_senionApiKey = apiKey;
                m_senionApiSecret = apiSecret;
                m_senionFloorMap = floorMap;
                m_senionInteriorId = interiorId;

                std::map<int, std::string> map = floorMap;

                for(std::map<int, std::string>::iterator it = map.begin(); it != map.end(); ++it)
                {
                    m_senionFloorMapString << it->second << "\n";
                }
            }
        }
    }
}
<commit_msg>Fix for MPLY-8264. Fixed the floor map show multiple instances of the same set of data. Buddy: Blair<commit_after>// Copyright eeGeo Ltd (2012-2015), All Rights Reserved

#include "AboutPageViewModel.h"

#include <sstream>
#include <iomanip>

namespace ExampleApp
{
    namespace AboutPage
    {
        namespace View
        {
            AboutPageViewModel::AboutPageViewModel(
                Eegeo::Helpers::TIdentity identity,
                Reaction::View::IReactionControllerModel& reactionControllerModel,
                const std::string& buildVersion,
                const std::string& platformVersion,
                const std::string& platformHash,
                const std::string& platformArchitecture,
                const std::string& aboutText,
                const std::string& appName)
                : m_openable(identity, reactionControllerModel)
                , m_buildVersion(buildVersion)
                , m_platformVersion(platformVersion)
                , m_platformHash(platformHash)
                , m_platformArchitecture(platformArchitecture)
                , m_aboutText(aboutText)
                , m_appName(appName)
                , m_indoorPositioningType("")
            {

            }

            AboutPageViewModel::~AboutPageViewModel()
            {

            }

            bool AboutPageViewModel::TryAcquireReactorControl()
            {
                return m_openable.TryAcquireReactorControl();
            }

            bool AboutPageViewModel::IsOpen() const
            {
                return m_openable.IsFullyOpen();
            }

            const std::string AboutPageViewModel::GetContent() const
            {
                std::stringstream content;

                content << m_aboutText
                        << "\n\nApplication build version: " + m_buildVersion
                        << "\n\nPlatform version: " + m_platformVersion
                        << "\nPlatform hash: " + m_platformHash
                        << "\nPlatform runtime arch: " + m_platformArchitecture
                        << "\nApplication Name: " + m_appName
                        << m_indoorPositioningType
                        << "\n";

                if(m_indoorPositioningType == "\nIndoor positioning type: Senion")
                {
                    content << "\n eeGeo Floor number: " << m_eegeoFloorNumber
                            << "\n Senion Floor number: " << m_senionFloorNumber
                            << "\n Latitude: " << std::setprecision(10) << m_senionLatitude
                            << "\n Longitude: " << m_senionLongitude
                            << "\n SenionApiKey: " << m_senionApiKey
                            << "\n SenionApiSecret: " << m_senionApiSecret
                            << "\n SenionFloorMap: " << m_senionFloorMapString.str()
                            << "\n SenionInteriorId: " << m_senionInteriorId
                            << "\n";
                }

                return content.str();
            }

            void AboutPageViewModel::Open()
            {
                if(!IsOpen())
                {
                    if(m_openable.Open())
                    {
                        m_openedCallbacks.ExecuteCallbacks();
                    }
                }
            }

            void AboutPageViewModel::Close()
            {
                if(IsOpen())
                {
                    {
                        const bool closed = m_openable.Close();
                        Eegeo_ASSERT(closed, "Failed to close");
                    }

                    m_closedCallbacks.ExecuteCallbacks();
                }
            }

            void AboutPageViewModel::UpdateApplicationName(const std::string& appName)
            {
                m_appName = appName;
            }

            OpenableControl::View::IOpenableControlViewModel& AboutPageViewModel::GetOpenableControl()
            {
                return m_openable;
            }

            void AboutPageViewModel::InsertOpenedCallback(Eegeo::Helpers::ICallback0& openedCallback)
            {
                m_openedCallbacks.AddCallback(openedCallback);
            }

            void AboutPageViewModel::RemoveOpenedCallback(Eegeo::Helpers::ICallback0& openedCallback)
            {
                m_openedCallbacks.RemoveCallback(openedCallback);
            }

            void AboutPageViewModel::InsertClosedCallback(Eegeo::Helpers::ICallback0& closedCallback)
            {
                m_closedCallbacks.AddCallback(closedCallback);
            }

            void AboutPageViewModel::RemoveClosedCallback(Eegeo::Helpers::ICallback0& closedCallback)
            {
                m_closedCallbacks.RemoveCallback(closedCallback);
            }

            void AboutPageViewModel::SetIndoorPositioningType(const std::string& indoorPositioningType)
            {
                m_indoorPositioningType = indoorPositioningType;
            }

            void AboutPageViewModel::SetSenionDataType(const int32_t& eegeoFloorNumber, const int& senionFloorNumber, const double& latitude, const double& longitude)
            {
                m_eegeoFloorNumber = eegeoFloorNumber;
                m_senionFloorNumber = senionFloorNumber;
                m_senionLatitude = latitude;
                m_senionLongitude = longitude;
            }

            void AboutPageViewModel::SetSenionSettingsType(const std::string& apiKey, const std::string& apiSecret, const std::map<int, std::string>& floorMap, const std::string& interiorId)
            {
                m_senionApiKey = apiKey;
                m_senionApiSecret = apiSecret;
                m_senionFloorMap = floorMap;
                m_senionInteriorId = interiorId;

                std::map<int, std::string> map = floorMap;

                m_senionFloorMapString.str(std::string());
                for(std::map<int, std::string>::iterator it = map.begin(); it != map.end(); ++it)
                {
                    m_senionFloorMapString << it->second << "\n";
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#include "SimpleInline.h"
#include "InlineHelper.h"
#include "Deleter.h"
#include "DexClass.h"
#include "DexInstruction.h"
#include "DexUtil.h"
#include "Resolver.h"
#include "Transform.h"
#include "walkers.h"
#include "ReachableClasses.h"
#include "Devirtualizer.h"

#include <algorithm>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>

namespace {

// the max number of callers we care to track explicitly, after that we
// group all callees/callers count in the same bucket
const int MAX_COUNT = 10;

DEBUG_ONLY bool method_breakup(
    std::vector<std::vector<DexMethod*>>& calls_group) {
  size_t size = calls_group.size();
  for (size_t i = 0; i < size; ++i) {
    size_t inst = 0;
    size_t stat = 0;
    auto group = calls_group[i];
    for (auto callee : group) {
      callee->get_access() & ACC_STATIC ? stat++ : inst++;
    }
    TRACE(SINL, 5, "%ld callers %ld: instance %ld, static %ld\n",
        i, group.size(), inst, stat);
  }
  return true;
}

std::unordered_set<DexType*> no_inline_annos(
  const std::vector<std::string>& annos,
  ConfigFiles& cfg
) {
  std::unordered_set<DexType*> no_inline;
  for (const auto& anno : cfg.get_no_optimizations_annos()) {
    no_inline.insert(anno);
  }
  for (auto const& no_inline_anno : annos) {
    auto type = DexType::get_type(
        DexString::get_string(no_inline_anno.c_str()));
    if (type != nullptr) {
      no_inline.insert(type);
    }
  }
  return no_inline;
}

template<typename DexMember>
bool has_anno(DexMember* m, const std::unordered_set<DexType*>& no_inline) {
  if (no_inline.size() == 0) return false;
  if (m != nullptr && m->get_anno_set() != nullptr) {
    for (const auto& anno : m->get_anno_set()->get_annotations()) {
      if (no_inline.count(anno->type()) > 0) {
        return true;
      }
    }
  }
  return false;
}

}

void SimpleInlinePass::run_pass(DexClassesVector& dexen, ConfigFiles& cfg) {
  const auto no_inline = no_inline_annos(m_no_inline_annos, cfg);

  auto scope = build_class_scope(dexen);
  // gather all inlinable candidates
  auto methods = gather_non_virtual_methods(scope, no_inline);
  select_single_called(scope, methods);

  auto resolver = [&](DexMethod* method, MethodSearch search) {
    return resolve_method(method, search, resolved_refs);
  };

  // inline candidates
  MultiMethodInliner inliner(scope, dexen[0], inlinable, resolver);
  inliner.inline_methods();

  // delete all methods that can be deleted
  auto inlined = inliner.get_inlined();
  size_t inlined_count = inlined.size();
  size_t deleted = delete_methods(scope, inlined, resolver);

  TRACE(SINL, 3, "recursive %ld\n", inliner.get_info().recursive);
  TRACE(SINL, 3, "invoke range %ld\n", inliner.get_info().invoke_range);
  TRACE(SINL, 3, "enum meths %ld\n", inliner.get_info().enum_callee);
  TRACE(SINL, 3, "more than 16 regs %ld\n",
      inliner.get_info().more_than_16regs);
  TRACE(SINL, 3, "try/catch in callee %ld\n",
      inliner.get_info().try_catch_block);
  TRACE(SINL, 3, "virtualizing methods %ld\n", inliner.get_info().need_vmethod);
  TRACE(SINL, 3, "invoke super %ld\n", inliner.get_info().invoke_super);
  TRACE(SINL, 3, "override inputs %ld\n", inliner.get_info().write_over_ins);
  TRACE(SINL, 3, "escaped virtual %ld\n", inliner.get_info().escaped_virtual);
  TRACE(SINL, 3, "known non public virtual %ld\n",
      inliner.get_info().non_pub_virtual);
  TRACE(SINL, 3, "non public ctor %ld\n", inliner.get_info().non_pub_ctor);
  TRACE(SINL, 3, "unknown field %ld\n", inliner.get_info().escaped_field);
  TRACE(SINL, 3, "non public field %ld\n", inliner.get_info().non_pub_field);
  TRACE(SINL, 3, "throws %ld\n", inliner.get_info().throws);
  TRACE(SINL, 3, "array data %ld\n", inliner.get_info().array_data);
  TRACE(SINL, 3, "multiple returns %ld\n", inliner.get_info().multi_ret);
  TRACE(SINL, 3, "reference outside of primary %ld\n",
      inliner.get_info().not_in_primary);
  TRACE(SINL, 3, "not found %ld\n", inliner.get_info().not_found);
  TRACE(SINL, 1,
      "%ld inlined calls over %ld methods and %ld methods removed\n",
      inliner.get_info().calls_inlined, inlined_count, deleted);
}

/**
 * Collect all non virtual methods and make all small methods candidates
 * for inlining.
 */
std::unordered_set<DexMethod*> SimpleInlinePass::gather_non_virtual_methods(
    Scope& scope, const std::unordered_set<DexType*>& no_inline) {
  // trace counter
  size_t all_methods = 0;
  size_t direct_methods = 0;
  size_t direct_no_code = 0;
  size_t non_virtual_no_code = 0;
  size_t clinit = 0;
  size_t init = 0;
  size_t static_methods = 0;
  size_t private_methods = 0;
  size_t dont_strip = 0;
  size_t no_inline_anno_count = 0;
  size_t non_virt_dont_strip = 0;
  size_t non_virt_methods = 0;

  // collect all non virtual methods (dmethods and vmethods)
  std::unordered_set<DexMethod*> methods;

  const auto can_inline_method = [&](DexMethod* meth, DexCode* code) {
    if (has_anno(type_class(meth->get_class()), no_inline) ||
        has_anno(meth, no_inline)) {
      no_inline_anno_count++;
      return;
    }
    if (code->get_instructions().size() < SMALL_CODE_SIZE) {
      // always inline small methods even if they are not deletable
      inlinable.insert(meth);
    } else {
      if (!can_delete(meth)) {
        // never inline methods that cannot be deleted
        TRACE(SINL, 4, "cannot_delete: %s\n", SHOW(meth));
        dont_strip++;
      } else {
        methods.insert(meth);
      }
    }
  };

  walk_methods(scope,
      [&](DexMethod* method) {
        all_methods++;
        if (method->is_virtual()) return;

        auto code = method->get_code();
        bool dont_inline = code == nullptr;

        direct_methods++;
        if (code == nullptr) direct_no_code++;
        if (is_constructor(method)) {
          (is_static(method)) ? clinit++ : init++;
          dont_inline = true;
        } else {
          (is_static(method)) ? static_methods++ : private_methods++;
        }

        if (dont_inline) return;

        can_inline_method(method, code);
      });
  if (m_virtual_inline) {
    auto non_virtual = devirtualize(scope);
    non_virt_methods = non_virtual.size();
    for (const auto& vmeth : non_virtual) {
      auto code = vmeth->get_code();
      if (code == nullptr) {
        non_virtual_no_code++;
        continue;
      }
      can_inline_method(vmeth, code);
    }
  }

  TRACE(SINL, 2, "All methods count: %ld\n", all_methods);
  TRACE(SINL, 2, "Direct methods count: %ld\n", direct_methods);
  TRACE(SINL, 2, "Virtual methods count: %ld\n", all_methods - direct_methods);
  TRACE(SINL, 2, "Direct methods no code: %ld\n", direct_no_code);
  TRACE(SINL, 2, "Direct methods with code: %ld\n",
      direct_methods - direct_no_code);
  TRACE(SINL, 2, "Constructors with or without code: %ld\n", init);
  TRACE(SINL, 2, "Static constructors: %ld\n", clinit);
  TRACE(SINL, 2, "Static methods: %ld\n", static_methods);
  TRACE(SINL, 2, "Private methods: %ld\n", private_methods);
  TRACE(SINL, 2, "Virtual methods non virtual count: %ld\n", non_virt_methods);
  TRACE(SINL, 2, "Non virtual no code count: %ld\n", non_virtual_no_code);
  TRACE(SINL, 2, "Non virtual no strip count: %ld\n", non_virt_dont_strip);
  TRACE(SINL, 2, "Small methods: %ld\n", inlinable.size());
  TRACE(SINL, 2, "Don't strip inlinable methods count: %ld\n", dont_strip);
  TRACE(SINL, 2, "Don't inline annotation count: %ld\n", no_inline_anno_count);
  return methods;
}

/**
 * Add to the list the single called.
 */
void SimpleInlinePass::select_single_called(
    Scope& scope, std::unordered_set<DexMethod*>& methods) {
  std::unordered_map<DexMethod*, int> calls;
  for (const auto& method : methods) {
    calls[method] = 0;
  }
  // count call sites for each method
  walk_opcodes(scope, [](DexMethod* meth) { return true; },
      [&](DexMethod* meth, DexInstruction* insn) {
        if (is_invoke(insn->opcode())) {
          auto mop = static_cast<DexOpcodeMethod*>(insn);
          auto callee = resolve_method(
              mop->get_method(), opcode_to_search(insn), resolved_refs);
          if (callee != nullptr && callee->is_concrete()
              && methods.count(callee) > 0) {
            calls[callee]++;
          }
        }
      });

  // pick methods with a single call site and add to candidates.
  // This vector usage is only because of logging we should remove it
  // once the optimization is "closed"
  std::vector<std::vector<DexMethod*>> calls_group(MAX_COUNT);
  for (auto call_it : calls) {
    if (call_it.second >= MAX_COUNT) {
      calls_group[MAX_COUNT - 1].push_back(call_it.first);
      continue;
    }
    calls_group[call_it.second].push_back(call_it.first);
  }
  assert(method_breakup(calls_group));
  for (auto callee : calls_group[1]) {
    inlinable.insert(callee);
  }
}
<commit_msg>Print try-catch-in-caller stats<commit_after>/**
 * Copyright (c) 2016-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#include "SimpleInline.h"
#include "InlineHelper.h"
#include "Deleter.h"
#include "DexClass.h"
#include "DexInstruction.h"
#include "DexUtil.h"
#include "Resolver.h"
#include "Transform.h"
#include "walkers.h"
#include "ReachableClasses.h"
#include "Devirtualizer.h"

#include <algorithm>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>

namespace {

// the max number of callers we care to track explicitly, after that we
// group all callees/callers count in the same bucket
const int MAX_COUNT = 10;

DEBUG_ONLY bool method_breakup(
    std::vector<std::vector<DexMethod*>>& calls_group) {
  size_t size = calls_group.size();
  for (size_t i = 0; i < size; ++i) {
    size_t inst = 0;
    size_t stat = 0;
    auto group = calls_group[i];
    for (auto callee : group) {
      callee->get_access() & ACC_STATIC ? stat++ : inst++;
    }
    TRACE(SINL, 5, "%ld callers %ld: instance %ld, static %ld\n",
        i, group.size(), inst, stat);
  }
  return true;
}

std::unordered_set<DexType*> no_inline_annos(
  const std::vector<std::string>& annos,
  ConfigFiles& cfg
) {
  std::unordered_set<DexType*> no_inline;
  for (const auto& anno : cfg.get_no_optimizations_annos()) {
    no_inline.insert(anno);
  }
  for (auto const& no_inline_anno : annos) {
    auto type = DexType::get_type(
        DexString::get_string(no_inline_anno.c_str()));
    if (type != nullptr) {
      no_inline.insert(type);
    }
  }
  return no_inline;
}

template<typename DexMember>
bool has_anno(DexMember* m, const std::unordered_set<DexType*>& no_inline) {
  if (no_inline.size() == 0) return false;
  if (m != nullptr && m->get_anno_set() != nullptr) {
    for (const auto& anno : m->get_anno_set()->get_annotations()) {
      if (no_inline.count(anno->type()) > 0) {
        return true;
      }
    }
  }
  return false;
}

}

void SimpleInlinePass::run_pass(DexClassesVector& dexen, ConfigFiles& cfg) {
  const auto no_inline = no_inline_annos(m_no_inline_annos, cfg);

  auto scope = build_class_scope(dexen);
  // gather all inlinable candidates
  auto methods = gather_non_virtual_methods(scope, no_inline);
  select_single_called(scope, methods);

  auto resolver = [&](DexMethod* method, MethodSearch search) {
    return resolve_method(method, search, resolved_refs);
  };

  // inline candidates
  MultiMethodInliner inliner(scope, dexen[0], inlinable, resolver);
  inliner.inline_methods();

  // delete all methods that can be deleted
  auto inlined = inliner.get_inlined();
  size_t inlined_count = inlined.size();
  size_t deleted = delete_methods(scope, inlined, resolver);

  TRACE(SINL, 3, "recursive %ld\n", inliner.get_info().recursive);
  TRACE(SINL, 3, "invoke range %ld\n", inliner.get_info().invoke_range);
  TRACE(SINL, 3, "enum meths %ld\n", inliner.get_info().enum_callee);
  TRACE(SINL, 3, "more than 16 regs %ld\n",
      inliner.get_info().more_than_16regs);
  TRACE(SINL, 3, "try/catch in callee %ld\n",
      inliner.get_info().try_catch_block);
  TRACE(SINL, 3, "try/catch in caller %ld\n",
      inliner.get_info().caller_tries);
  TRACE(SINL, 3, "virtualizing methods %ld\n", inliner.get_info().need_vmethod);
  TRACE(SINL, 3, "invoke super %ld\n", inliner.get_info().invoke_super);
  TRACE(SINL, 3, "override inputs %ld\n", inliner.get_info().write_over_ins);
  TRACE(SINL, 3, "escaped virtual %ld\n", inliner.get_info().escaped_virtual);
  TRACE(SINL, 3, "known non public virtual %ld\n",
      inliner.get_info().non_pub_virtual);
  TRACE(SINL, 3, "non public ctor %ld\n", inliner.get_info().non_pub_ctor);
  TRACE(SINL, 3, "unknown field %ld\n", inliner.get_info().escaped_field);
  TRACE(SINL, 3, "non public field %ld\n", inliner.get_info().non_pub_field);
  TRACE(SINL, 3, "throws %ld\n", inliner.get_info().throws);
  TRACE(SINL, 3, "array data %ld\n", inliner.get_info().array_data);
  TRACE(SINL, 3, "multiple returns %ld\n", inliner.get_info().multi_ret);
  TRACE(SINL, 3, "reference outside of primary %ld\n",
      inliner.get_info().not_in_primary);
  TRACE(SINL, 3, "not found %ld\n", inliner.get_info().not_found);
  TRACE(SINL, 1,
      "%ld inlined calls over %ld methods and %ld methods removed\n",
      inliner.get_info().calls_inlined, inlined_count, deleted);
}

/**
 * Collect all non virtual methods and make all small methods candidates
 * for inlining.
 */
std::unordered_set<DexMethod*> SimpleInlinePass::gather_non_virtual_methods(
    Scope& scope, const std::unordered_set<DexType*>& no_inline) {
  // trace counter
  size_t all_methods = 0;
  size_t direct_methods = 0;
  size_t direct_no_code = 0;
  size_t non_virtual_no_code = 0;
  size_t clinit = 0;
  size_t init = 0;
  size_t static_methods = 0;
  size_t private_methods = 0;
  size_t dont_strip = 0;
  size_t no_inline_anno_count = 0;
  size_t non_virt_dont_strip = 0;
  size_t non_virt_methods = 0;

  // collect all non virtual methods (dmethods and vmethods)
  std::unordered_set<DexMethod*> methods;

  const auto can_inline_method = [&](DexMethod* meth, DexCode* code) {
    if (has_anno(type_class(meth->get_class()), no_inline) ||
        has_anno(meth, no_inline)) {
      no_inline_anno_count++;
      return;
    }
    if (code->get_instructions().size() < SMALL_CODE_SIZE) {
      // always inline small methods even if they are not deletable
      inlinable.insert(meth);
    } else {
      if (!can_delete(meth)) {
        // never inline methods that cannot be deleted
        TRACE(SINL, 4, "cannot_delete: %s\n", SHOW(meth));
        dont_strip++;
      } else {
        methods.insert(meth);
      }
    }
  };

  walk_methods(scope,
      [&](DexMethod* method) {
        all_methods++;
        if (method->is_virtual()) return;

        auto code = method->get_code();
        bool dont_inline = code == nullptr;

        direct_methods++;
        if (code == nullptr) direct_no_code++;
        if (is_constructor(method)) {
          (is_static(method)) ? clinit++ : init++;
          dont_inline = true;
        } else {
          (is_static(method)) ? static_methods++ : private_methods++;
        }

        if (dont_inline) return;

        can_inline_method(method, code);
      });
  if (m_virtual_inline) {
    auto non_virtual = devirtualize(scope);
    non_virt_methods = non_virtual.size();
    for (const auto& vmeth : non_virtual) {
      auto code = vmeth->get_code();
      if (code == nullptr) {
        non_virtual_no_code++;
        continue;
      }
      can_inline_method(vmeth, code);
    }
  }

  TRACE(SINL, 2, "All methods count: %ld\n", all_methods);
  TRACE(SINL, 2, "Direct methods count: %ld\n", direct_methods);
  TRACE(SINL, 2, "Virtual methods count: %ld\n", all_methods - direct_methods);
  TRACE(SINL, 2, "Direct methods no code: %ld\n", direct_no_code);
  TRACE(SINL, 2, "Direct methods with code: %ld\n",
      direct_methods - direct_no_code);
  TRACE(SINL, 2, "Constructors with or without code: %ld\n", init);
  TRACE(SINL, 2, "Static constructors: %ld\n", clinit);
  TRACE(SINL, 2, "Static methods: %ld\n", static_methods);
  TRACE(SINL, 2, "Private methods: %ld\n", private_methods);
  TRACE(SINL, 2, "Virtual methods non virtual count: %ld\n", non_virt_methods);
  TRACE(SINL, 2, "Non virtual no code count: %ld\n", non_virtual_no_code);
  TRACE(SINL, 2, "Non virtual no strip count: %ld\n", non_virt_dont_strip);
  TRACE(SINL, 2, "Small methods: %ld\n", inlinable.size());
  TRACE(SINL, 2, "Don't strip inlinable methods count: %ld\n", dont_strip);
  TRACE(SINL, 2, "Don't inline annotation count: %ld\n", no_inline_anno_count);
  return methods;
}

/**
 * Add to the list the single called.
 */
void SimpleInlinePass::select_single_called(
    Scope& scope, std::unordered_set<DexMethod*>& methods) {
  std::unordered_map<DexMethod*, int> calls;
  for (const auto& method : methods) {
    calls[method] = 0;
  }
  // count call sites for each method
  walk_opcodes(scope, [](DexMethod* meth) { return true; },
      [&](DexMethod* meth, DexInstruction* insn) {
        if (is_invoke(insn->opcode())) {
          auto mop = static_cast<DexOpcodeMethod*>(insn);
          auto callee = resolve_method(
              mop->get_method(), opcode_to_search(insn), resolved_refs);
          if (callee != nullptr && callee->is_concrete()
              && methods.count(callee) > 0) {
            calls[callee]++;
          }
        }
      });

  // pick methods with a single call site and add to candidates.
  // This vector usage is only because of logging we should remove it
  // once the optimization is "closed"
  std::vector<std::vector<DexMethod*>> calls_group(MAX_COUNT);
  for (auto call_it : calls) {
    if (call_it.second >= MAX_COUNT) {
      calls_group[MAX_COUNT - 1].push_back(call_it.first);
      continue;
    }
    calls_group[call_it.second].push_back(call_it.first);
  }
  assert(method_breakup(calls_group));
  for (auto callee : calls_group[1]) {
    inlinable.insert(callee);
  }
}
<|endoftext|>


<commit_before>#include "parser.hpp"
#include "cvrp.hpp"
#include <iostream>
#include <algorithm>
#include <set>
#include <cmath>
#include <ctime>
#include <chrono>
#include <limits>
#include <utility>
#include <cstdlib>

namespace CVRP{
	class VNS{

	public:
		VNS(Instance);
		~VNS();
		Solution run();
		Solution vnd(Solution current_solution);
		Solution generate_initial_solution();
		double calc_cost_routes(Solution& solution);
		double calc_cost_route(Truck & truck);
		void calc_capacity(Solution& solution);
		void two_opt(Truck &truck);
		Truck two_opt_swap(Truck truck, int i, int k);
		Solution local_search(Solution &current_solution);
		Solution perturbation(Solution current_solution);

	private:
		Instance instance_;

	};
}<commit_msg>Fix | incluido random em vns.hpp<commit_after>#include "parser.hpp"
#include "cvrp.hpp"
#include <iostream>
#include <algorithm>
#include <set>
#include <cmath>
#include <random>
#include <ctime>
#include <chrono>
#include <limits>
#include <utility>
#include <cstdlib>

namespace CVRP{
	class VNS{

	public:
		VNS(Instance);
		~VNS();
		Solution run();
		Solution vnd(Solution current_solution);
		Solution generate_initial_solution();
		double calc_cost_routes(Solution& solution);
		double calc_cost_route(Truck & truck);
		void calc_capacity(Solution& solution);
		void two_opt(Truck &truck);
		Truck two_opt_swap(Truck truck, int i, int k);
		Solution local_search(Solution &current_solution);
		Solution perturbation(Solution current_solution);

	private:
		Instance instance_;

	};
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2019-2022 Diligent Graphics LLC
 *
 *  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.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#include "FileWrapper.hpp"
#include "RenderStateNotationParser.h"
#include "ParsingEnvironment.hpp"
#include "args.hxx"

using namespace Diligent;

enum class ParseStatus
{
    Success,
    SuccessHelp,
    Failed,
};

ParseStatus ParseCommandLine(int argc, char* argv[], ParsingEnvironmentCreateInfo& CreateInfo)
{
    args::ArgumentParser Parser{"DRSN Parser"};
    args::HelpFlag       Help(Parser, "help", "Help menu", {'h', "help"});

    args::ValueFlagList<std::string> ArgumentShaderDirs(Parser, "dir", "Shader Directory", {'s', "shader_dir"}, {});
    args::ValueFlagList<std::string> ArgumentRenderStateDirs(Parser, "dir", "Render State Directory", {'r', "render_state_dir"}, {});
    args::ValueFlagList<std::string> ArgumentInputs(Parser, "path", "Input render state notation files", {'i', "input"}, {}, args::Options::Required);
    args::ValueFlag<std::string>     ArgumentDeviceConfig(Parser, "path", "Path to Config", {'c', "config"}, "");
    args::ValueFlag<std::string>     ArgumentOutput(Parser, "path", "Output Binary Archive", {'o', "output"}, "Archive.bin");
    args::ValueFlag<std::string>     ArgumentDumpBytecode(Parser, "dir", "Dump Bytecode Directory", {'d', "dump_dir"}, "");
    args::ValueFlag<Uint32>          ArgumentThreadCount(Parser, "count", "Count of threads", {'t', "thread"}, 0);

    args::Group GroupDeviceFlags(Parser, "Device Flags:", args::Group::Validators::AtLeastOne);
    args::Flag  ArgumentDeviceFlagDx11(GroupDeviceFlags, "dx11", "D3D11", {"dx11"});
    args::Flag  ArgumentDeviceFlagDx12(GroupDeviceFlags, "dx12", "D3D12", {"dx12"});
    args::Flag  ArgumentDeviceFlagVulkan(GroupDeviceFlags, "vulkan", "Vulkan", {"vulkan"});
    args::Flag  ArgumentDeviceFlagOpenGL(GroupDeviceFlags, "opengl", "OpenGL", {"opengl"});
    args::Flag  ArgumentDeviceFlagOpenGLES(GroupDeviceFlags, "opengles", "OpenGLES", {"opengles"});
    args::Flag  ArgumentDeviceFlagMetalMacOS(GroupDeviceFlags, "metal_macos", "Metal_MacOS", {"metal_macos"});
    args::Flag  ArgumentDeviceFlagMetalIOS(GroupDeviceFlags, "metal_ios", "Metal_IOS", {"metal_ios"});

    args::Group ArchiveDeviceFlags(Parser, "Archive Flags:", args::Group::Validators::DontCare);
    args::Flag  ArgumentArchiveFlagStrip(ArchiveDeviceFlags, "strip_reflection", "Strip Shader Reflection", {"strip_reflection"});

    try
    {
        Parser.ParseCLI(argc, argv);
    }
    catch (const args::Help&)
    {
        LOG_INFO_MESSAGE(Parser.Help());
        return ParseStatus::SuccessHelp;
    }
    catch (const args::Error& e)
    {
        LOG_ERROR(e.what());
        LOG_INFO_MESSAGE(Parser.Help());
        return ParseStatus::Failed;
    }

    auto GetDeviceFlagsFromParser = [&]() //
    {
        ARCHIVE_DEVICE_DATA_FLAGS DeviceFlags = {};
        if (ArgumentDeviceFlagDx11)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_D3D11;
        if (ArgumentDeviceFlagDx12)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_D3D12;
        if (ArgumentDeviceFlagVulkan)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_VULKAN;
        if (ArgumentDeviceFlagOpenGL)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_GL;
        if (ArgumentDeviceFlagOpenGLES)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_GLES;
        if (ArgumentDeviceFlagMetalMacOS)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_METAL_MACOS;
        if (ArgumentDeviceFlagMetalIOS)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_METAL_IOS;
        return DeviceFlags;
    };

    CreateInfo.DeviceFlags     = GetDeviceFlagsFromParser();
    CreateInfo.PSOArchiveFlags = ArgumentArchiveFlagStrip ? PSO_ARCHIVE_FLAG_STRIP_REFLECTION : PSO_ARCHIVE_FLAG_NONE;
    CreateInfo.ShaderDirs      = args::get(ArgumentShaderDirs);
    CreateInfo.RenderStateDirs = args::get(ArgumentRenderStateDirs);
    CreateInfo.ConfigFilePath  = args::get(ArgumentDeviceConfig);
    CreateInfo.OuputFilePath   = args::get(ArgumentOutput);
    CreateInfo.InputFilePaths  = args::get(ArgumentInputs);
    CreateInfo.DumpBytecodeDir = args::get(ArgumentDumpBytecode);
    CreateInfo.ThreadCount     = args::get(ArgumentThreadCount);

    return ParseStatus::Success;
}

int main(int argc, char* argv[])
{
    ParsingEnvironmentCreateInfo EnvironmentCI{};

    switch (ParseCommandLine(argc, argv, EnvironmentCI))
    {
        case ParseStatus::Success:
            break;
        case ParseStatus::SuccessHelp:
            return EXIT_SUCCESS;
        case ParseStatus::Failed:
            LOG_FATAL_ERROR("Failed to parse command line");
            return EXIT_FAILURE;
        default:
            UNEXPECTED("Unexpected parse status");
            break;
    }

    auto pEnvironment = std::make_unique<ParsingEnvironment>(EnvironmentCI);
    if (!pEnvironment->Initialize())
    {
        LOG_FATAL_ERROR("Failed to initialize ParsingEnvironment");
        return EXIT_FAILURE;
    }

    auto pArchiveFactory = pEnvironment->GetArchiveFactory();
    auto pConverter      = pEnvironment->GetDeviceObjectConverter();

    RefCntAutoPtr<IArchiver> pArchive;
    pArchiveFactory->CreateArchiver(pEnvironment->GetSerializationDevice(), &pArchive);
    DEV_CHECK_ERR(pArchive != nullptr, "pArchive must not be null");

    auto const& OutputFilePath = EnvironmentCI.OuputFilePath;
    auto const& InputFilePaths = EnvironmentCI.InputFilePaths;

    if (!pConverter->ParseFiles(InputFilePaths))
    {
        LOG_FATAL_ERROR("Failed to parse files");
        return EXIT_FAILURE;
    }

    if (!pConverter->Execute(pArchive, EnvironmentCI.DumpBytecodeDir.empty() ? nullptr : EnvironmentCI.DumpBytecodeDir.c_str()))
    {
        LOG_FATAL_ERROR("Failed to archive");
        return EXIT_FAILURE;
    }

    RefCntAutoPtr<IDataBlob> pData;
    if (!pArchive->SerializeToBlob(&pData))
    {
        LOG_FATAL_ERROR("Failed to serialize to Data Blob");
        return EXIT_FAILURE;
    }

    FileWrapper File{OutputFilePath.c_str(), EFileAccessMode::Overwrite};
    if (!File)
    {
        LOG_FATAL_ERROR("Failed to open file: '", OutputFilePath, "'.");
        return EXIT_FAILURE;
    }

    File->Write(pData->GetDataPtr(), pData->GetSize());
}
<commit_msg>Render state packager: added no_signatures command line option<commit_after>/*
 *  Copyright 2019-2022 Diligent Graphics LLC
 *
 *  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.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#include "FileWrapper.hpp"
#include "RenderStateNotationParser.h"
#include "ParsingEnvironment.hpp"
#include "args.hxx"

using namespace Diligent;

enum class ParseStatus
{
    Success,
    SuccessHelp,
    Failed,
};

ParseStatus ParseCommandLine(int argc, char* argv[], ParsingEnvironmentCreateInfo& CreateInfo)
{
    args::ArgumentParser Parser{"DRSN Parser"};
    args::HelpFlag       Help(Parser, "help", "Help menu", {'h', "help"});

    args::ValueFlagList<std::string> ArgumentShaderDirs(Parser, "dir", "Shader directory", {'s', "shader_dir"}, {});
    args::ValueFlagList<std::string> ArgumentRenderStateDirs(Parser, "dir", "Render state directory", {'r', "render_state_dir"}, {});
    args::ValueFlagList<std::string> ArgumentInputs(Parser, "path", "Input render state notation files", {'i', "input"}, {}, args::Options::Required);
    args::ValueFlag<std::string>     ArgumentDeviceConfig(Parser, "path", "Path to the config file", {'c', "config"}, "");
    args::ValueFlag<std::string>     ArgumentOutput(Parser, "path", "Output binary archive", {'o', "output"}, "Archive.bin");
    args::ValueFlag<std::string>     ArgumentDumpBytecode(Parser, "dir", "Dump bytecode directory", {'d', "dump_dir"}, "");
    args::ValueFlag<Uint32>          ArgumentThreadCount(Parser, "count", "Count of threads", {'t', "thread"}, 0);

    args::Group GroupDeviceFlags(Parser, "Device Flags:", args::Group::Validators::AtLeastOne);
    args::Flag  ArgumentDeviceFlagDx11(GroupDeviceFlags, "dx11", "D3D11", {"dx11"});
    args::Flag  ArgumentDeviceFlagDx12(GroupDeviceFlags, "dx12", "D3D12", {"dx12"});
    args::Flag  ArgumentDeviceFlagVulkan(GroupDeviceFlags, "vulkan", "Vulkan", {"vulkan"});
    args::Flag  ArgumentDeviceFlagOpenGL(GroupDeviceFlags, "opengl", "OpenGL", {"opengl"});
    args::Flag  ArgumentDeviceFlagOpenGLES(GroupDeviceFlags, "opengles", "OpenGLES", {"opengles"});
    args::Flag  ArgumentDeviceFlagMetalMacOS(GroupDeviceFlags, "metal_macos", "Metal_MacOS", {"metal_macos"});
    args::Flag  ArgumentDeviceFlagMetalIOS(GroupDeviceFlags, "metal_ios", "Metal_IOS", {"metal_ios"});

    args::Group ArchiveDeviceFlags(Parser, "Archive Flags:", args::Group::Validators::DontCare);
    args::Flag  ArgumentArchiveFlagStrip(ArchiveDeviceFlags, "strip_reflection", "Strip shader reflection", {"strip_reflection"});
    args::Flag  ArgumentArchiveFlagNoSignatures(ArchiveDeviceFlags, "no_signatures", "Do not pack resource signatures", {"no_signatures"});

    try
    {
        Parser.ParseCLI(argc, argv);
    }
    catch (const args::Help&)
    {
        LOG_INFO_MESSAGE(Parser.Help());
        return ParseStatus::SuccessHelp;
    }
    catch (const args::Error& e)
    {
        LOG_ERROR(e.what());
        LOG_INFO_MESSAGE(Parser.Help());
        return ParseStatus::Failed;
    }

    auto GetDeviceFlagsFromParser = [&]() //
    {
        ARCHIVE_DEVICE_DATA_FLAGS DeviceFlags = {};
        if (ArgumentDeviceFlagDx11)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_D3D11;
        if (ArgumentDeviceFlagDx12)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_D3D12;
        if (ArgumentDeviceFlagVulkan)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_VULKAN;
        if (ArgumentDeviceFlagOpenGL)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_GL;
        if (ArgumentDeviceFlagOpenGLES)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_GLES;
        if (ArgumentDeviceFlagMetalMacOS)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_METAL_MACOS;
        if (ArgumentDeviceFlagMetalIOS)
            DeviceFlags |= ARCHIVE_DEVICE_DATA_FLAG_METAL_IOS;
        return DeviceFlags;
    };

    CreateInfo.DeviceFlags = GetDeviceFlagsFromParser();
    if (ArgumentArchiveFlagStrip)
        CreateInfo.PSOArchiveFlags |= PSO_ARCHIVE_FLAG_STRIP_REFLECTION;
    if (ArgumentArchiveFlagNoSignatures)
        CreateInfo.PSOArchiveFlags |= PSO_ARCHIVE_FLAG_DO_NOT_PACK_SIGNATURES;
    CreateInfo.ShaderDirs      = args::get(ArgumentShaderDirs);
    CreateInfo.RenderStateDirs = args::get(ArgumentRenderStateDirs);
    CreateInfo.ConfigFilePath  = args::get(ArgumentDeviceConfig);
    CreateInfo.OuputFilePath   = args::get(ArgumentOutput);
    CreateInfo.InputFilePaths  = args::get(ArgumentInputs);
    CreateInfo.DumpBytecodeDir = args::get(ArgumentDumpBytecode);
    CreateInfo.ThreadCount     = args::get(ArgumentThreadCount);

    return ParseStatus::Success;
}

int main(int argc, char* argv[])
{
    ParsingEnvironmentCreateInfo EnvironmentCI{};

    switch (ParseCommandLine(argc, argv, EnvironmentCI))
    {
        case ParseStatus::Success:
            break;
        case ParseStatus::SuccessHelp:
            return EXIT_SUCCESS;
        case ParseStatus::Failed:
            LOG_FATAL_ERROR("Failed to parse command line");
            return EXIT_FAILURE;
        default:
            UNEXPECTED("Unexpected parse status");
            break;
    }

    auto pEnvironment = std::make_unique<ParsingEnvironment>(EnvironmentCI);
    if (!pEnvironment->Initialize())
    {
        LOG_FATAL_ERROR("Failed to initialize ParsingEnvironment");
        return EXIT_FAILURE;
    }

    auto pArchiveFactory = pEnvironment->GetArchiveFactory();
    auto pConverter      = pEnvironment->GetDeviceObjectConverter();

    RefCntAutoPtr<IArchiver> pArchive;
    pArchiveFactory->CreateArchiver(pEnvironment->GetSerializationDevice(), &pArchive);
    DEV_CHECK_ERR(pArchive != nullptr, "pArchive must not be null");

    auto const& OutputFilePath = EnvironmentCI.OuputFilePath;
    auto const& InputFilePaths = EnvironmentCI.InputFilePaths;

    if (!pConverter->ParseFiles(InputFilePaths))
    {
        LOG_FATAL_ERROR("Failed to parse files");
        return EXIT_FAILURE;
    }

    if (!pConverter->Execute(pArchive, EnvironmentCI.DumpBytecodeDir.empty() ? nullptr : EnvironmentCI.DumpBytecodeDir.c_str()))
    {
        LOG_FATAL_ERROR("Failed to archive");
        return EXIT_FAILURE;
    }

    RefCntAutoPtr<IDataBlob> pData;
    if (!pArchive->SerializeToBlob(&pData))
    {
        LOG_FATAL_ERROR("Failed to serialize to Data Blob");
        return EXIT_FAILURE;
    }

    FileWrapper File{OutputFilePath.c_str(), EFileAccessMode::Overwrite};
    if (!File)
    {
        LOG_FATAL_ERROR("Failed to open file: '", OutputFilePath, "'.");
        return EXIT_FAILURE;
    }

    File->Write(pData->GetDataPtr(), pData->GetSize());
}
<|endoftext|>


<commit_before><commit_msg>Add example code to foo.cpp<commit_after>#include <iostream>

// A simple class with a constuctor and one method...

class Foo
{
    public:
        Foo(int);
        void bar();
    private:
        int val;
};

Foo::Foo(int n)
{
    val = n;
}

void Foo::bar()
{
    std::cout << "Value is " << val << std::endl;
}

// Define C functions for the C++ class - as ctypes can only talk to C...

extern "C"
{
    Foo* Foo_new(int n){return new Foo(n);}
    void Foo_bar(Foo* foo) {foo->bar();}
}

<|endoftext|>