<commit_before>#include "mpdatabase.h"

MpDatabase::MpDatabase()
{
   QStringList tables;
   //QSqlQuery q;
   db = QSqlDatabase::addDatabase("QSQLITE");
   db.setDatabaseName("SQLiteMpDatabase.db");

   if(!db.open()) {
      //throw something
      qDebug() << db.lastError();
   }

   tables = db.tables();
   q = QSqlQuery(db);

   q.exec("PRAGMA foreign_keys = ON"); //just to make sure the foreign key support is on

   if(!tables.contains("meals",Qt::CaseInsensitive)) {

      //may need to change the meals to just the date
      q.exec("create table meals(mid integer primary key, mdate text unique);");
   }
   if(!tables.contains("recipes",Qt::CaseInsensitive)) {
      q.exec("create table recipes(recid integer primary key, rname text unique, steps text);");
   }
   if(!tables.contains("ingredients",Qt::CaseInsensitive)) {
      q.exec("create table ingredients(ingid integer primary key, iname text unique,"
            "cal int, carbs int, fat int, protein int);");
   }

   //create relation table for recipe and ingredient

   q.exec("create table relate (rIdRelate int, iIdRelate int, "
         "foreign key (rIdRelate) references recipes(recid), "
         "foreign key (iIdRelate) references ingredients(ingid));");

   //create relation table for recipe and date
   //may need to change the meals relation if meals table is modified or removed

   q.exec("create table dateRecipeRelate (dnrmid int, dnrrid int, "
         "foreign key (dnrmid) references meals(mid),"
         "foreign key (dnrrid) references recipes(recid));");

   q.exec("create table steps (rId int, step text, "
         "foreign key (rId) references recipes(recid));");

}

MpDatabase& MpDatabase::GetDBInstance()
{
   static MpDatabase DB;
   return DB;
}

Ingredient MpDatabase::getIngredientByName(QString name)
{
   q.prepare("SELECT * FROM ingredients WHERE iname = :n");
   q.bindValue(":n",name);
   q.exec();
   q.next();
   Ingredient i(q.value(5).toInt(),q.value(4).toInt(),q.value(3).toInt(),q.value(2).toInt(),q.value(1).toString());
   return i;
}

Recipe MpDatabase::getRecipeByName(QString name)
{
   q.prepare("SELECT recid, rname, steps FROM recipes WHERE rname = :n");
   q.bindValue(":n",name);
   q.exec();
   q.next();

   QString tempSteps = q.value(2).toString();
   QString tempName = q.value(1).toString();

   QVector<QString> IngNames = getIngredientsByRecipe(name);
   QVector<Ingredient> Ings;

   foreach(QString s, IngNames.toList())
   {
      Ings.push_back(getIngredientByName(s));
   }

   Recipe r(Ings, tempSteps, tempName);
   return r;
}

QVector<QString> MpDatabase::getRecipeNames()
{

   QVector<QString> names;

   q.exec("SELECT rname FROM recipes;");

   while(q.next())
   {
      names.append(q.value(0).toString());
   }

   return names;
}

QVector<QString> MpDatabase::getIngredientNames()
{
   QVector<QString> names;
   //QSqlQuery q = QSqlQuery(db);
   q.exec("SELECT iname FROM ingredients;");
   while(q.next()) {
      names.append(q.value(0).toString());
   }
   return names;
}

QVector<Recipe> MpDatabase::getAllRecipe()
{
   QVector<QString> tempName(getRecipeNames());

   QVectorIterator<QString> tempNameIterator(tempName);

   QVector<Recipe> tempRecipe;

   while(tempNameIterator.hasNext())
   {
      tempRecipe.append(getRecipeByName(tempNameIterator.next()));
   }

   return tempRecipe;
}

   //-----------------------------------------------
   //-------adding into the database
   //-----------------------------------------------

void MpDatabase::addRecipe(const Recipe &recipe, const QString Date)
{
   QString tempRecipeId;

    q.prepare("SELECT recid FROM recipes where rname = :name;");
    q.bindValue(":name",recipe.RecipeName);
    q.exec();
    q.next();

   q.bindValue(":name", recipe.getName()); //name is private

   q.bindValue(":steps", recipe.GetDirections());

    updateMealRecipeRelation(Date, recipe.RecipeName);

    foreach(Ingredient i,recipe.IngredientsList.toList())
    {
        updateRecipeIngredientRelation(recipe.getName(),i.getName());
    }

   //updateMealRecipeRelation();

   q.prepare("SELECT recid FROM recipes where rname = :name;");
   q.bindValue(":name",recipe.RecipeName);
   q.exec();
   q.next();

   tempRecipeId=q.value(0).toString();

   addMeal(Date);

   updateMealRecipeRelation(Date, recipe.RecipeName);

   foreach(Ingredient i,recipe.IngredientsList.toList())
   {
      updateRecipeIngredientRelation(recipe.getName(),i.getName());
   }
}

void MpDatabase::addIngredient(const Ingredient &ingredient)
{

    //unique constraint has been added to the name column of the ingredient, to prevent duplication

   // QSqlQuery q = QSqlQuery(db);

    q.prepare("INSERT INTO ingredients(iname, cal, carbs, fat, protein) "
              "VALUES (:iname, :cal, :carbs, :fat, :protein)");

    //q.bindValue(":ingid", ingredient.id);
    q.bindValue(":iname", ingredient.getName());
    q.bindValue(":cal", ingredient.getCalories());
    q.bindValue(":carbs", ingredient.getCarbs());
    q.bindValue(":fat", ingredient.getFat());
    q.bindValue(":protein", ingredient.getProtein());
    q.exec();
}

void MpDatabase::addMeal(const QString &date)
{
   q.prepare("insert into meals (mdate) values (:date);");

   q.bindValue(":date", date);

   if(!q.exec())
   {

      qDebug() << q.lastError();

   }

}

//------------------------------------------------------------
//---------retriving from database using relational table
//-------------------------------------------------------------

QVector<QString> MpDatabase::getRecipesByIngredient(const QString &ing)
{

   QVector<QString> tempQueryResult;

   q.prepare("select rname from recipes where recid in "
         "(select rIdRelate from relate where iIdRelate in "
         "(select ingid from ingredients where iname = :ing));"); //rewrite the query using IN

   q.bindValue(":ing", ing);

   if(!q.exec())
   {
      qDebug() << "getRecipesByIngredient: " << q.lastError();
   }

   while(q.next())
   {
      tempQueryResult.append(q.value(0).toString());
   }

   return tempQueryResult;

}

//gets a list of ingredient name based on the recipe name
QVector<QString> MpDatabase::getIngredientsByRecipe(const QString &tempRecipeName)  //changed the type to ingredients from string
{
   QVector<QString> tempQueryResult;

   q.prepare("select iname from ingredients where ingid in "
         "(select iIdRelate from relate where rIdRelate in "
         "(select recid from recipes where rname = :name));"); //rewrite the query using IN

   q.bindValue(":name", tempRecipeName);

   if(!q.exec())
   {
      qDebug() << "getIngredientsByRecipe: " << q.lastError();
   }

   while(q.next())
   {
      tempQueryResult.append(q.value(0).toString());
   }

   return tempQueryResult;
}

//maybe consider returning an object of recipe
QVector<Recipe> MpDatabase::getRecipeByDate(const QString &date)
{
   // QSqlQuery q = QSqlQuery(db);

   QVector<QString> tempName;
   QVector<Recipe> tempRecipe;

   q.prepare("select rname from recipes where recid in "
         "(select dnrrid from dateRecipeRelate where dnrmid in "
         "(select mid from meals where mdate = :date));");

   q.bindValue(":date", date);

   if(!q.exec())
   {
      qDebug() << "getRecipeByDate: " << q.lastError();
   }

   while(q.next())
   {
      tempName.append(q.value(0).toString());
   }
   QVectorIterator<QString> tempNameIterator(tempName);

   while(tempNameIterator.hasNext())
   {
      tempRecipe.push_back(getRecipeByName(tempNameIterator.next()));
   }

   return tempRecipe;

}

//---------------------------------------------------------------
//----------updates for relational table
//----------------------------------------------------------------

void MpDatabase::updateRecipeIngredientRelation(const QString &recipeName, const QString &ingredientName)
{
   int recid = getRecipeIDByName(recipeName);
   int ingid = getIngredientIDByName(ingredientName);

   q.prepare("insert into relate (rIdRelate, iIdRelate) values (:rId, :iId);");
   q.bindValue(":rId", recid);
   q.bindValue(":iId", ingid);

   if(!q.exec())
   {
      qDebug() << "updateRecipeIngredientRelation: " << q.lastError();
   }

}

void MpDatabase::updateMealRecipeRelation(const QString &date, const QString &recipeName)
{
   int recid = getRecipeIDByName(recipeName);
   int mid = getMealIDByDate(date);

   qDebug() << recipeName << " " << date;
   qDebug() << recid << " " << mid;

   q.prepare("insert into dateRecipeRelate (dnrmid, dnrrid) values (:mid, :rid);");
   q.bindValue(":mid", mid);
   q.bindValue(":rid", recid);

   if(!q.exec())
   {
      qDebug() << "updateMealRecipeRelation: " << q.lastError();
   }

}

//-------------------------------------------------------------------
//-----------finding id's from names or date
//-------------------------------------------------------------------

int MpDatabase::getIngredientIDByName(const QString &ingredient)
{
   q.prepare("SELECT ingid FROM ingredients WHERE iname = :name;");
   q.bindValue(":name",ingredient);
   q.exec();
   q.next();
   return q.value(0).toInt();
}

int MpDatabase::getRecipeIDByName(const QString &recipe)
{
   q.prepare("SELECT recid FROM recipes WHERE rname = :name;");
   q.bindValue(":name",recipe);
   q.exec();
   q.next();
   return q.value(0).toInt();
}

int MpDatabase::getMealIDByDate(const QString &date)
{

   q.prepare("select mid from meals where mdate = :date;");

   q.bindValue(":date", date);

   if(!q.exec())
   {
      qDebug() << "getMealByDate: " << q.lastError();
   }

   q.next();

   qDebug() << "meal id: " << q.value(0).toInt();

   return q.value(0).toInt();
}
<commit_msg>some fix<commit_after>#include "mpdatabase.h"

MpDatabase::MpDatabase()
{
   QStringList tables;
   //QSqlQuery q;
   db = QSqlDatabase::addDatabase("QSQLITE");
   db.setDatabaseName("SQLiteMpDatabase.db");

   if(!db.open()) {
      //throw something
      qDebug() << db.lastError();
   }

   tables = db.tables();
   q = QSqlQuery(db);

   q.exec("PRAGMA foreign_keys = ON"); //just to make sure the foreign key support is on

   if(!tables.contains("meals",Qt::CaseInsensitive)) {

      //may need to change the meals to just the date
      q.exec("create table meals(mid integer primary key, mdate text unique);");
   }
   if(!tables.contains("recipes",Qt::CaseInsensitive)) {
      q.exec("create table recipes(recid integer primary key, rname text unique, steps text);");
   }
   if(!tables.contains("ingredients",Qt::CaseInsensitive)) {
      q.exec("create table ingredients(ingid integer primary key, iname text unique,"
            "cal int, carbs int, fat int, protein int);");
   }

   //create relation table for recipe and ingredient

   q.exec("create table relate (rIdRelate int, iIdRelate int, "
         "foreign key (rIdRelate) references recipes(recid), "
         "foreign key (iIdRelate) references ingredients(ingid));");

   //create relation table for recipe and date
   //may need to change the meals relation if meals table is modified or removed

   q.exec("create table dateRecipeRelate (dnrmid int, dnrrid int, "
         "foreign key (dnrmid) references meals(mid),"
         "foreign key (dnrrid) references recipes(recid));");

   q.exec("create table steps (rId int, step text, "
         "foreign key (rId) references recipes(recid));");

}

MpDatabase& MpDatabase::GetDBInstance()
{
   static MpDatabase DB;
   return DB;
}

Ingredient MpDatabase::getIngredientByName(QString name)
{
   q.prepare("SELECT * FROM ingredients WHERE iname = :n");
   q.bindValue(":n",name);
   q.exec();
   q.next();
   Ingredient i(q.value(5).toInt(),q.value(4).toInt(),q.value(3).toInt(),q.value(2).toInt(),q.value(1).toString());
   return i;
}

Recipe MpDatabase::getRecipeByName(QString name)
{
   q.prepare("SELECT recid, rname, steps FROM recipes WHERE rname = :n");
   q.bindValue(":n",name);
   q.exec();
   q.next();

   QString tempSteps = q.value(2).toString();
   QString tempName = q.value(1).toString();

   QVector<QString> IngNames = getIngredientsByRecipe(name);
   QVector<Ingredient> Ings;

   foreach(QString s, IngNames.toList())
   {
      Ings.push_back(getIngredientByName(s));
   }

   Recipe r(Ings, tempSteps, tempName);
   return r;
}

QVector<QString> MpDatabase::getRecipeNames()
{

   QVector<QString> names;

   q.exec("SELECT rname FROM recipes;");

   while(q.next())
   {
      names.append(q.value(0).toString());
   }

   return names;
}

QVector<QString> MpDatabase::getIngredientNames()
{
   QVector<QString> names;
   //QSqlQuery q = QSqlQuery(db);
   q.exec("SELECT iname FROM ingredients;");
   while(q.next()) {
      names.append(q.value(0).toString());
   }
   return names;
}

QVector<Recipe> MpDatabase::getAllRecipe()
{
   QVector<QString> tempName(getRecipeNames());

   QVectorIterator<QString> tempNameIterator(tempName);

   QVector<Recipe> tempRecipe;

   while(tempNameIterator.hasNext())
   {
      tempRecipe.append(getRecipeByName(tempNameIterator.next()));
   }

   return tempRecipe;
}

   //-----------------------------------------------
   //-------adding into the database
   //-----------------------------------------------

void MpDatabase::addRecipe(const Recipe &recipe, const QString Date)
{
   QString tempRecipeId;

    q.prepare("INSERT INTO recipes(rname, steps)"
              "VALUES (:name, :steps)");

    q.bindValue(":name", recipe.getName()); //name is private

    q.bindValue(":steps", recipe.GetDirections());

    if(!q.exec())
    {
        qDebug() << "addRecipe: " << q.lastError();
    }

    updateMealRecipeRelation(Date, recipe.RecipeName);

    foreach(Ingredient i,recipe.IngredientsList.toList())
    {
        updateRecipeIngredientRelation(recipe.getName(),i.getName());
    }

   //updateMealRecipeRelation();

   q.prepare("SELECT recid FROM recipes where rname = :name;");
   q.bindValue(":name",recipe.RecipeName);
   q.exec();
   q.next();

   tempRecipeId=q.value(0).toString();

   addMeal(Date);

   updateMealRecipeRelation(Date, recipe.RecipeName);

   foreach(Ingredient i,recipe.IngredientsList.toList())
   {
      updateRecipeIngredientRelation(recipe.getName(),i.getName());
   }
}

void MpDatabase::addIngredient(const Ingredient &ingredient)
{

    //unique constraint has been added to the name column of the ingredient, to prevent duplication

   // QSqlQuery q = QSqlQuery(db);

    q.prepare("INSERT INTO ingredients(iname, cal, carbs, fat, protein) "
              "VALUES (:iname, :cal, :carbs, :fat, :protein)");

    //q.bindValue(":ingid", ingredient.id);
    q.bindValue(":iname", ingredient.getName());
    q.bindValue(":cal", ingredient.getCalories());
    q.bindValue(":carbs", ingredient.getCarbs());
    q.bindValue(":fat", ingredient.getFat());
    q.bindValue(":protein", ingredient.getProtein());
    q.exec();
}

void MpDatabase::addMeal(const QString &date)
{
   q.prepare("insert into meals (mdate) values (:date);");

   q.bindValue(":date", date);

   if(!q.exec())
   {

      qDebug() << q.lastError();

   }

}

//------------------------------------------------------------
//---------retriving from database using relational table
//-------------------------------------------------------------

QVector<QString> MpDatabase::getRecipesByIngredient(const QString &ing)
{

   QVector<QString> tempQueryResult;

   q.prepare("select rname from recipes where recid in "
         "(select rIdRelate from relate where iIdRelate in "
         "(select ingid from ingredients where iname = :ing));"); //rewrite the query using IN

   q.bindValue(":ing", ing);

   if(!q.exec())
   {
      qDebug() << "getRecipesByIngredient: " << q.lastError();
   }

   while(q.next())
   {
      tempQueryResult.append(q.value(0).toString());
   }

   return tempQueryResult;

}

//gets a list of ingredient name based on the recipe name
QVector<QString> MpDatabase::getIngredientsByRecipe(const QString &tempRecipeName)  //changed the type to ingredients from string
{
   QVector<QString> tempQueryResult;

   q.prepare("select iname from ingredients where ingid in "
         "(select iIdRelate from relate where rIdRelate in "
         "(select recid from recipes where rname = :name));"); //rewrite the query using IN

   q.bindValue(":name", tempRecipeName);

   if(!q.exec())
   {
      qDebug() << "getIngredientsByRecipe: " << q.lastError();
   }

   while(q.next())
   {
      tempQueryResult.append(q.value(0).toString());
   }

   return tempQueryResult;
}

//maybe consider returning an object of recipe
QVector<Recipe> MpDatabase::getRecipeByDate(const QString &date)
{
   // QSqlQuery q = QSqlQuery(db);

   QVector<QString> tempName;
   QVector<Recipe> tempRecipe;

   q.prepare("select rname from recipes where recid in "
         "(select dnrrid from dateRecipeRelate where dnrmid in "
         "(select mid from meals where mdate = :date));");

   q.bindValue(":date", date);

   if(!q.exec())
   {
      qDebug() << "getRecipeByDate: " << q.lastError();
   }

   while(q.next())
   {
      tempName.append(q.value(0).toString());
   }
   QVectorIterator<QString> tempNameIterator(tempName);

   while(tempNameIterator.hasNext())
   {
      tempRecipe.push_back(getRecipeByName(tempNameIterator.next()));
   }

   return tempRecipe;

}

//---------------------------------------------------------------
//----------updates for relational table
//----------------------------------------------------------------

void MpDatabase::updateRecipeIngredientRelation(const QString &recipeName, const QString &ingredientName)
{
   int recid = getRecipeIDByName(recipeName);
   int ingid = getIngredientIDByName(ingredientName);

   q.prepare("insert into relate (rIdRelate, iIdRelate) values (:rId, :iId);");
   q.bindValue(":rId", recid);
   q.bindValue(":iId", ingid);

   if(!q.exec())
   {
      qDebug() << "updateRecipeIngredientRelation: " << q.lastError();
   }

}

void MpDatabase::updateMealRecipeRelation(const QString &date, const QString &recipeName)
{
   int recid = getRecipeIDByName(recipeName);
   int mid = getMealIDByDate(date);

   qDebug() << recipeName << " " << date;
   qDebug() << recid << " " << mid;

   q.prepare("insert into dateRecipeRelate (dnrmid, dnrrid) values (:mid, :rid);");
   q.bindValue(":mid", mid);
   q.bindValue(":rid", recid);

   if(!q.exec())
   {
      qDebug() << "updateMealRecipeRelation: " << q.lastError();
   }

}

//-------------------------------------------------------------------
//-----------finding id's from names or date
//-------------------------------------------------------------------

int MpDatabase::getIngredientIDByName(const QString &ingredient)
{
   q.prepare("SELECT ingid FROM ingredients WHERE iname = :name;");
   q.bindValue(":name",ingredient);
   q.exec();
   q.next();
   return q.value(0).toInt();
}

int MpDatabase::getRecipeIDByName(const QString &recipe)
{
   q.prepare("SELECT recid FROM recipes WHERE rname = :name;");
   q.bindValue(":name",recipe);
   q.exec();
   q.next();
   return q.value(0).toInt();
}

int MpDatabase::getMealIDByDate(const QString &date)
{

   q.prepare("select mid from meals where mdate = :date;");

   q.bindValue(":date", date);

   if(!q.exec())
   {
      qDebug() << "getMealByDate: " << q.lastError();
   }

   q.next();

   qDebug() << "meal id: " << q.value(0).toInt();

   return q.value(0).toInt();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: animationsetnode.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 15:31:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX
#define INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX

#include "animationbasenode.hxx"

namespace slideshow {
namespace internal {

class AnimationSetNode : public AnimationBaseNode
{
public:
    AnimationSetNode(
        ::com::sun::star::uno::Reference<
        ::com::sun::star::animations::XAnimationNode> const& xNode,
        ::boost::shared_ptr<BaseContainerNode> const& pParent,
        NodeContext const& rContext )
        : AnimationBaseNode( xNode, pParent, rContext ) {}

#if defined(VERBOSE) && defined(DBG_UTIL)
    virtual const char* getDescription() const { return "AnimationSetNode"; }
#endif

private:
    virtual AnimationActivitySharedPtr createActivity() const;
    void implScheduleDeactivationEvent();
};

} // namespace internal
} // namespace slideshow

#endif /* INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX */

<commit_msg>INTEGRATION: CWS changefileheader (1.6.74); FILE MERGED 2008/03/31 14:00:17 rt 1.6.74.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: animationsetnode.hxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX
#define INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX

#include "animationbasenode.hxx"

namespace slideshow {
namespace internal {

class AnimationSetNode : public AnimationBaseNode
{
public:
    AnimationSetNode(
        ::com::sun::star::uno::Reference<
        ::com::sun::star::animations::XAnimationNode> const& xNode,
        ::boost::shared_ptr<BaseContainerNode> const& pParent,
        NodeContext const& rContext )
        : AnimationBaseNode( xNode, pParent, rContext ) {}

#if defined(VERBOSE) && defined(DBG_UTIL)
    virtual const char* getDescription() const { return "AnimationSetNode"; }
#endif

private:
    virtual AnimationActivitySharedPtr createActivity() const;
    void implScheduleDeactivationEvent();
};

} // namespace internal
} // namespace slideshow

#endif /* INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX */

<|endoftext|>


<commit_before>#include "assign_bilinear_bases_dist.hxx"
#include "../../SDP.hxx"
#include "set_bases_blocks.hxx"

#include <boost/filesystem.hpp>

void read_blocks(const boost::filesystem::path &sdp_directory,
                 const El::Grid &grid, const Block_Info &block_info, SDP &sdp);
void read_objectives(const boost::filesystem::path &sdp_directory,
                     const El::Grid &grid, El::BigFloat &objective_const,
                     El::DistMatrix<El::BigFloat> &dual_objective_b);

SDP::SDP(const boost::filesystem::path &sdp_directory,
         const Block_Info &block_info, const El::Grid &grid)
{
  read_objectives(sdp_directory, grid, objective_const, dual_objective_b);
  read_blocks(sdp_directory, grid, block_info, *this);
}

SDP::SDP(const El::BigFloat &objective_const_input,
         const std::vector<El::BigFloat> &dual_objective_b_input,
         const std::vector<std::vector<El::BigFloat>> &primal_objective_c_input,
         const std::vector<El::Matrix<El::BigFloat>> &free_var_input,
         const Block_Info &block_info, const El::Grid &grid)
    : dual_objective_b(dual_objective_b_input.size(), 1, grid),
      yp_to_y(dual_objective_b_input.size(), dual_objective_b_input.size(),
              grid),
      objective_const(objective_const_input > 0 ? 1 : -1)
{
  El::Fill(dual_objective_b, El::BigFloat(1.0));

  auto &block_indices(block_info.block_indices);
  std::vector<El::Matrix<El::BigFloat>> bilinear_bases_local(
    2 * block_indices.size());
  for(size_t block(0); block != block_indices.size(); ++block)
    {
      bilinear_bases_local[2 * block].Resize(1, 1);
      bilinear_bases_local[2 * block + 1].Resize(0, 1);
      bilinear_bases_local[2 * block](0, 0) = 1;
    }
  assign_bilinear_bases_dist(bilinear_bases_local, grid, bilinear_bases);
  set_bases_blocks(block_info, bilinear_bases_local, bases_blocks, grid);

  for(size_t block(0); block != block_indices.size(); ++block)
    {
      primal_objective_c.blocks.emplace_back(
        primal_objective_c_input.at(block_indices.at(block)).size(), 1, grid);
      // TODO: copied from sdp_solve/SDP/SDP/read_primal_objective_c.cxx
      auto &primal_block(primal_objective_c.blocks.back());
      const size_t local_height(primal_block.LocalHeight());
      if(primal_block.GlobalCol(0) == 0)
        {
          for(size_t row = 0; row < local_height; ++row)
            {
              const size_t global_row(primal_block.GlobalRow(row));
              primal_block.SetLocal(
                row, 0,
                primal_objective_c_input.at(block_indices.at(block))
                  .at(global_row));
            }
        }
    }

  const int64_t B_Height([&]() {
    int64_t result(0);
    for(auto &block : primal_objective_c_input)
      {
        result += block.size();
      }
    return result;
  }());
  const int64_t B_Width(dual_objective_b.Height());
  El::DistMatrix<El::BigFloat> B(B_Height, B_Width, grid);

  const El::BigFloat objective_scale(El::Abs(objective_const_input));
  int64_t row_block(0);
  for(size_t block(0); block != block_indices.size(); ++block)
    {
      const int64_t block_height(
        free_var_input.at(block_indices.at(block)).Height()),
        block_width(free_var_input.at(block_indices.at(block)).Width());
      for(int64_t row_offset(0); row_offset != block_height; ++row_offset)
        {
          const size_t global_row(row_block + row_offset);
          for(int64_t global_column(0); global_column != block_width;
              ++global_column)
            {
              if(B.IsLocal(global_row, global_column))
                {
                  B.SetLocal(B.LocalRow(global_row), B.LocalCol(global_column),
                             free_var_input.at(block_indices.at(block))(
                               row_offset, global_column)
                               * (objective_scale
                                  / dual_objective_b_input[global_column]));
                }
            }
        }
      row_block += block_height;
    }

  El::DistMatrix<El::BigFloat> U(grid), s(grid), V(grid);
  El::SVD(B, U, s, V);

  for(int64_t row(0); row < s.LocalHeight(); ++row)
    {
      for(int64_t column(0); column < s.LocalWidth(); ++column)
        {
          s.SetLocal(row, column, 1 / s.GetLocal(row, column));
        }
    }
  El::Copy(V, yp_to_y);
  El::DiagonalScale(El::LeftOrRight::RIGHT, El::Orientation::NORMAL, s,
                    yp_to_y);

  El::DistMatrix<El::BigFloat> b_new(dual_objective_b);
  El::Gemv(El::Orientation::TRANSPOSE, El::BigFloat(1.0), yp_to_y, b_new,
           El::BigFloat(0.0), dual_objective_b);

  free_var_matrix.blocks.reserve(block_indices.size());
  int64_t global_row(0);
  for(size_t block(0); block != block_indices.size(); ++block)
    {
      free_var_matrix.blocks.emplace_back(
        free_var_input.at(block_indices.at(block)).Height(),
        free_var_input.at(block_indices.at(block)).Width(), grid);
      auto &free_var_block(free_var_matrix.blocks.back());
      for(int64_t row(0); row != free_var_block.Height(); ++row)
        {
          for(int64_t column(0); column != free_var_block.Width(); ++column)
            {
              if(free_var_block.IsLocal(row, column))
                {
                  free_var_block.SetLocal(free_var_block.LocalRow(row),
                                          free_var_block.LocalCol(column),
                                          U.Get(global_row, column));
                }
            }
          ++global_row;
        }
    }
}
<commit_msg>Remove copies and intermediate results in SDP()<commit_after>#include "assign_bilinear_bases_dist.hxx"
#include "../../SDP.hxx"
#include "set_bases_blocks.hxx"

#include <boost/filesystem.hpp>

void read_blocks(const boost::filesystem::path &sdp_directory,
                 const El::Grid &grid, const Block_Info &block_info, SDP &sdp);
void read_objectives(const boost::filesystem::path &sdp_directory,
                     const El::Grid &grid, El::BigFloat &objective_const,
                     El::DistMatrix<El::BigFloat> &dual_objective_b);

SDP::SDP(const boost::filesystem::path &sdp_directory,
         const Block_Info &block_info, const El::Grid &grid)
{
  read_objectives(sdp_directory, grid, objective_const, dual_objective_b);
  read_blocks(sdp_directory, grid, block_info, *this);
}

SDP::SDP(const El::BigFloat &objective_const_input,
         const std::vector<El::BigFloat> &dual_objective_b_input,
         const std::vector<std::vector<El::BigFloat>> &primal_objective_c_input,
         const std::vector<El::Matrix<El::BigFloat>> &free_var_input,
         const Block_Info &block_info, const El::Grid &grid)
    : dual_objective_b(dual_objective_b_input.size(), 1, grid), yp_to_y(grid),
      objective_const(objective_const_input > 0 ? 1 : -1)
{
  El::Fill(dual_objective_b, El::BigFloat(1.0));

  auto &block_indices(block_info.block_indices);
  std::vector<El::Matrix<El::BigFloat>> bilinear_bases_local(
    2 * block_indices.size());
  for(size_t block(0); block != block_indices.size(); ++block)
    {
      bilinear_bases_local[2 * block].Resize(1, 1);
      bilinear_bases_local[2 * block + 1].Resize(0, 1);
      bilinear_bases_local[2 * block](0, 0) = 1;
    }
  assign_bilinear_bases_dist(bilinear_bases_local, grid, bilinear_bases);
  set_bases_blocks(block_info, bilinear_bases_local, bases_blocks, grid);

  for(size_t block(0); block != block_indices.size(); ++block)
    {
      primal_objective_c.blocks.emplace_back(
        primal_objective_c_input.at(block_indices.at(block)).size(), 1, grid);
      // TODO: copied from sdp_solve/SDP/SDP/read_primal_objective_c.cxx
      auto &primal_block(primal_objective_c.blocks.back());
      const size_t local_height(primal_block.LocalHeight());
      if(primal_block.GlobalCol(0) == 0)
        {
          for(size_t row = 0; row < local_height; ++row)
            {
              const size_t global_row(primal_block.GlobalRow(row));
              primal_block.SetLocal(
                row, 0,
                primal_objective_c_input.at(block_indices.at(block))
                  .at(global_row));
            }
        }
    }

  const int64_t B_Height([&]() {
    int64_t result(0);
    for(auto &block : primal_objective_c_input)
      {
        result += block.size();
      }
    return result;
  }());
  const int64_t B_Width(dual_objective_b.Height());
  El::DistMatrix<El::BigFloat> B(B_Height, B_Width, grid);

  const El::BigFloat objective_scale(El::Abs(objective_const_input));
  int64_t row_block(0);
  for(size_t block(0); block != block_indices.size(); ++block)
    {
      const int64_t block_height(
        free_var_input.at(block_indices.at(block)).Height()),
        block_width(free_var_input.at(block_indices.at(block)).Width());
      for(int64_t row_offset(0); row_offset != block_height; ++row_offset)
        {
          const size_t global_row(row_block + row_offset);
          for(int64_t global_column(0); global_column != block_width;
              ++global_column)
            {
              if(B.IsLocal(global_row, global_column))
                {
                  B.SetLocal(B.LocalRow(global_row), B.LocalCol(global_column),
                             free_var_input.at(block_indices.at(block))(
                               row_offset, global_column)
                               * (objective_scale
                                  / dual_objective_b_input[global_column]));
                }
            }
        }
      row_block += block_height;
    }

  El::DistMatrix<El::BigFloat> U(grid);
  {
    El::DistMatrix<El::BigFloat> s(grid);
    El::SVD(B, U, s, yp_to_y);
    El::DiagonalSolve(El::LeftOrRight::RIGHT, El::Orientation::NORMAL, s,
                      yp_to_y);
  }
  {
    El::DistMatrix<El::BigFloat> b_new(dual_objective_b);
    El::Gemv(El::Orientation::TRANSPOSE, El::BigFloat(1.0), yp_to_y, b_new,
             El::BigFloat(0.0), dual_objective_b);
  }

  free_var_matrix.blocks.reserve(block_indices.size());
  int64_t global_row(0);
  for(size_t block(0); block != block_indices.size(); ++block)
    {
      free_var_matrix.blocks.emplace_back(
        free_var_input.at(block_indices.at(block)).Height(),
        free_var_input.at(block_indices.at(block)).Width(), grid);
      auto &free_var_block(free_var_matrix.blocks.back());
      for(int64_t row(0); row != free_var_block.Height(); ++row)
        {
          for(int64_t column(0); column != free_var_block.Width(); ++column)
            {
              if(free_var_block.IsLocal(row, column))
                {
                  free_var_block.SetLocal(free_var_block.LocalRow(row),
                                          free_var_block.LocalCol(column),
                                          U.Get(global_row, column));
                }
            }
          ++global_row;
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "Renderer.h"
#include "core/Engine.h"
#include "Texture.h"
#include "Shader.h"
#include "events/EventHandler.h"
#include "MeshBuffer.h"
#include "events/EventDispatcher.h"
#include "RenderTarget.h"
#include "BlendState.h"
#include "core/Window.h"

namespace ouzel
{
    namespace graphics
    {
        Renderer::Renderer(Driver pDriver):
            driver(pDriver), clearColor(0, 0, 0, 255)
        {

        }

        Renderer::~Renderer()
        {

        }

        void Renderer::free()
        {
            while (!activeDrawQueue.empty())
            {
                activeDrawQueue.pop();
            }

            ready = false;
        }

        bool Renderer::init(const WindowPtr& window,
                            uint32_t newSampleCount,
                            TextureFiltering newTextureFiltering,
                            float newTargetFPS,
                            bool newVerticalSync)
        {
            size = window->getSize();
            fullscreen = window->isFullscreen();
            sampleCount = newSampleCount;
            textureFiltering = newTextureFiltering;
            targetFPS = newTargetFPS;
            verticalSync = newVerticalSync;

            ready = true;

            return true;
        }

        bool Renderer::present()
        {
            return true;
        }

        void Renderer::setSize(const Size2& newSize)
        {
            size = newSize;
        }

        void Renderer::setFullscreen(bool newFullscreen)
        {
            fullscreen = newFullscreen;
        }

        std::vector<Size2> Renderer::getSupportedResolutions() const
        {
            return std::vector<Size2>();
        }

        BlendStatePtr Renderer::createBlendState()
        {
            BlendStatePtr blendState(new BlendState());
            return blendState;
        }

        TexturePtr Renderer::createTexture()
        {
            TexturePtr texture(new Texture());
            return texture;
        }

        RenderTargetPtr Renderer::createRenderTarget()
        {
            RenderTargetPtr renderTarget(new RenderTarget());
            return renderTarget;
        }

        ShaderPtr Renderer::createShader()
        {
            ShaderPtr shader(new Shader());
            return shader;
        }

        MeshBufferPtr Renderer::createMeshBuffer()
        {
            MeshBufferPtr meshBuffer(new MeshBuffer());
            return meshBuffer;
        }

        bool Renderer::addDrawCommand(const std::vector<TexturePtr>& textures,
                                      const ShaderPtr& shader,
                                      const std::vector<std::vector<float>>& pixelShaderConstants,
                                      const std::vector<std::vector<float>>& vertexShaderConstants,
                                      const BlendStatePtr& blendState,
                                      const MeshBufferPtr& meshBuffer,
                                      uint32_t indexCount,
                                      DrawMode drawMode,
                                      uint32_t startIndex,
                                      const RenderTargetPtr& renderTarget,
                                      bool scissorTestEnabled,
                                      const Rectangle& scissorTest)
        {
            activeDrawQueue.push({
                textures,
                shader,
                pixelShaderConstants,
                vertexShaderConstants,
                blendState,
                meshBuffer,
                (indexCount > 0) ? indexCount : meshBuffer->getIndexCount(),
                drawMode,
                startIndex,
                renderTarget,
                scissorTestEnabled,
                scissorTest
            });

            return true;
        }

        void Renderer::flushDrawCommands()
        {
            std::lock_guard<std::mutex> lock(drawQueueMutex);
            drawQueue = std::move(activeDrawQueue);
            drawCallCount = static_cast<uint32_t>(drawQueue.size());
        }

        Vector2 Renderer::viewToScreenLocation(const Vector2& position)
        {
            float x = 2.0f * position.x / size.width - 1.0f;
            float y = 2.0f * (size.height - position.y) / size.height - 1.0f;

            return Vector2(x, y);
        }

        Vector2 Renderer::viewToScreenRelativeLocation(const Vector2& position)
        {
            float x = 2.0f * position.x / size.width;
            float y = -2.0f * position.y / size.height;

            return Vector2(x, y);
        }

        Vector2 Renderer::screenToViewLocation(const Vector2& position)
        {
            float x = (position.x + 1.0f) / 2.0f * size.width;
            float y = size.height - (position.y + 1.0f) / 2.0f * size.height;

            return Vector2(x, y);
        }

        bool Renderer::saveScreenshot(const std::string& filename)
        {
            return true;
        }

        void Renderer::scheduleUpdate(const ResourcePtr& resource)
        {
            std::lock_guard<std::mutex> lock(updateMutex);

            auto i = updateSet.insert(resource);

            if (i.second)
            {
                updateQueue.push(resource);
            }
        }
    } // namespace graphics
} // namespace ouzel
<commit_msg>Remove unused attribute name from saveScreenshot<commit_after>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "Renderer.h"
#include "core/Engine.h"
#include "Texture.h"
#include "Shader.h"
#include "events/EventHandler.h"
#include "MeshBuffer.h"
#include "events/EventDispatcher.h"
#include "RenderTarget.h"
#include "BlendState.h"
#include "core/Window.h"

namespace ouzel
{
    namespace graphics
    {
        Renderer::Renderer(Driver pDriver):
            driver(pDriver), clearColor(0, 0, 0, 255)
        {

        }

        Renderer::~Renderer()
        {

        }

        void Renderer::free()
        {
            while (!activeDrawQueue.empty())
            {
                activeDrawQueue.pop();
            }

            ready = false;
        }

        bool Renderer::init(const WindowPtr& window,
                            uint32_t newSampleCount,
                            TextureFiltering newTextureFiltering,
                            float newTargetFPS,
                            bool newVerticalSync)
        {
            size = window->getSize();
            fullscreen = window->isFullscreen();
            sampleCount = newSampleCount;
            textureFiltering = newTextureFiltering;
            targetFPS = newTargetFPS;
            verticalSync = newVerticalSync;

            ready = true;

            return true;
        }

        bool Renderer::present()
        {
            return true;
        }

        void Renderer::setSize(const Size2& newSize)
        {
            size = newSize;
        }

        void Renderer::setFullscreen(bool newFullscreen)
        {
            fullscreen = newFullscreen;
        }

        std::vector<Size2> Renderer::getSupportedResolutions() const
        {
            return std::vector<Size2>();
        }

        BlendStatePtr Renderer::createBlendState()
        {
            BlendStatePtr blendState(new BlendState());
            return blendState;
        }

        TexturePtr Renderer::createTexture()
        {
            TexturePtr texture(new Texture());
            return texture;
        }

        RenderTargetPtr Renderer::createRenderTarget()
        {
            RenderTargetPtr renderTarget(new RenderTarget());
            return renderTarget;
        }

        ShaderPtr Renderer::createShader()
        {
            ShaderPtr shader(new Shader());
            return shader;
        }

        MeshBufferPtr Renderer::createMeshBuffer()
        {
            MeshBufferPtr meshBuffer(new MeshBuffer());
            return meshBuffer;
        }

        bool Renderer::addDrawCommand(const std::vector<TexturePtr>& textures,
                                      const ShaderPtr& shader,
                                      const std::vector<std::vector<float>>& pixelShaderConstants,
                                      const std::vector<std::vector<float>>& vertexShaderConstants,
                                      const BlendStatePtr& blendState,
                                      const MeshBufferPtr& meshBuffer,
                                      uint32_t indexCount,
                                      DrawMode drawMode,
                                      uint32_t startIndex,
                                      const RenderTargetPtr& renderTarget,
                                      bool scissorTestEnabled,
                                      const Rectangle& scissorTest)
        {
            activeDrawQueue.push({
                textures,
                shader,
                pixelShaderConstants,
                vertexShaderConstants,
                blendState,
                meshBuffer,
                (indexCount > 0) ? indexCount : meshBuffer->getIndexCount(),
                drawMode,
                startIndex,
                renderTarget,
                scissorTestEnabled,
                scissorTest
            });

            return true;
        }

        void Renderer::flushDrawCommands()
        {
            std::lock_guard<std::mutex> lock(drawQueueMutex);
            drawQueue = std::move(activeDrawQueue);
            drawCallCount = static_cast<uint32_t>(drawQueue.size());
        }

        Vector2 Renderer::viewToScreenLocation(const Vector2& position)
        {
            float x = 2.0f * position.x / size.width - 1.0f;
            float y = 2.0f * (size.height - position.y) / size.height - 1.0f;

            return Vector2(x, y);
        }

        Vector2 Renderer::viewToScreenRelativeLocation(const Vector2& position)
        {
            float x = 2.0f * position.x / size.width;
            float y = -2.0f * position.y / size.height;

            return Vector2(x, y);
        }

        Vector2 Renderer::screenToViewLocation(const Vector2& position)
        {
            float x = (position.x + 1.0f) / 2.0f * size.width;
            float y = size.height - (position.y + 1.0f) / 2.0f * size.height;

            return Vector2(x, y);
        }

        bool Renderer::saveScreenshot(const std::string&)
        {
            return true;
        }

        void Renderer::scheduleUpdate(const ResourcePtr& resource)
        {
            std::lock_guard<std::mutex> lock(updateMutex);

            auto i = updateSet.insert(resource);

            if (i.second)
            {
                updateQueue.push(resource);
            }
        }
    } // namespace graphics
} // namespace ouzel
<|endoftext|>


<commit_before>#include "./manager.hpp"

using namespace json;

regex JsonTree::lastTokenRgx = regex ("^(.*)(?:\\.)(.+)$");

JsonTree::JsonTree () :
  top (new ObjectMap())
{}

JsonTree::JsonTree (AbstractObject* root) {
  top = (ObjectMap*)root;
}

JsonTree::~JsonTree () {
  delete top;
}

void JsonTree::getterError (string path, AbstractObject* obj, int type) {
  cerr << "ERROR : ";
  if (obj == nullptr) {
    cerr << "Attempting to load the element " << path
         << " which does not exist."
         << " The default value will be returned " << endl;
  } else {
    cerr << "Attempting to load the element " << path
         << " as a "<< objectsTypesReverse[type] << " when is of type "
         << objectsTypesReverse[obj->getType()]
         << ". The default value will be returned " << endl;
  }
}

ObjectVector* JsonTree::createVec (vector<double> &array) {
  ObjectVector* object = new ObjectVector ();
  for (double number : array) {
    object->insert("", new ObjectFinalNumberFloat (number));
  }
  return object;
}

ObjectVector* JsonTree::createVec (vector<int> &array) {
  ObjectVector* object = new ObjectVector ();
  for (int number : array) {
    object->insert("", new ObjectFinalNumberInt (float(number)));
  }
  return object;
}

ObjectVector* JsonTree::createVec (vector<bool> &array) {
  ObjectVector* object = new ObjectVector ();
  for (bool boolean : array) {
    object->insert("", new ObjectFinalBool (boolean));
  }
  return object;
}

ObjectVector* JsonTree::createVec (vector<string> &array) {
  ObjectVector* object = new ObjectVector ();
  for (string word : array) {
    object->insert("", new ObjectFinalString (word));
  }
  return object;
}

vector <string> JsonTree::getKeys (string path) {
  AbstractObject* obj = top->get(path);
  if (obj != nullptr && obj->getType() == MAP) {
    return ((ObjectMap*)obj)->getKeys();
  } else {
    return vector<string> (0);
  }
}

int JsonTree::getSizeAt (string path) {
  AbstractObject* obj = top->get(path);
  if (obj != nullptr && obj->getType() == VECTOR) {
    return ((ObjectVector*)obj)->size();
  } else {
    return 0;
  }
}

string JsonTree::toText () {
  string txt;
  top->toTxt(txt, 0);
  return txt;
}

bool JsonTree::isNumber (string path) {
  return (isFloat(path) || isInt(path));
}

bool JsonTree::isFloat (string path) {
  return isType (top->get(path), NUMBER_FLOAT);
}

bool JsonTree::isInt (string path) {
  return isType (top->get(path), NUMBER_INT);
}

bool JsonTree::isBool (string path) {
  return isType (top->get(path), BOOL);
}

bool JsonTree::isString (string path) {
  return isType (top->get(path), STRING);
}

bool JsonTree::isMap (string path) {
  return isType (top->get(path), MAP);
}

bool JsonTree::isVector (string path) {
  return isType (top->get(path), VECTOR);
}

bool JsonTree::isType (AbstractObject* obj, int type) {
  return (obj != nullptr && obj->getType() == type);
}

bool JsonTree::exist (string path) {
  return top->get(path) != nullptr;
}

int JsonTree::getType(string path) {
  AbstractObject* obj = top->get(path);
  if (obj != nullptr)
    return obj->getType();
  else
    return -1;
}

// FINALS

bool JsonTree::get (bool &to, string path) {
  AbstractObject* obj = top->get(path);
  if (isType(obj, BOOL)) {
    to = ((ObjectFinalBool*)obj)->getContent();
    return true;
  }
  getterError(path, obj, BOOL);
  return false;
}

bool JsonTree::get (string &to, string path) {
  AbstractObject* obj = top->get(path);
  if (isType(obj, STRING)) {
    to = ((ObjectFinalString*)obj)->getContent();
    return true;
  }
  getterError(path, obj, STRING);
  return false;
}

bool JsonTree::get (double &to, string path) {
  AbstractObject* obj = top->get(path);
  if (isType(obj, NUMBER_INT)) {
    to = ((ObjectFinalNumberInt*)obj)->getContent();
    return true;
  }
  if (isType(obj, NUMBER_FLOAT)) {
    to = ((ObjectFinalNumberFloat*)obj)->getContent();
    return true;
  }
  getterError(path, obj, NUMBER_FLOAT);
  return false;
}

bool JsonTree::get (float &to, string path) {
  AbstractObject* obj = top->get(path);
  if (isType(obj, NUMBER_INT)) {
    to = ((ObjectFinalNumberInt*)obj)->getContent();
    return true;
  }
  if (isType(obj, NUMBER_FLOAT)) {
    to = ((ObjectFinalNumberFloat*)obj)->getContent();
    return true;
  }
  getterError(path, obj, NUMBER_FLOAT);
  return false;
}

bool JsonTree::get (int &to, string path) {
  AbstractObject* obj = top->get(path);
  if (isType(obj, NUMBER_INT)) {
    to = ((ObjectFinalNumberInt*)obj)->getContent();
    return true;
  }
  if (isType(obj, NUMBER_FLOAT)) {
    to = ((ObjectFinalNumberFloat*)obj)->getContent();
    return true;
  }
  getterError(path, obj, NUMBER_INT);
  return false;
}

// VECTORS

bool JsonTree::get (vector<double>& array, string path) {
  AbstractObject* obj = top->get(path);
  if (isType (obj, VECTOR)) {
    ObjectVector* vect = (ObjectVector*)obj;
    int size = vect->size();
    array.resize (size);
    for (int i = 0; i < size; i++) {
      if (((ObjectFinalNumberFloat*)vect->operator[](i))->getType() == NUMBER_FLOAT)
        array[i] = int(((ObjectFinalNumberFloat*)vect->operator[](i))->getContent());
      else if (((ObjectFinalNumberInt*)vect->operator[](i))->getType() == NUMBER_INT)
        array[i] = int(((ObjectFinalNumberInt*)vect->operator[](i))->getContent());
      else {
        getterError(path, obj, VECTOR);
        return false;
      }
    }
    return true;
  }
  getterError(path, obj, VECTOR);
  return false;
}

bool JsonTree::get (vector<int>& array, string path) {
  AbstractObject* obj = top->get(path);
  if (isType (obj, VECTOR)) {
    ObjectVector* vect = (ObjectVector*)obj;
    int size = vect->size();
    array.resize (size);
    for (int i = 0; i < size; i++) {
      if (((ObjectFinalNumberFloat*)vect->operator[](i))->getType() == NUMBER_FLOAT)
        array[i] = int(((ObjectFinalNumberFloat*)vect->operator[](i))->getContent());
      else if (((ObjectFinalNumberInt*)vect->operator[](i))->getType() == NUMBER_INT)
        array[i] = int(((ObjectFinalNumberInt*)vect->operator[](i))->getContent());
      else {
        getterError(path, obj, VECTOR);
        return false;
      }
    }
    return true;
  }
  getterError(path, obj, VECTOR);
  return false;
}

bool JsonTree::get (vector<string>& array, string path) {
  AbstractObject* obj = top->get(path);
  if (isType (obj, VECTOR)) {
    ObjectVector* vect = (ObjectVector*)obj;
    int size = vect->size();
    array.resize (size);
    for (int i = 0; i < size; i++) {
      if (((ObjectFinalString*)vect->operator[](i))->getType() == STRING)
        array[i] = ((ObjectFinalString*)vect->operator[](i))->getContent();
      else {
        getterError(path, obj, VECTOR);
        return false;
      }
    }
    return true;
  }
  getterError(path, obj, VECTOR);
  return false;
}

bool JsonTree::get (vector<bool>& array, string path) {
  AbstractObject* obj = top->get(path);
  if (isType (obj, VECTOR)) {
    ObjectVector* vect = (ObjectVector*)obj;
    int size = vect->size();
    array.resize (size);
    for (int i = 0; i < size; i++) {
      if (((ObjectFinalBool*)vect->operator[](i))->getType() == BOOL)
        array[i] = ((ObjectFinalBool*)vect->operator[](i))->getContent();
      else {
        getterError(path, obj, VECTOR);
        return false;
      }
    }
    return true;
  }
  getterError(path, obj, VECTOR);
  return false;
}

AbstractObject* JsonTree::insertObject(string path, AbstractObject *obj) {
  return nullptr;
}

// ADD

bool JsonTree::add (double value, string path) {
  AbstractObject* object = new ObjectFinalNumberFloat (value);
  return top->add (path, object);
};

bool JsonTree::add (float value, string path) {
  return add (double(value), path);
};

bool JsonTree::add (int value, string path) {
  AbstractObject* object = new ObjectFinalNumberInt (value);
  return top->add (path, object);
};

bool JsonTree::add (bool value, string path) {
  AbstractObject* object = new ObjectFinalBool (value);
  return top->add (path, object);
};

bool JsonTree::add (string value, string path) {
  AbstractObject* object = new ObjectFinalString (value);
  return top->add (path, object);
};

bool JsonTree::add (const char* value, string path) {
  return add (string(value), path);
};

bool JsonTree::add (vector<double> &array, string path) {
  return top->add (path, createVec(array));
}

bool JsonTree::add (vector<int> &array, string path) {
  return top->add (path, createVec(array));
}

bool JsonTree::add (vector<bool> &array, string path) {
  return top->add (path, createVec(array));
}

bool JsonTree::add (vector<string> &array, string path) {
  return top->add (path, createVec(array));
}

bool JsonTree::addMap (string path) {
  return top->add (path, new ObjectMap ());
}

bool JsonTree::addVector (string path) {
  return top->add (path, new ObjectVector ());
}

// REPLACE

bool JsonTree::replace (AbstractObject *newObj, string path) {
  smatch matcher;
  if (regex_search (path, matcher, lastTokenRgx)) {
      AbstractObject* father = top->get (matcher[1]);
      if (father != nullptr && father->getType() == MAP)
        return ((ObjectMap*)father)->replace (matcher[2], newObj);
      return false;
  } else if (!path.empty()) {
    return ((ObjectMap*)top)->replace (path, newObj);
  }
  return false;
}

bool JsonTree::replace (double from, string path) {
  AbstractObject* object = new ObjectFinalNumberFloat (from);
  if(replace (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::replace (float from, string path) {
  return replace (double(from), path);
}

bool JsonTree::replace (int from, string path) {
  AbstractObject* object = new ObjectFinalNumberInt (from);
  if(replace (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::replace (bool from, string path) {
  AbstractObject* object = new ObjectFinalBool (from);
  if(replace (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::replace (string from, string path) {
  AbstractObject* object = new ObjectFinalString (from);
  if(replace (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::replace (const char* from, string path) {
  return replace (string(from), path);
}

bool JsonTree::replace (vector<double>& array, string path) {
  return replace (createVec (array), path);
}

bool JsonTree::replace (vector<int>& array, string path) {
  return replace (createVec (array), path);
}

bool JsonTree::replace (vector<bool>& array, string path) {
  return replace (createVec (array), path);
}

bool JsonTree::replace (vector<string>& array, string path) {
  return replace (createVec (array), path);
}

// SET

bool JsonTree::set(AbstractObject *newObj, string path) {
  if (exist (path))
    return replace (newObj, path);
  else
    return top->add (path, newObj);
}

bool JsonTree::set (double from, string path) {
  AbstractObject* object = new ObjectFinalNumberFloat (from);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::set (float from, string path) {
  return set (double(from), path);
}

bool JsonTree::set (int from, string path) {
  AbstractObject* object = new ObjectFinalNumberInt (from);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::set (bool from, string path) {
  AbstractObject* object = new ObjectFinalBool (from);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::set (string value, string path) {
  AbstractObject* object = new ObjectFinalString (value);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::set(const char *value, string path) {
  return set (string(value), path);
}

bool JsonTree::set (vector<double>& array, string path) {
  return set (createVec (array), path);
}

bool JsonTree::set (vector<int>& array, string path) {
  return set (createVec (array), path);
}

bool JsonTree::set (vector<bool>& array, string path) {
  return set (createVec (array), path);
}

bool JsonTree::set (vector<string>& array, string path) {
  return set (createVec (array), path);
}

// ERASE

bool JsonTree::erase (string path) {
  smatch matcher;
  if (regex_search (path, matcher, lastTokenRgx)) {
      AbstractObject* father = top->get (matcher[1]);
      if (father != nullptr && father->getType() == MAP)
        return ((ObjectMap*)father)->erase (matcher[2]);
      return false;
  } else if (!path.empty())
    return ((ObjectMap*)top)->erase (path);
  return false;
}

// REMOVE

bool JsonTree::remove (string path) {
  smatch matcher;
  if (regex_search (path, matcher, lastTokenRgx)) {
      AbstractObject* father = top->get (matcher[1]);
      if (father != nullptr && father->getType() == MAP)
        return ((ObjectMap*)father)->remove (matcher[2]);
      return true;
  } else if (!path.empty())
    return ((ObjectMap*)top)->erase (path);
  return false;
}
<commit_msg>Memory leaks solved<commit_after>#include "./manager.hpp"

using namespace json;

regex JsonTree::lastTokenRgx = regex ("^(.*)(?:\\.)(.+)$");

JsonTree::JsonTree () :
  top (new ObjectMap())
{}

JsonTree::JsonTree (AbstractObject* root) {
  top = (ObjectMap*)root;
}

JsonTree::~JsonTree () {
  delete top;
}

void JsonTree::getterError (string path, AbstractObject* obj, int type) {
  cerr << "ERROR : ";
  if (obj == nullptr) {
    cerr << "Attempting to load the element " << path
         << " which does not exist."
         << " The default value will be returned " << endl;
  } else {
    cerr << "Attempting to load the element " << path
         << " as a "<< objectsTypesReverse[type] << " when is of type "
         << objectsTypesReverse[obj->getType()]
         << ". The default value will be returned " << endl;
  }
}

ObjectVector* JsonTree::createVec (vector<double> &array) {
  ObjectVector* object = new ObjectVector ();
  for (double number : array) {
    object->insert("", new ObjectFinalNumberFloat (number));
  }
  return object;
}

ObjectVector* JsonTree::createVec (vector<int> &array) {
  ObjectVector* object = new ObjectVector ();
  for (int number : array) {
    object->insert("", new ObjectFinalNumberInt (float(number)));
  }
  return object;
}

ObjectVector* JsonTree::createVec (vector<bool> &array) {
  ObjectVector* object = new ObjectVector ();
  for (bool boolean : array) {
    object->insert("", new ObjectFinalBool (boolean));
  }
  return object;
}

ObjectVector* JsonTree::createVec (vector<string> &array) {
  ObjectVector* object = new ObjectVector ();
  for (string word : array) {
    object->insert("", new ObjectFinalString (word));
  }
  return object;
}

vector <string> JsonTree::getKeys (string path) {
  AbstractObject* obj = top->get(path);
  if (obj != nullptr && obj->getType() == MAP) {
    return ((ObjectMap*)obj)->getKeys();
  } else {
    return vector<string> (0);
  }
}

int JsonTree::getSizeAt (string path) {
  AbstractObject* obj = top->get(path);
  if (obj != nullptr && obj->getType() == VECTOR) {
    return ((ObjectVector*)obj)->size();
  } else {
    return 0;
  }
}

string JsonTree::toText () {
  string txt;
  top->toTxt(txt, 0);
  return txt;
}

bool JsonTree::isNumber (string path) {
  return (isFloat(path) || isInt(path));
}

bool JsonTree::isFloat (string path) {
  return isType (top->get(path), NUMBER_FLOAT);
}

bool JsonTree::isInt (string path) {
  return isType (top->get(path), NUMBER_INT);
}

bool JsonTree::isBool (string path) {
  return isType (top->get(path), BOOL);
}

bool JsonTree::isString (string path) {
  return isType (top->get(path), STRING);
}

bool JsonTree::isMap (string path) {
  return isType (top->get(path), MAP);
}

bool JsonTree::isVector (string path) {
  return isType (top->get(path), VECTOR);
}

bool JsonTree::isType (AbstractObject* obj, int type) {
  return (obj != nullptr && obj->getType() == type);
}

bool JsonTree::exist (string path) {
  return top->get(path) != nullptr;
}

int JsonTree::getType(string path) {
  AbstractObject* obj = top->get(path);
  if (obj != nullptr)
    return obj->getType();
  else
    return -1;
}

// FINALS

bool JsonTree::get (bool &to, string path) {
  AbstractObject* obj = top->get(path);
  if (isType(obj, BOOL)) {
    to = ((ObjectFinalBool*)obj)->getContent();
    return true;
  }
  getterError(path, obj, BOOL);
  return false;
}

bool JsonTree::get (string &to, string path) {
  AbstractObject* obj = top->get(path);
  if (isType(obj, STRING)) {
    to = ((ObjectFinalString*)obj)->getContent();
    return true;
  }
  getterError(path, obj, STRING);
  return false;
}

bool JsonTree::get (double &to, string path) {
  AbstractObject* obj = top->get(path);
  if (isType(obj, NUMBER_INT)) {
    to = ((ObjectFinalNumberInt*)obj)->getContent();
    return true;
  }
  if (isType(obj, NUMBER_FLOAT)) {
    to = ((ObjectFinalNumberFloat*)obj)->getContent();
    return true;
  }
  getterError(path, obj, NUMBER_FLOAT);
  return false;
}

bool JsonTree::get (float &to, string path) {
  AbstractObject* obj = top->get(path);
  if (isType(obj, NUMBER_INT)) {
    to = ((ObjectFinalNumberInt*)obj)->getContent();
    return true;
  }
  if (isType(obj, NUMBER_FLOAT)) {
    to = ((ObjectFinalNumberFloat*)obj)->getContent();
    return true;
  }
  getterError(path, obj, NUMBER_FLOAT);
  return false;
}

bool JsonTree::get (int &to, string path) {
  AbstractObject* obj = top->get(path);
  if (isType(obj, NUMBER_INT)) {
    to = ((ObjectFinalNumberInt*)obj)->getContent();
    return true;
  }
  if (isType(obj, NUMBER_FLOAT)) {
    to = ((ObjectFinalNumberFloat*)obj)->getContent();
    return true;
  }
  getterError(path, obj, NUMBER_INT);
  return false;
}

// VECTORS

bool JsonTree::get (vector<double>& array, string path) {
  AbstractObject* obj = top->get(path);
  if (isType (obj, VECTOR)) {
    ObjectVector* vect = (ObjectVector*)obj;
    int size = vect->size();
    array.resize (size);
    for (int i = 0; i < size; i++) {
      if (((ObjectFinalNumberFloat*)vect->operator[](i))->getType() == NUMBER_FLOAT)
        array[i] = int(((ObjectFinalNumberFloat*)vect->operator[](i))->getContent());
      else if (((ObjectFinalNumberInt*)vect->operator[](i))->getType() == NUMBER_INT)
        array[i] = int(((ObjectFinalNumberInt*)vect->operator[](i))->getContent());
      else {
        getterError(path, obj, VECTOR);
        return false;
      }
    }
    return true;
  }
  getterError(path, obj, VECTOR);
  return false;
}

bool JsonTree::get (vector<int>& array, string path) {
  AbstractObject* obj = top->get(path);
  if (isType (obj, VECTOR)) {
    ObjectVector* vect = (ObjectVector*)obj;
    int size = vect->size();
    array.resize (size);
    for (int i = 0; i < size; i++) {
      if (((ObjectFinalNumberFloat*)vect->operator[](i))->getType() == NUMBER_FLOAT)
        array[i] = int(((ObjectFinalNumberFloat*)vect->operator[](i))->getContent());
      else if (((ObjectFinalNumberInt*)vect->operator[](i))->getType() == NUMBER_INT)
        array[i] = int(((ObjectFinalNumberInt*)vect->operator[](i))->getContent());
      else {
        getterError(path, obj, VECTOR);
        return false;
      }
    }
    return true;
  }
  getterError(path, obj, VECTOR);
  return false;
}

bool JsonTree::get (vector<string>& array, string path) {
  AbstractObject* obj = top->get(path);
  if (isType (obj, VECTOR)) {
    ObjectVector* vect = (ObjectVector*)obj;
    int size = vect->size();
    array.resize (size);
    for (int i = 0; i < size; i++) {
      if (((ObjectFinalString*)vect->operator[](i))->getType() == STRING)
        array[i] = ((ObjectFinalString*)vect->operator[](i))->getContent();
      else {
        getterError(path, obj, VECTOR);
        return false;
      }
    }
    return true;
  }
  getterError(path, obj, VECTOR);
  return false;
}

bool JsonTree::get (vector<bool>& array, string path) {
  AbstractObject* obj = top->get(path);
  if (isType (obj, VECTOR)) {
    ObjectVector* vect = (ObjectVector*)obj;
    int size = vect->size();
    array.resize (size);
    for (int i = 0; i < size; i++) {
      if (((ObjectFinalBool*)vect->operator[](i))->getType() == BOOL)
        array[i] = ((ObjectFinalBool*)vect->operator[](i))->getContent();
      else {
        getterError(path, obj, VECTOR);
        return false;
      }
    }
    return true;
  }
  getterError(path, obj, VECTOR);
  return false;
}

AbstractObject* JsonTree::insertObject(string path, AbstractObject *obj) {
  return nullptr;
}

// ADD

bool JsonTree::add (double value, string path) {
  AbstractObject* object = new ObjectFinalNumberFloat (value);
  return top->add (path, object);
};

bool JsonTree::add (float value, string path) {
  return add (double(value), path);
};

bool JsonTree::add (int value, string path) {
  AbstractObject* object = new ObjectFinalNumberInt (value);
  return top->add (path, object);
};

bool JsonTree::add (bool value, string path) {
  AbstractObject* object = new ObjectFinalBool (value);
  return top->add (path, object);
};

bool JsonTree::add (string value, string path) {
  AbstractObject* object = new ObjectFinalString (value);
  return top->add (path, object);
};

bool JsonTree::add (const char* value, string path) {
  return add (string(value), path);
};

bool JsonTree::add (vector<double> &array, string path) {
  return top->add (path, createVec(array));
}

bool JsonTree::add (vector<int> &array, string path) {
  return top->add (path, createVec(array));
}

bool JsonTree::add (vector<bool> &array, string path) {
  return top->add (path, createVec(array));
}

bool JsonTree::add (vector<string> &array, string path) {
  return top->add (path, createVec(array));
}

bool JsonTree::addMap (string path) {
  return top->add (path, new ObjectMap ());
}

bool JsonTree::addVector (string path) {
  return top->add (path, new ObjectVector ());
}

// REPLACE

bool JsonTree::replace (AbstractObject *newObj, string path) {
  smatch matcher;
  if (regex_search (path, matcher, lastTokenRgx)) {
      AbstractObject* father = top->get (matcher[1]);
      if (father != nullptr && father->getType() == MAP)
        return ((ObjectMap*)father)->replace (matcher[2], newObj);
      return false;
  } else if (!path.empty()) {
    return ((ObjectMap*)top)->replace (path, newObj);
  }
  return false;
}

bool JsonTree::replace (double from, string path) {
  AbstractObject* object = new ObjectFinalNumberFloat (from);
  if(replace (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::replace (float from, string path) {
  return replace (double(from), path);
}

bool JsonTree::replace (int from, string path) {
  AbstractObject* object = new ObjectFinalNumberInt (from);
  if(replace (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::replace (bool from, string path) {
  AbstractObject* object = new ObjectFinalBool (from);
  if(replace (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::replace (string from, string path) {
  AbstractObject* object = new ObjectFinalString (from);
  if(replace (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::replace (const char* from, string path) {
  return replace (string(from), path);
}

bool JsonTree::replace (vector<double>& array, string path) {
  return replace (createVec (array), path);
}

bool JsonTree::replace (vector<int>& array, string path) {
  return replace (createVec (array), path);
}

bool JsonTree::replace (vector<bool>& array, string path) {
  return replace (createVec (array), path);
}

bool JsonTree::replace (vector<string>& array, string path) {
  return replace (createVec (array), path);
}

// SET

bool JsonTree::set(AbstractObject *newObj, string path) {
  if (exist (path))
    return replace (newObj, path);
  else
    return top->add (path, newObj);
}

bool JsonTree::set (double from, string path) {
  AbstractObject* object = new ObjectFinalNumberFloat (from);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::set (float from, string path) {
  return set (double(from), path);
}

bool JsonTree::set (int from, string path) {
  AbstractObject* object = new ObjectFinalNumberInt (from);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::set (bool from, string path) {
  AbstractObject* object = new ObjectFinalBool (from);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::set (string value, string path) {
  AbstractObject* object = new ObjectFinalString (value);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::set(const char *value, string path) {
  return set (string(value), path);
}

bool JsonTree::set (vector<double>& array, string path) {
  AbstractObject* object = createVec (array);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::set (vector<int>& array, string path) {
  AbstractObject* object = createVec (array);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::set (vector<bool>& array, string path) {
  AbstractObject* object = createVec (array);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

bool JsonTree::set (vector<string>& array, string path) {
  AbstractObject* object = createVec (array);
  if(set (object, path))
    return true;
  delete object;
  return false;
}

// ERASE

bool JsonTree::erase (string path) {
  smatch matcher;
  if (regex_search (path, matcher, lastTokenRgx)) {
      AbstractObject* father = top->get (matcher[1]);
      if (father != nullptr && father->getType() == MAP)
        return ((ObjectMap*)father)->erase (matcher[2]);
      return false;
  } else if (!path.empty())
    return ((ObjectMap*)top)->erase (path);
  return false;
}

// REMOVE

bool JsonTree::remove (string path) {
  smatch matcher;
  if (regex_search (path, matcher, lastTokenRgx)) {
      AbstractObject* father = top->get (matcher[1]);
      if (father != nullptr && father->getType() == MAP)
        return ((ObjectMap*)father)->remove (matcher[2]);
      return true;
  } else if (!path.empty())
    return ((ObjectMap*)top)->erase (path);
  return false;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libvisio project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "VSDMetaData.h"
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <unicode/ucnv.h>
#include <ctime>

libvisio::VSDMetaData::VSDMetaData()
  : m_idsAndOffsets(), m_typedPropertyValues(), m_metaData()
{
}

libvisio::VSDMetaData::~VSDMetaData()
{
}

enum PIDDSI
{
  PIDDSI_CODEPAGE          = 0x00000001,
  PIDDSI_CATEGORY          = 0x00000002,
  PIDDSI_PRESFORMAT        = 0x00000003,
  PIDDSI_BYTECOUNT         = 0x00000004,
  PIDDSI_LINECOUNT         = 0x00000005,
  PIDDSI_PARACOUNT         = 0x00000006,
  PIDDSI_SLIDECOUNT        = 0x00000007,
  PIDDSI_NOTECOUNT         = 0x00000008,
  PIDDSI_HIDDENCOUNT       = 0x00000009,
  PIDDSI_MMCLIPCOUNT       = 0x0000000A,
  PIDDSI_SCALE             = 0x0000000B,
  PIDDSI_HEADINGPAIR       = 0x0000000C,
  PIDDSI_DOCPARTS          = 0x0000000D,
  PIDDSI_MANAGER           = 0x0000000E,
  PIDDSI_COMPANY           = 0x0000000F,
  PIDDSI_LINKSDIRTY        = 0x00000010,
  PIDDSI_CCHWITHSPACES     = 0x00000011,
  PIDDSI_SHAREDDOC         = 0x00000013,
  PIDDSI_LINKBASE          = 0x00000014,
  PIDDSI_HLINKS            = 0x00000015,
  PIDDSI_HYPERLINKSCHANGED = 0x00000016,
  PIDDSI_VERSION           = 0x00000017,
  PIDDSI_DIGSIG            = 0x00000018,
  PIDDSI_CONTENTTYPE       = 0x0000001A,
  PIDDSI_CONTENTSTATUS     = 0x0000001B,
  PIDDSI_LANGUAGE          = 0x0000001C,
  PIDDSI_DOCVERSION        = 0x0000001D
};

enum PIDSI
{
  CODEPAGE_PROPERTY_IDENTIFIER = 0x00000001,
  PIDSI_TITLE                  = 0x00000002,
  PIDSI_SUBJECT                = 0x00000003,
  PIDSI_AUTHOR                 = 0x00000004,
  PIDSI_KEYWORDS               = 0x00000005,
  PIDSI_COMMENTS               = 0x00000006,
  PIDSI_TEMPLATE               = 0x00000007,
  PIDSI_LASTAUTHOR             = 0x00000008,
  PIDSI_REVNUMBER              = 0x00000009,
  PIDSI_EDITTIME               = 0x0000000A,
  PIDSI_LASTPRINTED            = 0x0000000B,
  PIDSI_CREATE_DTM             = 0x0000000C,
  PIDSI_LASTSAVE_DTM           = 0x0000000D,
  PIDSI_PAGECOUNT              = 0x0000000E,
  PIDSI_WORDCOUNT              = 0x0000000F,
  PIDSI_CHARCOUNT              = 0x00000010,
  PIDSI_THUMBNAIL              = 0x00000011,
  PIDSI_APPNAME                = 0x00000012,
  PIDSI_DOC_SECURITY           = 0x00000013
};

bool libvisio::VSDMetaData::parse(librevenge::RVNGInputStream *input)
{
  if (!input)
    return false;

  readPropertySetStream(input);

  return true;
}

void libvisio::VSDMetaData::readPropertySetStream(librevenge::RVNGInputStream *input)
{
  // ByteOrder
  input->seek(2, librevenge::RVNG_SEEK_CUR);
  // Version
  input->seek(2, librevenge::RVNG_SEEK_CUR);
  // SystemIdentifier
  input->seek(4, librevenge::RVNG_SEEK_CUR);
  // CLSID
  input->seek(16, librevenge::RVNG_SEEK_CUR);
  // NumPropertySets
  input->seek(4, librevenge::RVNG_SEEK_CUR);
  // FMTID0
  //input->seek(16, librevenge::RVNG_SEEK_CUR);
  uint32_t data1 = readU32(input);
  uint16_t data2 = readU16(input);
  uint16_t data3 = readU16(input);
  uint8_t data4[8];
  for (int i = 0; i < 8; i++)
  {
    data4[i] = readU8(input);
  }
  // Pretty-printed GUID is 36 bytes + the terminating null-character.
  char FMTID0[37];
  sprintf(FMTID0, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", data1, data2, data3,
          data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7]);

  uint32_t offset0 = readU32(input);
  readPropertySet(input, offset0, FMTID0);
}

void libvisio::VSDMetaData::readPropertySet(librevenge::RVNGInputStream *input, uint32_t offset, char *FMTID)
{
  input->seek(offset, librevenge::RVNG_SEEK_SET);

  // Size
  input->seek(4, librevenge::RVNG_SEEK_CUR);
  uint32_t numProperties = readU32(input);
  for (uint32_t i = 0; i < numProperties; ++i)
    readPropertyIdentifierAndOffset(input);
  for (uint32_t i = 0; i < numProperties; ++i)
  {
    if (i >= m_idsAndOffsets.size())
      break;
    readTypedPropertyValue(input, i, offset + m_idsAndOffsets[i].second, FMTID);
  }
}

uint32_t libvisio::VSDMetaData::getCodePage()
{
  for (size_t i = 0; i < m_idsAndOffsets.size(); ++i)
  {
    if (m_idsAndOffsets[i].first == CODEPAGE_PROPERTY_IDENTIFIER)
    {
      if (i >= m_typedPropertyValues.size())
        break;
      return m_typedPropertyValues[i];
    }
  }

  return 0;
}

void libvisio::VSDMetaData::readPropertyIdentifierAndOffset(librevenge::RVNGInputStream *input)
{
  uint32_t propertyIdentifier = readU32(input);
  uint32_t offset = readU32(input);
  m_idsAndOffsets.push_back(std::make_pair(propertyIdentifier, offset));
}

#define VT_I2 0x0002
#define VT_LPSTR 0x001E

void libvisio::VSDMetaData::readTypedPropertyValue(librevenge::RVNGInputStream *input,
                                                   uint32_t index,
                                                   uint32_t offset,
                                                   char *FMTID)
{
  input->seek(offset, librevenge::RVNG_SEEK_SET);
  uint16_t type = readU16(input);
  // Padding
  input->seek(2, librevenge::RVNG_SEEK_CUR);

  if (type == VT_I2)
  {
    uint16_t value = readU16(input);
    m_typedPropertyValues[index] = value;
  }
  else if (type == VT_LPSTR)
  {
    librevenge::RVNGString string = readCodePageString(input);
    if (!string.empty())
    {
      if (index >= m_idsAndOffsets.size())
        return;

      if (!strcmp(FMTID, "f29f85e0-4ff9-1068-ab91-08002b27b3d9"))
      {
        switch (m_idsAndOffsets[index].first)
        {
        case PIDSI_TITLE:
          m_metaData.insert("dc:title", string);
          break;
        case PIDSI_SUBJECT:
          m_metaData.insert("dc:subject", string);
          break;
        case PIDSI_AUTHOR:
          m_metaData.insert("meta:initial-creator", string);
          m_metaData.insert("dc:creator", string);
          break;
        case PIDSI_KEYWORDS:
          m_metaData.insert("meta:keyword", string);
          break;
        case PIDSI_COMMENTS:
          m_metaData.insert("dc:description", string);
          break;
        case PIDSI_TEMPLATE:
          std::string templateHref(string.cstr());
          size_t found = templateHref.find_last_of("/\\");
          if (found != std::string::npos)
            string = librevenge::RVNGString(templateHref.substr(found+1).c_str());
          m_metaData.insert("librevenge:template", string);
          break;
        }
      }
      else if (!strcmp(FMTID,"d5cdd502-2e9c-101b-9397-08002b2cf9ae"))
      {
        switch (m_idsAndOffsets[index].first)
        {
        case PIDDSI::PIDDSI_CATEGORY:
          m_metaData.insert("librevenge:category", string);
          break;
        case PIDDSI::PIDDSI_LINECOUNT:
          // this should actually be PIDDSI::PIDDSI_COMPANY but this
          // is what company is mapped to
          m_metaData.insert("librevenge:company", string);
          break;
        case PIDDSI::PIDDSI_LANGUAGE:
          m_metaData.insert("dc:language", string);
          break;
        }
      }
    }
  }
}

librevenge::RVNGString libvisio::VSDMetaData::readCodePageString(librevenge::RVNGInputStream *input)
{
  uint32_t size = readU32(input);

  std::vector<unsigned char> characters;
  for (uint32_t i = 0; i < size; ++i)
    characters.push_back(readU8(input));

  uint32_t codepage = getCodePage();
  librevenge::RVNGString string;

  if (codepage == 65001)
  {
    // http://msdn.microsoft.com/en-us/library/windows/desktop/dd374130%28v=vs.85%29.aspx
    // says this is UTF-8.
    for (std::vector<unsigned char>::const_iterator i = characters.begin(); i != characters.end(); ++i)
      string.append((const char)*i);
  }
  else
  {
    UErrorCode status = U_ZERO_ERROR;
    UConverter *conv = 0;

    switch (codepage)
    {
    case 1252:
      // http://msdn.microsoft.com/en-us/goglobal/bb964654
      conv = ucnv_open("windows-1252", &status);
      break;
    }

    if (U_SUCCESS(status) && conv)
    {
      const char *src = (const char *)&characters[0];
      const char *srcLimit = (const char *)src + characters.size();
      while (src < srcLimit)
      {
        UChar32 ucs4Character = ucnv_getNextUChar(conv, &src, srcLimit, &status);
        if (U_SUCCESS(status) && U_IS_UNICODE_CHAR(ucs4Character))
          appendUCS4(string, ucs4Character);
      }
    }

    if (conv)
      ucnv_close(conv);
  }

  return string;
}

bool libvisio::VSDMetaData::parseTimes(librevenge::RVNGInputStream *input)
{
  // Parse the header
  // HeaderSignature: 8 bytes
  // HeaderCLSID: 16 bytes
  // MinorVersion: 2 bytes
  // MajorVersion: 2 bytes
  // ByteOrder: 2 bytes
  input->seek(30, librevenge::RVNG_SEEK_CUR);
  uint16_t sectorShift = readU16(input);
  // MiniSectorShift: 2 bytes
  // Reserved: 6 bytes
  // NumDirectorySectors: 4 bytes
  // NumFATSectors: 4 bytes
  input->seek(16, librevenge::RVNG_SEEK_CUR);
  uint32_t firstDirSectorLocation = readU32(input);

  // Seek to the Root Directory Entry
  size_t sectorSize = std::pow(2, sectorShift);
  input->seek((firstDirSectorLocation + 1) * sectorSize, librevenge::RVNG_SEEK_SET);
  // DirectoryEntryName: 64 bytes
  // DirectoryEntryNameLength: 2 bytes
  // ObjectType: 1 byte
  // ColorFlag: 1 byte
  // LeftSiblingID: 4 bytes
  // RightSiblingID: 4 bytes
  // ChildID: 4 bytes
  // CLSID: 16 bytes
  // StateBits: 4 bytes
  // CreationTime: 8 bytes
  input->seek(108, librevenge::RVNG_SEEK_CUR);
  uint64_t modifiedTime = readU64(input);

  // modifiedTime is number of 100ns since Jan 1 1601
  const uint64_t epoch = uint64_t(116444736UL) * 100;
  time_t sec = (modifiedTime / 10000000) - epoch;
  const struct tm *time = localtime(&sec);
  if (time)
  {
    static const int MAX_BUFFER = 1024;
    char buffer[MAX_BUFFER];
    strftime(&buffer[0], MAX_BUFFER-1, "%Y-%m-%dT%H:%M:%SZ", time);
    librevenge::RVNGString result;
    result.append(buffer);
    // Visio UI uses modifiedTime for both purposes.
    m_metaData.insert("meta:creation-date", result);
    m_metaData.insert("dc:date", result);
    return true;
  }
  return false;
}

const librevenge::RVNGPropertyList &libvisio::VSDMetaData::getMetaData()
{
  return m_metaData;
}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>C++11 syntax is not allowed<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libvisio project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "VSDMetaData.h"
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <unicode/ucnv.h>
#include <ctime>

libvisio::VSDMetaData::VSDMetaData()
  : m_idsAndOffsets(), m_typedPropertyValues(), m_metaData()
{
}

libvisio::VSDMetaData::~VSDMetaData()
{
}

enum PIDDSI
{
  PIDDSI_CODEPAGE          = 0x00000001,
  PIDDSI_CATEGORY          = 0x00000002,
  PIDDSI_PRESFORMAT        = 0x00000003,
  PIDDSI_BYTECOUNT         = 0x00000004,
  PIDDSI_LINECOUNT         = 0x00000005,
  PIDDSI_PARACOUNT         = 0x00000006,
  PIDDSI_SLIDECOUNT        = 0x00000007,
  PIDDSI_NOTECOUNT         = 0x00000008,
  PIDDSI_HIDDENCOUNT       = 0x00000009,
  PIDDSI_MMCLIPCOUNT       = 0x0000000A,
  PIDDSI_SCALE             = 0x0000000B,
  PIDDSI_HEADINGPAIR       = 0x0000000C,
  PIDDSI_DOCPARTS          = 0x0000000D,
  PIDDSI_MANAGER           = 0x0000000E,
  PIDDSI_COMPANY           = 0x0000000F,
  PIDDSI_LINKSDIRTY        = 0x00000010,
  PIDDSI_CCHWITHSPACES     = 0x00000011,
  PIDDSI_SHAREDDOC         = 0x00000013,
  PIDDSI_LINKBASE          = 0x00000014,
  PIDDSI_HLINKS            = 0x00000015,
  PIDDSI_HYPERLINKSCHANGED = 0x00000016,
  PIDDSI_VERSION           = 0x00000017,
  PIDDSI_DIGSIG            = 0x00000018,
  PIDDSI_CONTENTTYPE       = 0x0000001A,
  PIDDSI_CONTENTSTATUS     = 0x0000001B,
  PIDDSI_LANGUAGE          = 0x0000001C,
  PIDDSI_DOCVERSION        = 0x0000001D
};

enum PIDSI
{
  CODEPAGE_PROPERTY_IDENTIFIER = 0x00000001,
  PIDSI_TITLE                  = 0x00000002,
  PIDSI_SUBJECT                = 0x00000003,
  PIDSI_AUTHOR                 = 0x00000004,
  PIDSI_KEYWORDS               = 0x00000005,
  PIDSI_COMMENTS               = 0x00000006,
  PIDSI_TEMPLATE               = 0x00000007,
  PIDSI_LASTAUTHOR             = 0x00000008,
  PIDSI_REVNUMBER              = 0x00000009,
  PIDSI_EDITTIME               = 0x0000000A,
  PIDSI_LASTPRINTED            = 0x0000000B,
  PIDSI_CREATE_DTM             = 0x0000000C,
  PIDSI_LASTSAVE_DTM           = 0x0000000D,
  PIDSI_PAGECOUNT              = 0x0000000E,
  PIDSI_WORDCOUNT              = 0x0000000F,
  PIDSI_CHARCOUNT              = 0x00000010,
  PIDSI_THUMBNAIL              = 0x00000011,
  PIDSI_APPNAME                = 0x00000012,
  PIDSI_DOC_SECURITY           = 0x00000013
};

bool libvisio::VSDMetaData::parse(librevenge::RVNGInputStream *input)
{
  if (!input)
    return false;

  readPropertySetStream(input);

  return true;
}

void libvisio::VSDMetaData::readPropertySetStream(librevenge::RVNGInputStream *input)
{
  // ByteOrder
  input->seek(2, librevenge::RVNG_SEEK_CUR);
  // Version
  input->seek(2, librevenge::RVNG_SEEK_CUR);
  // SystemIdentifier
  input->seek(4, librevenge::RVNG_SEEK_CUR);
  // CLSID
  input->seek(16, librevenge::RVNG_SEEK_CUR);
  // NumPropertySets
  input->seek(4, librevenge::RVNG_SEEK_CUR);
  // FMTID0
  //input->seek(16, librevenge::RVNG_SEEK_CUR);
  uint32_t data1 = readU32(input);
  uint16_t data2 = readU16(input);
  uint16_t data3 = readU16(input);
  uint8_t data4[8];
  for (int i = 0; i < 8; i++)
  {
    data4[i] = readU8(input);
  }
  // Pretty-printed GUID is 36 bytes + the terminating null-character.
  char FMTID0[37];
  sprintf(FMTID0, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", data1, data2, data3,
          data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7]);

  uint32_t offset0 = readU32(input);
  readPropertySet(input, offset0, FMTID0);
}

void libvisio::VSDMetaData::readPropertySet(librevenge::RVNGInputStream *input, uint32_t offset, char *FMTID)
{
  input->seek(offset, librevenge::RVNG_SEEK_SET);

  // Size
  input->seek(4, librevenge::RVNG_SEEK_CUR);
  uint32_t numProperties = readU32(input);
  for (uint32_t i = 0; i < numProperties; ++i)
    readPropertyIdentifierAndOffset(input);
  for (uint32_t i = 0; i < numProperties; ++i)
  {
    if (i >= m_idsAndOffsets.size())
      break;
    readTypedPropertyValue(input, i, offset + m_idsAndOffsets[i].second, FMTID);
  }
}

uint32_t libvisio::VSDMetaData::getCodePage()
{
  for (size_t i = 0; i < m_idsAndOffsets.size(); ++i)
  {
    if (m_idsAndOffsets[i].first == CODEPAGE_PROPERTY_IDENTIFIER)
    {
      if (i >= m_typedPropertyValues.size())
        break;
      return m_typedPropertyValues[i];
    }
  }

  return 0;
}

void libvisio::VSDMetaData::readPropertyIdentifierAndOffset(librevenge::RVNGInputStream *input)
{
  uint32_t propertyIdentifier = readU32(input);
  uint32_t offset = readU32(input);
  m_idsAndOffsets.push_back(std::make_pair(propertyIdentifier, offset));
}

#define VT_I2 0x0002
#define VT_LPSTR 0x001E

void libvisio::VSDMetaData::readTypedPropertyValue(librevenge::RVNGInputStream *input,
                                                   uint32_t index,
                                                   uint32_t offset,
                                                   char *FMTID)
{
  input->seek(offset, librevenge::RVNG_SEEK_SET);
  uint16_t type = readU16(input);
  // Padding
  input->seek(2, librevenge::RVNG_SEEK_CUR);

  if (type == VT_I2)
  {
    uint16_t value = readU16(input);
    m_typedPropertyValues[index] = value;
  }
  else if (type == VT_LPSTR)
  {
    librevenge::RVNGString string = readCodePageString(input);
    if (!string.empty())
    {
      if (index >= m_idsAndOffsets.size())
        return;

      if (!strcmp(FMTID, "f29f85e0-4ff9-1068-ab91-08002b27b3d9"))
      {
        switch (m_idsAndOffsets[index].first)
        {
        case PIDSI_TITLE:
          m_metaData.insert("dc:title", string);
          break;
        case PIDSI_SUBJECT:
          m_metaData.insert("dc:subject", string);
          break;
        case PIDSI_AUTHOR:
          m_metaData.insert("meta:initial-creator", string);
          m_metaData.insert("dc:creator", string);
          break;
        case PIDSI_KEYWORDS:
          m_metaData.insert("meta:keyword", string);
          break;
        case PIDSI_COMMENTS:
          m_metaData.insert("dc:description", string);
          break;
        case PIDSI_TEMPLATE:
          std::string templateHref(string.cstr());
          size_t found = templateHref.find_last_of("/\\");
          if (found != std::string::npos)
            string = librevenge::RVNGString(templateHref.substr(found+1).c_str());
          m_metaData.insert("librevenge:template", string);
          break;
        }
      }
      else if (!strcmp(FMTID,"d5cdd502-2e9c-101b-9397-08002b2cf9ae"))
      {
        switch (m_idsAndOffsets[index].first)
        {
        case PIDDSI_CATEGORY:
          m_metaData.insert("librevenge:category", string);
          break;
        case PIDDSI_LINECOUNT:
          // this should actually be PIDDSI_COMPANY but this
          // is what company is mapped to
          m_metaData.insert("librevenge:company", string);
          break;
        case PIDDSI_LANGUAGE:
          m_metaData.insert("dc:language", string);
          break;
        }
      }
    }
  }
}

librevenge::RVNGString libvisio::VSDMetaData::readCodePageString(librevenge::RVNGInputStream *input)
{
  uint32_t size = readU32(input);

  std::vector<unsigned char> characters;
  for (uint32_t i = 0; i < size; ++i)
    characters.push_back(readU8(input));

  uint32_t codepage = getCodePage();
  librevenge::RVNGString string;

  if (codepage == 65001)
  {
    // http://msdn.microsoft.com/en-us/library/windows/desktop/dd374130%28v=vs.85%29.aspx
    // says this is UTF-8.
    for (std::vector<unsigned char>::const_iterator i = characters.begin(); i != characters.end(); ++i)
      string.append((const char)*i);
  }
  else
  {
    UErrorCode status = U_ZERO_ERROR;
    UConverter *conv = 0;

    switch (codepage)
    {
    case 1252:
      // http://msdn.microsoft.com/en-us/goglobal/bb964654
      conv = ucnv_open("windows-1252", &status);
      break;
    }

    if (U_SUCCESS(status) && conv)
    {
      const char *src = (const char *)&characters[0];
      const char *srcLimit = (const char *)src + characters.size();
      while (src < srcLimit)
      {
        UChar32 ucs4Character = ucnv_getNextUChar(conv, &src, srcLimit, &status);
        if (U_SUCCESS(status) && U_IS_UNICODE_CHAR(ucs4Character))
          appendUCS4(string, ucs4Character);
      }
    }

    if (conv)
      ucnv_close(conv);
  }

  return string;
}

bool libvisio::VSDMetaData::parseTimes(librevenge::RVNGInputStream *input)
{
  // Parse the header
  // HeaderSignature: 8 bytes
  // HeaderCLSID: 16 bytes
  // MinorVersion: 2 bytes
  // MajorVersion: 2 bytes
  // ByteOrder: 2 bytes
  input->seek(30, librevenge::RVNG_SEEK_CUR);
  uint16_t sectorShift = readU16(input);
  // MiniSectorShift: 2 bytes
  // Reserved: 6 bytes
  // NumDirectorySectors: 4 bytes
  // NumFATSectors: 4 bytes
  input->seek(16, librevenge::RVNG_SEEK_CUR);
  uint32_t firstDirSectorLocation = readU32(input);

  // Seek to the Root Directory Entry
  size_t sectorSize = std::pow(2, sectorShift);
  input->seek((firstDirSectorLocation + 1) * sectorSize, librevenge::RVNG_SEEK_SET);
  // DirectoryEntryName: 64 bytes
  // DirectoryEntryNameLength: 2 bytes
  // ObjectType: 1 byte
  // ColorFlag: 1 byte
  // LeftSiblingID: 4 bytes
  // RightSiblingID: 4 bytes
  // ChildID: 4 bytes
  // CLSID: 16 bytes
  // StateBits: 4 bytes
  // CreationTime: 8 bytes
  input->seek(108, librevenge::RVNG_SEEK_CUR);
  uint64_t modifiedTime = readU64(input);

  // modifiedTime is number of 100ns since Jan 1 1601
  const uint64_t epoch = uint64_t(116444736UL) * 100;
  time_t sec = (modifiedTime / 10000000) - epoch;
  const struct tm *time = localtime(&sec);
  if (time)
  {
    static const int MAX_BUFFER = 1024;
    char buffer[MAX_BUFFER];
    strftime(&buffer[0], MAX_BUFFER-1, "%Y-%m-%dT%H:%M:%SZ", time);
    librevenge::RVNGString result;
    result.append(buffer);
    // Visio UI uses modifiedTime for both purposes.
    m_metaData.insert("meta:creation-date", result);
    m_metaData.insert("dc:date", result);
    return true;
  }
  return false;
}

const librevenge::RVNGPropertyList &libvisio::VSDMetaData::getMetaData()
{
  return m_metaData;
}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<|endoftext|>