<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "fnord-msg/MessageBuilder.h"
#include "fnord-msg/MessageObject.h"
#include "fnord-msg/MessageEncoder.h"
#include "fnord-msg/MessageDecoder.h"
#include "fnord-msg/MessagePrinter.h"
#include <fnord-fts/fts.h>
#include <fnord-fts/fts_common.h>
#include "logjoin/LogJoinTarget.h"
#include "common.h"

using namespace fnord;

namespace cm {

LogJoinTarget::LogJoinTarget(
    const msg::MessageSchema& joined_sessions_schema,
    fts::Analyzer* analyzer,
    RefPtr<FeatureIndexWriter> index,
    bool dry_run) :
    joined_sessions_schema_(joined_sessions_schema),
    analyzer_(analyzer),
    index_(index),
    dry_run_(dry_run),
    num_sessions(0),
    num_queries(0),
    num_item_visits(0) {}

void LogJoinTarget::onSession(
    mdb::MDBTransaction* txn,
    const TrackedSession& session) {
  const auto& schema = joined_sessions_schema_;
  msg::MessageObject obj;

  for (const auto& tq : session.flushed_queries) {
    auto q = trackedQueryToJoinedQuery(session, tq);
    auto& qry_obj = obj.addChild(schema.id("queries"));

    /* queries.time */
    qry_obj.addChild(
        schema.id("queries.time"),
        (uint32_t) (q.time.unixMicros() / kMicrosPerSecond));

    /* queries.language */
    auto lang = cm::extractLanguage(q.attrs);
    qry_obj.addChild(schema.id("queries.language"), (uint32_t) lang);

    /* queries.query_string */
    auto qstr = cm::extractQueryString(q.attrs);
    if (!qstr.isEmpty()) {
      auto qstr_norm = analyzer_->normalize(lang, qstr.get());
      qry_obj.addChild(schema.id("queries.query_string"), qstr.get());
      qry_obj.addChild(schema.id("queries.query_string_normalized"), qstr_norm);
    }

    /* queries.num_item_clicks, queries.num_items */
    uint32_t nitems = 0;
    uint32_t nclicks = 0;
    uint32_t nads = 0;
    uint32_t nadclicks = 0;
    for (const auto& i : q.items) {
      // DAWANDA HACK
      if (i.position >= 1 && i.position <= 4) {
        ++nads;
        nadclicks += i.clicked;
      }
      // EOF DAWANDA HACK

      ++nitems;
      nclicks += i.clicked;
    }

    qry_obj.addChild(schema.id("queries.num_items"), nitems);
    qry_obj.addChild(schema.id("queries.num_items_clicked"), nclicks);
    qry_obj.addChild(schema.id("queries.num_ad_impressions"), nads);
    qry_obj.addChild(schema.id("queries.num_ad_clicks"), nadclicks);

    /* queries.page */
    auto pg_str = cm::extractAttr(q.attrs, "pg");
    if (!pg_str.isEmpty()) {
      uint32_t pg = std::stoul(pg_str.get());
      qry_obj.addChild(schema.id("queries.page"), pg);
    }

    /* queries.ab_test_group */
    auto abgrp = cm::extractABTestGroup(q.attrs);
    if (!abgrp.isEmpty()) {
      qry_obj.addChild(schema.id("queries.ab_test_group"), abgrp.get());
    }

    /* queries.category1 */
    auto qcat1 = cm::extractAttr(q.attrs, "q_cat1");
    if (!qcat1.isEmpty()) {
      uint32_t c = std::stoul(qcat1.get());
      qry_obj.addChild(schema.id("queries.category1"), c);
    }

    /* queries.category1 */
    auto qcat2 = cm::extractAttr(q.attrs, "q_cat2");
    if (!qcat2.isEmpty()) {
      uint32_t c = std::stoul(qcat2.get());
      qry_obj.addChild(schema.id("queries.category2"), c);
    }

    /* queries.category1 */
    auto qcat3 = cm::extractAttr(q.attrs, "q_cat3");
    if (!qcat3.isEmpty()) {
      uint32_t c = std::stoul(qcat3.get());
      qry_obj.addChild(schema.id("queries.category3"), c);
    }

    /* queries.device_type */
    qry_obj.addChild(
        schema.id("queries.device_type"),
        (uint32_t) extractDeviceType(q.attrs));

    /* queries.page_type */
    qry_obj.addChild(
        schema.id("queries.page_type"),
        (uint32_t) extractPageType(q.attrs));

    for (const auto& item : q.items) {
      auto& item_obj = qry_obj.addChild(schema.id("queries.items"));

      item_obj.addChild(
          schema.id("queries.items.position"),
          (uint32_t) item.position);

      item_obj.addChild(
          schema.id("queries.items.item_id"),
          item.item.docID().docid);

      if (item.clicked) {
        item_obj.addChild(schema.id("queries.items.clicked"), msg::TRUE);
      } else {
        item_obj.addChild(schema.id("queries.items.clicked"), msg::FALSE);
      }

      auto docid = item.item.docID();

      auto shopid = index_->getField(docid, "shop_id");
      if (shopid.isEmpty()) {
        fnord::logWarning(
            "cm.logjoin",
            "item not found in featureindex: $0",
            docid.docid);
      } else {
        item_obj.addChild(
            schema.id("queries.items.shop_id"),
            (uint32_t) std::stoull(shopid.get()));
      }

      auto category1 = index_->getField(docid, "category1");
      if (!category1.isEmpty()) {
        item_obj.addChild(
            schema.id("queries.items.category1"),
            (uint32_t) std::stoull(category1.get()));
      }

      auto category2 = index_->getField(docid, "category2");
      if (!category2.isEmpty()) {
        item_obj.addChild(
            schema.id("queries.items.category2"),
            (uint32_t) std::stoull(category2.get()));
      }

      auto category3 = index_->getField(docid, "category3");
      if (!category3.isEmpty()) {
        item_obj.addChild(
            schema.id("queries.items.category3"),
            (uint32_t) std::stoull(category3.get()));
      }
    }
  }

  if (dry_run_) {
    fnord::logInfo(
        "cm.logjoin",
        "[DRYRUN] not upload session: $0",
        msg::MessagePrinter::print(obj, joined_sessions_schema_));
  } else {
    Buffer msg_buf;
    msg::MessageEncoder::encode(obj, joined_sessions_schema_, &msg_buf);
    auto key = StringUtil::format("__uploadq-sessions-$0",  rnd_.hex128());
    txn->update(key, msg_buf);
  }

  ++num_sessions;
}

void LogJoinTarget::onQuery(
    mdb::MDBTransaction* txn,
    const TrackedSession& session,
    const TrackedQuery& query) {
  //fnord::iputs("on query... $0", query.items.size());
  ++num_queries;
}

void LogJoinTarget::onItemVisit(
    mdb::MDBTransaction* txn,
    const TrackedSession& session,
    const TrackedItemVisit& item_visit) {

}

void LogJoinTarget::onItemVisit(
    mdb::MDBTransaction* txn,
    const TrackedSession& session,
    const TrackedItemVisit& item_visit,
    const TrackedQuery& query) {
  ++num_item_visits;
}

JoinedQuery LogJoinTarget::trackedQueryToJoinedQuery(
    const TrackedSession& session,
    const TrackedQuery& query) const {
  JoinedQuery jq;
  jq.customer = session.customer_key;
  jq.uid = session.uid;
  jq.time = query.time;
  jq.attrs = query.attrs;
  for (const auto& a : session.attrs) {
    jq.attrs.emplace_back("s!" + a);
  }

  for (const auto& item : query.items) {
    JoinedQueryItem jqi;
    jqi.item = item.item;
    jqi.clicked = item.clicked;
    jqi.variant = item.variant;
    jqi.position = item.position;
    jq.items.emplace_back(jqi);
  }

  return jq;
}

/*
void LogJoin::onQuery(
    const TrackedSession& session,
    const TrackedQuery& query) {
  stat_joined_queries_.incr(1);
  auto jq_json = json::toJSONString(jq);
  auto feeds = getFeedsForCustomer(jq.customer);

  if (dry_run_) {
#ifndef NDEBUG
    fnord::logTrace(
        "cm.logjoin",
        "[dry-run] would write joined query: $0",
        jq_json);
#endif
  } else {
    feeds->joined_queries_feed_writer->appendEntry(jq_json);
  }
}

void LogJoin::onItemVisit(
    const TrackedSession& session,
    const TrackedItemVisit& item_visit) {
  stat_joined_item_visits_.incr(1);

  JoinedItemVisit jiv;
  jiv.customer = session.customer_key;
  jiv.uid = session.uid;
  jiv.time = item_visit.time;
  jiv.item = item_visit.item;
  jiv.attrs = item_visit.attrs;

  for (const auto& a : session.attrs) {
    jiv.attrs.emplace_back("s!" + a);
  }

  auto jiv_json = json::toJSONString(jiv);
  auto feeds = getFeedsForCustomer(jiv.customer);

  if (dry_run_) {
#ifndef NDEBUG
    fnord::logTrace(
        "cm.logjoin",
        "[dry-run] would write joined item visit: $0",
        jiv_json);
#endif
  } else {
    feeds->joined_item_visits_feed_writer->appendEntry(jiv_json);
  }
}

void LogJoin::onItemVisit(
    const TrackedSession& session,
    const TrackedItemVisit& item_visit,
    const TrackedQuery& query) {
  stat_joined_item_visits_.incr(1);

  JoinedItemVisit jiv;
  jiv.customer = session.customer_key;
  jiv.uid = session.uid;
  jiv.time = item_visit.time;
  jiv.item = item_visit.item;
  jiv.attrs = item_visit.attrs;

  for (const auto& a : session.attrs) {
    jiv.attrs.emplace_back("s!" + a);
  }

  for (const auto& a : query.attrs) {
    jiv.attrs.emplace_back("q!" + a);
  }

  auto jiv_json = json::toJSONString(jiv);
  auto feeds = getFeedsForCustomer(jiv.customer);

  if (dry_run_) {
#ifndef NDEBUG
    fnord::logTrace(
        "cm.logjoin",
        "[dry-run] would write joined item visit: $0",
        jiv_json);
#endif
  } else {
    feeds->joined_item_visits_feed_writer->appendEntry(jiv_json);
  }
}
*/

} // namespace cm

<commit_msg>typo fix<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "fnord-msg/MessageBuilder.h"
#include "fnord-msg/MessageObject.h"
#include "fnord-msg/MessageEncoder.h"
#include "fnord-msg/MessageDecoder.h"
#include "fnord-msg/MessagePrinter.h"
#include <fnord-fts/fts.h>
#include <fnord-fts/fts_common.h>
#include "logjoin/LogJoinTarget.h"
#include "common.h"

using namespace fnord;

namespace cm {

LogJoinTarget::LogJoinTarget(
    const msg::MessageSchema& joined_sessions_schema,
    fts::Analyzer* analyzer,
    RefPtr<FeatureIndexWriter> index,
    bool dry_run) :
    joined_sessions_schema_(joined_sessions_schema),
    analyzer_(analyzer),
    index_(index),
    dry_run_(dry_run),
    num_sessions(0),
    num_queries(0),
    num_item_visits(0) {}

void LogJoinTarget::onSession(
    mdb::MDBTransaction* txn,
    const TrackedSession& session) {
  const auto& schema = joined_sessions_schema_;
  msg::MessageObject obj;

  for (const auto& tq : session.flushed_queries) {
    auto q = trackedQueryToJoinedQuery(session, tq);
    auto& qry_obj = obj.addChild(schema.id("queries"));

    /* queries.time */
    qry_obj.addChild(
        schema.id("queries.time"),
        (uint32_t) (q.time.unixMicros() / kMicrosPerSecond));

    /* queries.language */
    auto lang = cm::extractLanguage(q.attrs);
    qry_obj.addChild(schema.id("queries.language"), (uint32_t) lang);

    /* queries.query_string */
    auto qstr = cm::extractQueryString(q.attrs);
    if (!qstr.isEmpty()) {
      auto qstr_norm = analyzer_->normalize(lang, qstr.get());
      qry_obj.addChild(schema.id("queries.query_string"), qstr.get());
      qry_obj.addChild(schema.id("queries.query_string_normalized"), qstr_norm);
    }

    /* queries.num_item_clicks, queries.num_items */
    uint32_t nitems = 0;
    uint32_t nclicks = 0;
    uint32_t nads = 0;
    uint32_t nadclicks = 0;
    for (const auto& i : q.items) {
      // DAWANDA HACK
      if (i.position >= 1 && i.position <= 4) {
        ++nads;
        nadclicks += i.clicked;
      }
      // EOF DAWANDA HACK

      ++nitems;
      nclicks += i.clicked;
    }

    qry_obj.addChild(schema.id("queries.num_items"), nitems);
    qry_obj.addChild(schema.id("queries.num_items_clicked"), nclicks);
    qry_obj.addChild(schema.id("queries.num_ad_impressions"), nads);
    qry_obj.addChild(schema.id("queries.num_ad_clicks"), nadclicks);

    /* queries.page */
    auto pg_str = cm::extractAttr(q.attrs, "pg");
    if (!pg_str.isEmpty()) {
      uint32_t pg = std::stoul(pg_str.get());
      qry_obj.addChild(schema.id("queries.page"), pg);
    }

    /* queries.ab_test_group */
    auto abgrp = cm::extractABTestGroup(q.attrs);
    if (!abgrp.isEmpty()) {
      qry_obj.addChild(schema.id("queries.ab_test_group"), abgrp.get());
    }

    /* queries.category1 */
    auto qcat1 = cm::extractAttr(q.attrs, "q_cat1");
    if (!qcat1.isEmpty()) {
      uint32_t c = std::stoul(qcat1.get());
      qry_obj.addChild(schema.id("queries.category1"), c);
    }

    /* queries.category1 */
    auto qcat2 = cm::extractAttr(q.attrs, "q_cat2");
    if (!qcat2.isEmpty()) {
      uint32_t c = std::stoul(qcat2.get());
      qry_obj.addChild(schema.id("queries.category2"), c);
    }

    /* queries.category1 */
    auto qcat3 = cm::extractAttr(q.attrs, "q_cat3");
    if (!qcat3.isEmpty()) {
      uint32_t c = std::stoul(qcat3.get());
      qry_obj.addChild(schema.id("queries.category3"), c);
    }

    /* queries.device_type */
    qry_obj.addChild(
        schema.id("queries.device_type"),
        (uint32_t) extractDeviceType(q.attrs));

    /* queries.page_type */
    qry_obj.addChild(
        schema.id("queries.page_type"),
        (uint32_t) extractPageType(q.attrs));

    for (const auto& item : q.items) {
      auto& item_obj = qry_obj.addChild(schema.id("queries.items"));

      item_obj.addChild(
          schema.id("queries.items.position"),
          (uint32_t) item.position);

      item_obj.addChild(
          schema.id("queries.items.item_id"),
          item.item.docID().docid);

      if (item.clicked) {
        item_obj.addChild(schema.id("queries.items.clicked"), msg::TRUE);
      } else {
        item_obj.addChild(schema.id("queries.items.clicked"), msg::FALSE);
      }

      auto docid = item.item.docID();

      auto shopid = index_->getField(docid, "shop_id");
      if (shopid.isEmpty()) {
        fnord::logWarning(
            "cm.logjoin",
            "item not found in featureindex: $0",
            docid.docid);
      } else {
        item_obj.addChild(
            schema.id("queries.items.shop_id"),
            (uint32_t) std::stoull(shopid.get()));
      }

      auto category1 = index_->getField(docid, "category1");
      if (!category1.isEmpty()) {
        item_obj.addChild(
            schema.id("queries.items.category1"),
            (uint32_t) std::stoull(category1.get()));
      }

      auto category2 = index_->getField(docid, "category2");
      if (!category2.isEmpty()) {
        item_obj.addChild(
            schema.id("queries.items.category2"),
            (uint32_t) std::stoull(category2.get()));
      }

      auto category3 = index_->getField(docid, "category3");
      if (!category3.isEmpty()) {
        item_obj.addChild(
            schema.id("queries.items.category3"),
            (uint32_t) std::stoull(category3.get()));
      }
    }
  }

  if (dry_run_) {
    fnord::logInfo(
        "cm.logjoin",
        "[DRYRUN] not uploading session: $0",
        msg::MessagePrinter::print(obj, joined_sessions_schema_));
  } else {
    Buffer msg_buf;
    msg::MessageEncoder::encode(obj, joined_sessions_schema_, &msg_buf);
    auto key = StringUtil::format("__uploadq-sessions-$0",  rnd_.hex128());
    txn->update(key, msg_buf);
  }

  ++num_sessions;
}

void LogJoinTarget::onQuery(
    mdb::MDBTransaction* txn,
    const TrackedSession& session,
    const TrackedQuery& query) {
  //fnord::iputs("on query... $0", query.items.size());
  ++num_queries;
}

void LogJoinTarget::onItemVisit(
    mdb::MDBTransaction* txn,
    const TrackedSession& session,
    const TrackedItemVisit& item_visit) {

}

void LogJoinTarget::onItemVisit(
    mdb::MDBTransaction* txn,
    const TrackedSession& session,
    const TrackedItemVisit& item_visit,
    const TrackedQuery& query) {
  ++num_item_visits;
}

JoinedQuery LogJoinTarget::trackedQueryToJoinedQuery(
    const TrackedSession& session,
    const TrackedQuery& query) const {
  JoinedQuery jq;
  jq.customer = session.customer_key;
  jq.uid = session.uid;
  jq.time = query.time;
  jq.attrs = query.attrs;
  for (const auto& a : session.attrs) {
    jq.attrs.emplace_back("s!" + a);
  }

  for (const auto& item : query.items) {
    JoinedQueryItem jqi;
    jqi.item = item.item;
    jqi.clicked = item.clicked;
    jqi.variant = item.variant;
    jqi.position = item.position;
    jq.items.emplace_back(jqi);
  }

  return jq;
}

/*
void LogJoin::onQuery(
    const TrackedSession& session,
    const TrackedQuery& query) {
  stat_joined_queries_.incr(1);
  auto jq_json = json::toJSONString(jq);
  auto feeds = getFeedsForCustomer(jq.customer);

  if (dry_run_) {
#ifndef NDEBUG
    fnord::logTrace(
        "cm.logjoin",
        "[dry-run] would write joined query: $0",
        jq_json);
#endif
  } else {
    feeds->joined_queries_feed_writer->appendEntry(jq_json);
  }
}

void LogJoin::onItemVisit(
    const TrackedSession& session,
    const TrackedItemVisit& item_visit) {
  stat_joined_item_visits_.incr(1);

  JoinedItemVisit jiv;
  jiv.customer = session.customer_key;
  jiv.uid = session.uid;
  jiv.time = item_visit.time;
  jiv.item = item_visit.item;
  jiv.attrs = item_visit.attrs;

  for (const auto& a : session.attrs) {
    jiv.attrs.emplace_back("s!" + a);
  }

  auto jiv_json = json::toJSONString(jiv);
  auto feeds = getFeedsForCustomer(jiv.customer);

  if (dry_run_) {
#ifndef NDEBUG
    fnord::logTrace(
        "cm.logjoin",
        "[dry-run] would write joined item visit: $0",
        jiv_json);
#endif
  } else {
    feeds->joined_item_visits_feed_writer->appendEntry(jiv_json);
  }
}

void LogJoin::onItemVisit(
    const TrackedSession& session,
    const TrackedItemVisit& item_visit,
    const TrackedQuery& query) {
  stat_joined_item_visits_.incr(1);

  JoinedItemVisit jiv;
  jiv.customer = session.customer_key;
  jiv.uid = session.uid;
  jiv.time = item_visit.time;
  jiv.item = item_visit.item;
  jiv.attrs = item_visit.attrs;

  for (const auto& a : session.attrs) {
    jiv.attrs.emplace_back("s!" + a);
  }

  for (const auto& a : query.attrs) {
    jiv.attrs.emplace_back("q!" + a);
  }

  auto jiv_json = json::toJSONString(jiv);
  auto feeds = getFeedsForCustomer(jiv.customer);

  if (dry_run_) {
#ifndef NDEBUG
    fnord::logTrace(
        "cm.logjoin",
        "[dry-run] would write joined item visit: $0",
        jiv_json);
#endif
  } else {
    feeds->joined_item_visits_feed_writer->appendEntry(jiv_json);
  }
}
*/

} // namespace cm

<|endoftext|>


<commit_before>/***********************************************************************
 test_wnp.cpp - Tests WindowsNamedPipeConnection::is_wnp().  This test
 	can only fail on Windows!  It succeeds when built for anything else.

 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ 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 MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>

#include <iostream>
#include <sstream>

int
main()
{
#if defined(MYSQLPP_PLATFORM_WINDOWS)
	if (!WindowsNamedPipeConnection::is_wnp(".")) {
		std::cerr << "Failed to identify Windows named pipe" << std::endl;

	}
	else if (WindowsNamedPipeConnection::is_wnp("bogus")) {
		std::cerr << "Failed to fail for bogus named pipe" << std::endl;
	}
	else if (WindowsNamedPipeConnection::is_wnp(0)) {
		std::cerr << "Failed to fail for null named pipe" << std::endl;
	}
	else {
		return 0;
	}

	return 1;
#else
	return 0;
#endif
}
<commit_msg>Fixed a namespace problem in test_wnp.cpp<commit_after>/***********************************************************************
 test_wnp.cpp - Tests WindowsNamedPipeConnection::is_wnp().  This test
 	can only fail on Windows!  It succeeds when built for anything else.

 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ 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 MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>

#include <iostream>
#include <sstream>

int
main()
{
#if defined(MYSQLPP_PLATFORM_WINDOWS)
	if (!mysqlpp::WindowsNamedPipeConnection::is_wnp(".")) {
		std::cerr << "Failed to identify Windows named pipe" << std::endl;

	}
	else if (mysqlpp::WindowsNamedPipeConnection::is_wnp("bogus")) {
		std::cerr << "Failed to fail for bogus named pipe" << std::endl;
	}
	else if (mysqlpp::WindowsNamedPipeConnection::is_wnp(0)) {
		std::cerr << "Failed to fail for null named pipe" << std::endl;
	}
	else {
		return 0;
	}

	return 1;
#else
	return 0;
#endif
}
<|endoftext|>


<commit_before>#include "game_window.h"

bool GameWindow::sdlInitialized = false;

bool GameWindow::initialize() {
	Logger::getInstance()->writeInformation("Initializing graphics");
	if (GameWindow::sdlInitialized) {
		Logger::getInstance()->writeWarning("SDL already initialized");
	} else {
		atexit(SDL_Quit);
		if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
			Logger::getInstance()->writeError("SDL could not initialize!");
			Logger::getInstance()->writeError(SDL_GetError());
			GameWindow::sdlInitialized = false;
		} else {
			GameWindow::sdlInitialized = true;
		}
	}
	return GameWindow::sdlInitialized;
}

GameWindow::GameWindow() {
	this->parser = new ParserYAML(CONFIG_FILE_PATH);
	this->model = NULL;
	this->exit = false;
	this->focus_x = 0;
	this->focus_y = 0;

	Logger::getInstance()->writeInformation("Creating window");

	GameWindow::initialize();
	window = SDL_CreateWindow("Trabajo Práctico 7542",
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		ANCHO_DEFAULT, ALTO_DEFAULT,
		SDL_WINDOW_SHOWN);

	Logger::getInstance()->writeInformation("Creating renderer");
	renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );

	// TODO: IMG_INIT

	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Color: negro opaco
	SDL_RenderClear(renderer); // Limpio pantalla inicialmente
	SDL_RenderPresent( renderer );
}

GameWindow::~GameWindow() {
	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}

	delete parser;
	delete model;

	Logger::getInstance()->writeInformation("Destroying renderer");
	if (renderer != NULL) {
		SDL_DestroyRenderer(renderer);
		renderer = NULL;
	}

	Logger::getInstance()->writeInformation("Destroying window");
	if (window != NULL) {
		Logger::getInstance()->writeWarning("Window never initialized");
		SDL_DestroyWindow(window);
		window = NULL;
	}
}

bool GameWindow::endOfGame(){
	return this->exit;
}

void GameWindow::render(){
	//	Dibujar
	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
	SDL_RenderClear(renderer);
	std::vector<std::shared_ptr<Entity>> entities = this->model->getBoard()->getEntities();
	std::map<std::string,SpriteSheet*>::iterator it;
	SpriteSheet* ss;
	for (std::size_t i =0; i < entities.size(); ++i){
		it = this->spritesSheets.find(entities[i]->name);
		if(it != this->spritesSheets.end()){
			ss = it->second;
			ss->render(entities[i]->getX(), entities[i]->getY(), 0, entities[i]->getDirection() , renderer);
		}
		else
			Logger::getInstance()->writeWarning("No existe SpriteSheet para este tipo de entidad" + entities[i]->name);
	}

	SDL_RenderPresent( renderer );
	return;
}

void GameWindow::restart(){
	//model->restart()	PARA NO TENER Q INSTANCIAR UN NUEVO MODEL
	delete model;

	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}

	init();
}

void GameWindow::init(){
	this->parser->parse();

	this->model = new Game(parser);

	this->spritesSheets["agua"] = new SpriteSheet("resources//agua.png", 0, 0, TILE_HEIGHT_DEFAULT, TILE_WIDTH_DEFAULT,  1, 0, 0, *this);
	this->spritesSheets["pasto"] = new SpriteSheet("resources//pasto.png", 0, 0, TILE_HEIGHT_DEFAULT, TILE_WIDTH_DEFAULT, 1, 0, 0, *this);
	this->spritesSheets["piedra"] = new SpriteSheet("resources//piedra.png", 0, 0, TILE_HEIGHT_DEFAULT, TILE_WIDTH_DEFAULT, 1, 0, 0, *this);
	this->spritesSheets["chancho"] = new SpriteSheet("resources//chanchos.png", 10, 10, 44, 48, 15, 0, 1, *this);
}

void GameWindow::update(){
	model->update();
	return;
}

void GameWindow::processInput(){
	//	Procesar input del usuario
	if(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		if(EventHandler::getInstance()->getEvent()->type == SDL_QUIT )
			this->exit = true;
		if(EventHandler::getInstance()->getEvent()->type == SDL_KEYDOWN ){
			Logger::getInstance()->writeInformation("Teclado");
			if(EventHandler::getInstance()->getEvent()->key.keysym.sym == SDLK_r){
				restart();
			}
		}
		if( EventHandler::getInstance()->getEvent()->type == SDL_MOUSEBUTTONUP ){
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT )
				Logger::getInstance()->writeInformation("Boton Izquierdo");
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT)
				Logger::getInstance()->writeInformation("Boton derecho");
		}
	}
}

int GameWindow::start(){
	init();

	Uint8 mouse_b;
	int mouse_x, mouse_y;
	const double SCROLL_SPEED = 1;

	while (!endOfGame())
	{
		double ds = SCROLL_SPEED * model->getBoard()->dt / 1000; //deltascroll
		SDL_GetMouseState(&mouse_x, &mouse_y);

		if(mouse_x <= MARGEN_PANTALLA_DEFAULT)
		{
			focus_x -= ds;
			focus_y += ds;
			Logger::getInstance()->writeInformation("Mouse izquierda");
		}
		else if(mouse_x >= ANCHO_DEFAULT - MARGEN_PANTALLA_DEFAULT){
			focus_x += ds;
			focus_y -= ds;
			Logger::getInstance()->writeInformation("Mouse derecha");
		}
		if(mouse_y <= MARGEN_PANTALLA_DEFAULT)
		{
			focus_x -= ds;
			focus_y -= ds;
			Logger::getInstance()->writeInformation("Mouse arriba");
		}
		if(mouse_y >= ALTO_DEFAULT - MARGEN_PANTALLA_DEFAULT)
		{
			focus_x += ds;
			focus_y += ds;
			Logger::getInstance()->writeInformation("Mouse abajo");
		}
		auto & board = *(model->getBoard());
		if(focus_x >= board.sizeX - 1){
			focus_x = board.sizeX - 1;
		}else if(focus_x < 0){
			focus_x = 0;
		}

		if(focus_y >= board.sizeY - 1){
			focus_y = board.sizeY - 1;
		}else if(focus_y < 0){
			focus_y = 0;
		}

		processInput();
		update();
		render();

		SDL_Delay(100); // TODO: Optimizar, sacar hardcodeo
	}
	return 0;
}

<commit_msg>inclusion de velocidades en el scroll.<commit_after>#include "game_window.h"

bool GameWindow::sdlInitialized = false;

bool GameWindow::initialize() {
	Logger::getInstance()->writeInformation("Initializing graphics");
	if (GameWindow::sdlInitialized) {
		Logger::getInstance()->writeWarning("SDL already initialized");
	} else {
		atexit(SDL_Quit);
		if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
			Logger::getInstance()->writeError("SDL could not initialize!");
			Logger::getInstance()->writeError(SDL_GetError());
			GameWindow::sdlInitialized = false;
		} else {
			GameWindow::sdlInitialized = true;
		}
	}
	return GameWindow::sdlInitialized;
}

GameWindow::GameWindow() {
	this->parser = new ParserYAML(CONFIG_FILE_PATH);
	this->model = NULL;
	this->exit = false;
	this->focus_x = 0;
	this->focus_y = 0;

	Logger::getInstance()->writeInformation("Creating window");

	GameWindow::initialize();
	window = SDL_CreateWindow("Trabajo Práctico 7542",
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		ANCHO_DEFAULT, ALTO_DEFAULT,
		SDL_WINDOW_SHOWN);

	Logger::getInstance()->writeInformation("Creating renderer");
	renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );

	// TODO: IMG_INIT

	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Color: negro opaco
	SDL_RenderClear(renderer); // Limpio pantalla inicialmente
	SDL_RenderPresent( renderer );
}

GameWindow::~GameWindow() {
	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}

	delete parser;
	delete model;

	Logger::getInstance()->writeInformation("Destroying renderer");
	if (renderer != NULL) {
		SDL_DestroyRenderer(renderer);
		renderer = NULL;
	}

	Logger::getInstance()->writeInformation("Destroying window");
	if (window != NULL) {
		Logger::getInstance()->writeWarning("Window never initialized");
		SDL_DestroyWindow(window);
		window = NULL;
	}
}

bool GameWindow::endOfGame(){
	return this->exit;
}

void GameWindow::render(){
	//	Dibujar
	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
	SDL_RenderClear(renderer);
	std::vector<std::shared_ptr<Entity>> entities = this->model->getBoard()->getEntities();
	std::map<std::string,SpriteSheet*>::iterator it;
	SpriteSheet* ss;
	for (std::size_t i =0; i < entities.size(); ++i){
		it = this->spritesSheets.find(entities[i]->name);
		if(it != this->spritesSheets.end()){
			ss = it->second;
			ss->render(entities[i]->getX(), entities[i]->getY(), 0, entities[i]->getDirection() , renderer);
		}
		else
			Logger::getInstance()->writeWarning("No existe SpriteSheet para este tipo de entidad" + entities[i]->name);
	}

	SDL_RenderPresent( renderer );
	return;
}

void GameWindow::restart(){
	//model->restart()	PARA NO TENER Q INSTANCIAR UN NUEVO MODEL
	delete model;

	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}

	init();
}

void GameWindow::init(){
	this->parser->parse();

	this->model = new Game(parser);

	this->spritesSheets["agua"] = new SpriteSheet("resources//agua.png", 0, 0, TILE_HEIGHT_DEFAULT, TILE_WIDTH_DEFAULT,  1, 0, 0, *this);
	this->spritesSheets["pasto"] = new SpriteSheet("resources//pasto.png", 0, 0, TILE_HEIGHT_DEFAULT, TILE_WIDTH_DEFAULT, 1, 0, 0, *this);
	this->spritesSheets["piedra"] = new SpriteSheet("resources//piedra.png", 0, 0, TILE_HEIGHT_DEFAULT, TILE_WIDTH_DEFAULT, 1, 0, 0, *this);
	this->spritesSheets["chancho"] = new SpriteSheet("resources//chanchos.png", 10, 10, 44, 48, 15, 0, 1, *this);
}

void GameWindow::update(){
	model->update();
	return;
}

void GameWindow::processInput(){
	//	Procesar input del usuario
	if(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		if(EventHandler::getInstance()->getEvent()->type == SDL_QUIT )
			this->exit = true;
		if(EventHandler::getInstance()->getEvent()->type == SDL_KEYDOWN ){
			Logger::getInstance()->writeInformation("Teclado");
			if(EventHandler::getInstance()->getEvent()->key.keysym.sym == SDLK_r){
				restart();
			}
		}
		if( EventHandler::getInstance()->getEvent()->type == SDL_MOUSEBUTTONUP ){
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT )
				Logger::getInstance()->writeInformation("Boton Izquierdo");
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT)
				Logger::getInstance()->writeInformation("Boton derecho");
		}
	}
}

int GameWindow::start(){
	init();

	Uint8 mouse_b;
	int mouse_x, mouse_y;
	const double SCROLL_SPEED = 5;

	while (!endOfGame())
	{
		double ds = SCROLL_SPEED * model->getBoard()->dt / 1000; //deltascroll
		SDL_GetMouseState(&mouse_x, &mouse_y);

		if(mouse_x <= MARGEN_PANTALLA_DEFAULT)
		{
			double dsi = (1.0 - ((double)mouse_x / (double)MARGEN_PANTALLA_DEFAULT)) * ds;

			focus_x -= dsi;
			focus_y += dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia la izquierda");
		}
		else if(mouse_x >= ANCHO_DEFAULT - MARGEN_PANTALLA_DEFAULT){

			double dsi = ((double)(mouse_x + MARGEN_PANTALLA_DEFAULT - ANCHO_DEFAULT)/(double)MARGEN_PANTALLA_DEFAULT) * ds;

			focus_x += dsi;
			focus_y -= dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia la derecha");
		}
		if(mouse_y <= MARGEN_PANTALLA_DEFAULT)
		{
			double dsi = (1.0 - ((double)mouse_y / (double)MARGEN_PANTALLA_DEFAULT)) * ds;
			focus_x -= dsi;
			focus_y -= dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia arriba");
		}
		if(mouse_y >= ALTO_DEFAULT - MARGEN_PANTALLA_DEFAULT)
		{
			double dsi = ((double)(mouse_y + MARGEN_PANTALLA_DEFAULT - ALTO_DEFAULT)/(double)MARGEN_PANTALLA_DEFAULT) * ds;

			focus_x += dsi;
			focus_y += dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia abajo");
		}

		auto & board = *(model->getBoard());

		if(focus_x >= board.sizeX - 1){
			focus_x = board.sizeX - 1;
		}
		else if(focus_x < 0){
			focus_x = 0;
		}

		if(focus_y >= board.sizeY - 1){
			focus_y = board.sizeY - 1;
		}else if(focus_y < 0){
			focus_y = 0;
		}

		processInput();
		update();
		render();

		SDL_Delay(100); // TODO: Optimizar, sacar hardcodeo
	}
	return 0;
}

<|endoftext|>


<commit_before>#include "athena/FileWriter.hpp"
#include "win32_largefilewrapper.h"

namespace athena::io {
FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr)
: m_fileHandle(0), m_globalErr(globalErr) {
  m_filename = utility::utf8ToWide(filename);
  open(overwrite);
}

FileWriter::FileWriter(std::wstring_view filename, bool overwrite, bool globalErr)
: m_fileHandle(0), m_globalErr(globalErr) {
  m_filename = filename;
  open(overwrite);
}

FileWriter::~FileWriter() {
  if (isOpen())
    close();
}

void FileWriter::open(bool overwrite) {
  int attempt = 0;
  do {
    if (overwrite) {
      std::wstring tmpFilename = m_filename + L'~';
#if WINDOWS_STORE
      m_fileHandle = CreateFile2(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, CREATE_ALWAYS, nullptr);
#else
      m_fileHandle = CreateFileW(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS,
                                 FILE_ATTRIBUTE_NORMAL, nullptr);
#endif
    } else {
#if WINDOWS_STORE
      m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, OPEN_ALWAYS, nullptr);
#else
      m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS,
                                 FILE_ATTRIBUTE_NORMAL, nullptr);
#endif
    }
  } while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100);

  if (m_fileHandle == INVALID_HANDLE_VALUE) {
    m_fileHandle = 0;
    if (m_globalErr)
      atError(fmt("Unable to open file '{}'"), filename());
    setError();
    return;
  }

  // reset error
  m_hasError = false;
}

void FileWriter::close() {
  if (!m_fileHandle) {
    if (m_globalErr)
      atError(fmt("Cannot close an unopened stream"));
    setError();
    return;
  }

  FlushFileBuffers(m_fileHandle);
  CloseHandle(m_fileHandle);
  m_fileHandle = 0;

  std::wstring tmpFilename = m_filename + L'~';
  MoveFileExW(tmpFilename.c_str(), m_filename.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
}

void FileWriter::seek(atInt64 pos, SeekOrigin origin) {
  if (!isOpen()) {
    if (m_globalErr)
      atError(fmt("Unable to seek in file, not open"));
    setError();
    return;
  }

  LARGE_INTEGER li;
  li.QuadPart = pos;
  if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin))) {
    if (m_globalErr)
      atError(fmt("Unable to seek in file"));
    setError();
  }
}

atUint64 FileWriter::position() const {
  LARGE_INTEGER li = {};
  LARGE_INTEGER res;
  SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT);
  return static_cast<atUint64>(res.QuadPart);
}

atUint64 FileWriter::length() const { return utility::fileSize(m_filename); }

void FileWriter::writeUBytes(const atUint8* data, atUint64 len) {
  if (!isOpen()) {
    if (m_globalErr)
      atError(fmt("File not open for writing"));
    setError();
    return;
  }

  DWORD ret = 0;
  WriteFile(m_fileHandle, data, len, &ret, nullptr);
  if (ret != len) {
    if (m_globalErr)
      atError(fmt("Unable to write to stream"));
    setError();
  }
}

} // namespace athena::io
<commit_msg>FileWriterWin32: Handle large files within writeUBytes<commit_after>#include "athena/FileWriter.hpp"

#include <algorithm>
#include <limits>

#undef min
#undef max

namespace athena::io {
FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr)
: m_fileHandle(0), m_globalErr(globalErr) {
  m_filename = utility::utf8ToWide(filename);
  open(overwrite);
}

FileWriter::FileWriter(std::wstring_view filename, bool overwrite, bool globalErr)
: m_fileHandle(0), m_globalErr(globalErr) {
  m_filename = filename;
  open(overwrite);
}

FileWriter::~FileWriter() {
  if (isOpen())
    close();
}

void FileWriter::open(bool overwrite) {
  int attempt = 0;
  do {
    if (overwrite) {
      std::wstring tmpFilename = m_filename + L'~';
#if WINDOWS_STORE
      m_fileHandle = CreateFile2(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, CREATE_ALWAYS, nullptr);
#else
      m_fileHandle = CreateFileW(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS,
                                 FILE_ATTRIBUTE_NORMAL, nullptr);
#endif
    } else {
#if WINDOWS_STORE
      m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, OPEN_ALWAYS, nullptr);
#else
      m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS,
                                 FILE_ATTRIBUTE_NORMAL, nullptr);
#endif
    }
  } while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100);

  if (m_fileHandle == INVALID_HANDLE_VALUE) {
    m_fileHandle = 0;
    if (m_globalErr)
      atError(fmt("Unable to open file '{}'"), filename());
    setError();
    return;
  }

  // reset error
  m_hasError = false;
}

void FileWriter::close() {
  if (!m_fileHandle) {
    if (m_globalErr)
      atError(fmt("Cannot close an unopened stream"));
    setError();
    return;
  }

  FlushFileBuffers(m_fileHandle);
  CloseHandle(m_fileHandle);
  m_fileHandle = 0;

  std::wstring tmpFilename = m_filename + L'~';
  MoveFileExW(tmpFilename.c_str(), m_filename.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
}

void FileWriter::seek(atInt64 pos, SeekOrigin origin) {
  if (!isOpen()) {
    if (m_globalErr)
      atError(fmt("Unable to seek in file, not open"));
    setError();
    return;
  }

  LARGE_INTEGER li;
  li.QuadPart = pos;
  if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin))) {
    if (m_globalErr)
      atError(fmt("Unable to seek in file"));
    setError();
  }
}

atUint64 FileWriter::position() const {
  LARGE_INTEGER li = {};
  LARGE_INTEGER res;
  SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT);
  return static_cast<atUint64>(res.QuadPart);
}

atUint64 FileWriter::length() const { return utility::fileSize(m_filename); }

void FileWriter::writeUBytes(const atUint8* data, atUint64 len) {
  if (!isOpen()) {
    if (m_globalErr) {
      atError(fmt("File not open for writing"));
    }
    setError();
    return;
  }

  atUint64 remaining = len;
  do {
    const auto toWrite = static_cast<DWORD>(std::min(remaining, atUint64{std::numeric_limits<DWORD>::max()}));
    DWORD written = 0;

    if (WriteFile(m_fileHandle, data, toWrite, &written, nullptr) == FALSE) {
      if (m_globalErr) {
        atError(fmt("Unable to write to file"));
      }
      setError();
      return;
    }

    remaining -= written;
    data += written;
  } while (remaining != 0);
}

} // namespace athena::io
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// schema.cpp
//
// Identification: src/backend/catalog/schema.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <cassert>
#include <algorithm>
#include <sstream>

#include "backend/catalog/schema.h"

namespace peloton {
namespace catalog {

// Helper function for creating TupleSchema
void Schema::CreateTupleSchema(const std::vector<ValueType> &column_types,
                               const std::vector<oid_t> &column_lengths,
                               const std::vector<std::string> &column_names,
                               const std::vector<bool> &is_inlined) {
  bool tup_is_inlined = true;
  oid_t num_columns = column_types.size();
  oid_t column_offset = 0;

  for (oid_t column_itr = 0; column_itr < num_columns; column_itr++) {
    Column column(column_types[column_itr], column_lengths[column_itr],
                  column_names[column_itr], is_inlined[column_itr],
                  column_offset);

    column_offset += column.fixed_length;

    columns.push_back(column);

    if (is_inlined[column_itr] == false) {
      tup_is_inlined = false;
      uninlined_columns.push_back(column_itr);
    }
  }

  length = column_offset;
  tuple_is_inlined = tup_is_inlined;

  column_count = columns.size();
  uninlined_column_count = uninlined_columns.size();
}

// Construct schema from vector of Column
Schema::Schema(const std::vector<Column> &columns)
    : length(0), tuple_is_inlined(false) {
  oid_t column_count = columns.size();

  std::vector<ValueType> column_types;
  std::vector<oid_t> column_lengths;
  std::vector<std::string> column_names;
  std::vector<bool> is_inlined;

  for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
    column_types.push_back(columns[column_itr].column_type);

    if (columns[column_itr].is_inlined)
      column_lengths.push_back(columns[column_itr].fixed_length);
    else
      column_lengths.push_back(columns[column_itr].variable_length);

    column_names.push_back(columns[column_itr].column_name);
    is_inlined.push_back(columns[column_itr].is_inlined);
  }

  CreateTupleSchema(column_types, column_lengths, column_names, is_inlined);

  // Add constraints
  for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
    for (auto constraint : columns[column_itr].constraints)
      AddConstraint(column_itr, constraint);
  }
}

// Copy schema
Schema *Schema::CopySchema(const Schema *schema) {
  oid_t column_count = schema->GetColumnCount();
  std::vector<oid_t> set;

  for (oid_t column_itr = 0; column_itr < column_count; column_itr++)
    set.push_back(column_itr);

  return CopySchema(schema, set);
}

// Copy subset of columns in the given schema
Schema *Schema::CopySchema(const Schema *schema,
                           const std::vector<oid_t> &set) {
  oid_t column_count = schema->GetColumnCount();
  std::vector<Column> columns;

  for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
    // If column exists in set
    if (std::find(set.begin(), set.end(), column_itr) != set.end()) {
      columns.push_back(schema->columns[column_itr]);
    }
  }

  Schema *ret_schema = new Schema(columns);
  return ret_schema;
}

// Append two schema objects
Schema *Schema::AppendSchema(Schema *first, Schema *second) {
  return AppendSchemaPtrList({first, second});
}

// Append subset of columns in the two given schemas
Schema *Schema::AppendSchema(Schema *first, std::vector<oid_t> &first_set,
                             Schema *second, std::vector<oid_t> &second_set) {
  const std::vector<Schema *> schema_list({first, second});
  const std::vector<std::vector<oid_t>> subsets({first_set, second_set});
  return AppendSchemaPtrList(schema_list, subsets);
}

// Append given schemas.
Schema *Schema::AppendSchemaList(std::vector<Schema> &schema_list) {
  // All we do here is convert vector<Schema> to vector<Schema *>.
  // This is a convenience function.
  std::vector<Schema *> schema_ptr_list;
  for (unsigned int i = 0; i < schema_list.size(); i++) {
    schema_ptr_list.push_back(&schema_list[i]);
  }
  return AppendSchemaPtrList(schema_ptr_list);
}

// Append given schemas.
Schema *Schema::AppendSchemaPtrList(const std::vector<Schema *> &schema_list) {
  std::vector<std::vector<oid_t>> subsets;

  for (unsigned int i = 0; i < schema_list.size(); i++) {
    unsigned int column_count = schema_list[i]->GetColumnCount();
    std::vector<oid_t> subset;
    for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
      subset.push_back(column_itr);
    }
    subsets.push_back(subset);
  }

  return AppendSchemaPtrList(schema_list, subsets);
}

// Append subsets of columns in the given schemas.
Schema *Schema::AppendSchemaPtrList(
    const std::vector<Schema *> &schema_list,
    const std::vector<std::vector<oid_t>> &subsets) {
  assert(schema_list.size() == subsets.size());

  std::vector<Column> columns;
  for (unsigned int i = 0; i < schema_list.size(); i++) {
    Schema *schema = schema_list[i];
    const std::vector<oid_t> &subset = subsets[i];
    unsigned int column_count = schema->GetColumnCount();

    for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
      // If column exists in set.
      if (std::find(subset.begin(), subset.end(), column_itr) != subset.end()) {
        columns.push_back(schema->columns[column_itr]);
      }
    }
  }

  Schema *ret_schema = new Schema(columns);

  return ret_schema;
}

// Get a string representation of this schema for debugging
std::ostream &operator<<(std::ostream &os, const Schema &schema) {
  os << "\tSchema :: "
     << " column_count = " << schema.column_count
     << " is_inlined = " << schema.tuple_is_inlined << ","
     << " length = " << schema.length << ","
     << " uninlined_column_count = " << schema.uninlined_column_count
     << std::endl;

  for (oid_t column_itr = 0; column_itr < schema.column_count; column_itr++) {
    os << "\t Column " << column_itr << " :: " << schema.columns[column_itr];
  }

  return os;
}

// Compare two schemas
bool Schema::operator==(const Schema &other) const {
  if (other.GetColumnCount() != GetColumnCount() ||
      other.GetUninlinedColumnCount() != GetUninlinedColumnCount() ||
      other.IsInlined() != IsInlined()) {
    return false;
  }

  for (oid_t column_itr = 0; column_itr < other.GetColumnCount();
       column_itr++) {
    const Column &column_info = other.GetColumn(column_itr);
    const Column &other_column_info = GetColumn(column_itr);

    if (column_info != other_column_info) {
      return false;
    }
  }

  return true;
}

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

}  // End catalog namespace
}  // End peloton namespace
<commit_msg>avoid copy<commit_after>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// schema.cpp
//
// Identification: src/backend/catalog/schema.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <cassert>
#include <algorithm>
#include <sstream>

#include "backend/catalog/schema.h"

namespace peloton {
namespace catalog {

// Helper function for creating TupleSchema
void Schema::CreateTupleSchema(const std::vector<ValueType> &column_types,
                               const std::vector<oid_t> &column_lengths,
                               const std::vector<std::string> &column_names,
                               const std::vector<bool> &is_inlined) {
  bool tup_is_inlined = true;
  oid_t num_columns = column_types.size();
  oid_t column_offset = 0;

  for (oid_t column_itr = 0; column_itr < num_columns; column_itr++) {
    Column column(column_types[column_itr], column_lengths[column_itr],
                  column_names[column_itr], is_inlined[column_itr],
                  column_offset);

    column_offset += column.fixed_length;

    columns.push_back(std::move(column));

    if (is_inlined[column_itr] == false) {
      tup_is_inlined = false;
      uninlined_columns.push_back(column_itr);
    }
  }

  length = column_offset;
  tuple_is_inlined = tup_is_inlined;

  column_count = columns.size();
  uninlined_column_count = uninlined_columns.size();
}

// Construct schema from vector of Column
Schema::Schema(const std::vector<Column> &columns)
    : length(0), tuple_is_inlined(false) {
  oid_t column_count = columns.size();

  std::vector<ValueType> column_types;
  std::vector<oid_t> column_lengths;
  std::vector<std::string> column_names;
  std::vector<bool> is_inlined;

  for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
    column_types.push_back(columns[column_itr].column_type);

    if (columns[column_itr].is_inlined)
      column_lengths.push_back(columns[column_itr].fixed_length);
    else
      column_lengths.push_back(columns[column_itr].variable_length);

    column_names.push_back(columns[column_itr].column_name);
    is_inlined.push_back(columns[column_itr].is_inlined);
  }

  CreateTupleSchema(column_types, column_lengths, column_names, is_inlined);

  // Add constraints
  for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
    for (auto constraint : columns[column_itr].constraints)
      AddConstraint(column_itr, constraint);
  }
}

// Copy schema
Schema *Schema::CopySchema(const Schema *schema) {
  oid_t column_count = schema->GetColumnCount();
  std::vector<oid_t> set;

  for (oid_t column_itr = 0; column_itr < column_count; column_itr++)
    set.push_back(column_itr);

  return CopySchema(schema, set);
}

// Copy subset of columns in the given schema
Schema *Schema::CopySchema(const Schema *schema,
                           const std::vector<oid_t> &set) {
  oid_t column_count = schema->GetColumnCount();
  std::vector<Column> columns;

  for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
    // If column exists in set
    if (std::find(set.begin(), set.end(), column_itr) != set.end()) {
      columns.push_back(schema->columns[column_itr]);
    }
  }

  Schema *ret_schema = new Schema(columns);
  return ret_schema;
}

// Append two schema objects
Schema *Schema::AppendSchema(Schema *first, Schema *second) {
  return AppendSchemaPtrList({first, second});
}

// Append subset of columns in the two given schemas
Schema *Schema::AppendSchema(Schema *first, std::vector<oid_t> &first_set,
                             Schema *second, std::vector<oid_t> &second_set) {
  const std::vector<Schema *> schema_list({first, second});
  const std::vector<std::vector<oid_t>> subsets({first_set, second_set});
  return AppendSchemaPtrList(schema_list, subsets);
}

// Append given schemas.
Schema *Schema::AppendSchemaList(std::vector<Schema> &schema_list) {
  // All we do here is convert vector<Schema> to vector<Schema *>.
  // This is a convenience function.
  std::vector<Schema *> schema_ptr_list;
  for (unsigned int i = 0; i < schema_list.size(); i++) {
    schema_ptr_list.push_back(&schema_list[i]);
  }
  return AppendSchemaPtrList(schema_ptr_list);
}

// Append given schemas.
Schema *Schema::AppendSchemaPtrList(const std::vector<Schema *> &schema_list) {
  std::vector<std::vector<oid_t>> subsets;

  for (unsigned int i = 0; i < schema_list.size(); i++) {
    unsigned int column_count = schema_list[i]->GetColumnCount();
    std::vector<oid_t> subset;
    for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
      subset.push_back(column_itr);
    }
    subsets.push_back(subset);
  }

  return AppendSchemaPtrList(schema_list, subsets);
}

// Append subsets of columns in the given schemas.
Schema *Schema::AppendSchemaPtrList(
    const std::vector<Schema *> &schema_list,
    const std::vector<std::vector<oid_t>> &subsets) {
  assert(schema_list.size() == subsets.size());

  std::vector<Column> columns;
  for (unsigned int i = 0; i < schema_list.size(); i++) {
    Schema *schema = schema_list[i];
    const std::vector<oid_t> &subset = subsets[i];
    unsigned int column_count = schema->GetColumnCount();

    for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
      // If column exists in set.
      if (std::find(subset.begin(), subset.end(), column_itr) != subset.end()) {
        columns.push_back(schema->columns[column_itr]);
      }
    }
  }

  Schema *ret_schema = new Schema(columns);

  return ret_schema;
}

// Get a string representation of this schema for debugging
std::ostream &operator<<(std::ostream &os, const Schema &schema) {
  os << "\tSchema :: "
     << " column_count = " << schema.column_count
     << " is_inlined = " << schema.tuple_is_inlined << ","
     << " length = " << schema.length << ","
     << " uninlined_column_count = " << schema.uninlined_column_count
     << std::endl;

  for (oid_t column_itr = 0; column_itr < schema.column_count; column_itr++) {
    os << "\t Column " << column_itr << " :: " << schema.columns[column_itr];
  }

  return os;
}

// Compare two schemas
bool Schema::operator==(const Schema &other) const {
  if (other.GetColumnCount() != GetColumnCount() ||
      other.GetUninlinedColumnCount() != GetUninlinedColumnCount() ||
      other.IsInlined() != IsInlined()) {
    return false;
  }

  for (oid_t column_itr = 0; column_itr < other.GetColumnCount();
       column_itr++) {
    const Column &column_info = other.GetColumn(column_itr);
    const Column &other_column_info = GetColumn(column_itr);

    if (column_info != other_column_info) {
      return false;
    }
  }

  return true;
}

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

}  // End catalog namespace
}  // End peloton namespace
<|endoftext|>


<commit_before>#include "mainwindow.h"

#include <QLabel>
#include <QDockWidget>
#include <QSettings>
#include <QAction>
#include <QMenuBar>
#include <QMenu>
#include <QFile>
#include <QMessageBox>
#include <QFileDialog>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // menu - file
    QMenu *menuFile = new QMenu("File", this);
    this->menuBar()->addMenu(menuFile);

    // action - new block
    QAction *actNewBlock = new QAction("new block", this);
    menuFile->addAction(actNewBlock);
    actNewBlock->setShortcut(Qt::Key_N | Qt::CTRL);
    connect(actNewBlock, SIGNAL(triggered(bool)), this, SLOT(slotActionNewBlock()));

    // action - save
    QAction *actSave = new QAction("save block", this);
    menuFile->addAction(actSave);
    actSave->setShortcut(Qt::Key_S | Qt::CTRL);
    connect(actSave, SIGNAL(triggered(bool)), this, SLOT(slotActionSave()));

    // action - save as
    QAction *actSaveAs = new QAction("save block as", this);
    menuFile->addAction(actSaveAs);
    actSaveAs->setShortcut(Qt::Key_S | Qt::CTRL | Qt::SHIFT);
    connect(actSaveAs, SIGNAL(triggered(bool)), this, SLOT(slotActionSaveAs()));

    // action - quit
    QAction *actQuit = new QAction("quit", this);
    menuFile->addAction(actQuit);
    actQuit->setShortcut(Qt::Key_Q | Qt::CTRL);
    connect(actQuit, SIGNAL(triggered(bool)), this, SLOT(slotActionQuit()));

    // central widget
    this->widgetMain = new QTabWidget(this);
    this->setCentralWidget(this->widgetMain);

    // block browser
    this->blockBrowser = new BlockBrowser(this);
    connect(this->blockBrowser, SIGNAL(signalFileOpen(QString)), this, SLOT(slotFileOpen(QString)));

    // block browser dock
    QDockWidget *dock = new QDockWidget("", this);
    dock->setObjectName("BlockBrowser");
    dock->setAllowedAreas(Qt::LeftDockWidgetArea);
    dock->setWidget(this->blockBrowser);
    dock->setFloating(false);
    dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
    this->addDockWidget(Qt::LeftDockWidgetArea, dock);

    // restore window state
    QSettings s;
    this->restoreState(s.value("Mainwindow/State").toByteArray());
    this->restoreGeometry(s.value("MainWindow/Geometry").toByteArray());
}

MainWindow::~MainWindow()
{
    // save window state
    QSettings s;
    s.setValue("MainWindow/State", this->saveState());
    s.setValue("MainWindow/Geometry", this->saveGeometry());
}

void MainWindow::slotFileOpen(QString filePath)
{
    // open file
    QFile f(filePath);
    if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QMessageBox::critical(this, "Error", "Cannot open file!");
        return;
    }

    // parse block
    libblockdia::Block * block = libblockdia::Block::parseBlockDef(&f);
    f.close();
    if (!block) {
        QMessageBox::critical(this, "Error", "Error on parsing file!");
        return;
    }

    // remember opened file
    this->openFilePathHash[block] = filePath;

    // Ignore the first change signal for just created block
    // Because instantiating the block causes the signal.
    this->ignoreChangedBlocks.append(block);

    // open new tab for block
    QTabWidget *tw = (QTabWidget *) this->centralWidget();
    int index = tw->addTab(new libblockdia::ViewBlockEditor(block), block->typeId());
    tw->setCurrentIndex(index);

    // catch changes inside the block
    connect(block, SIGNAL(signalSomethingChanged(libblockdia::Block*)), this, SLOT(slotBlockChanged(libblockdia::Block*)));
}

void MainWindow::slotActionNewBlock()
{
    // create new block
    libblockdia::Block *block = new libblockdia::Block(this);
    block->setTypeName("New Block Type *");
    block->setTypeId("NBT");

    // create new block editor
    libblockdia::ViewBlockEditor *bEditor = new libblockdia::ViewBlockEditor(block);

    // add block editor to central widget
    QTabWidget *tw = (QTabWidget *) this->centralWidget();
    int index = tw->addTab(bEditor, block->typeId() + "*");
    tw->setCurrentIndex(index);

    // catch changes inside the block
    connect(block, SIGNAL(signalSomethingChanged(libblockdia::Block*)), this, SLOT(slotBlockChanged(libblockdia::Block*)));
}

void MainWindow::slotActionSave()
{
    // get tab widget
    QTabWidget *tw = (QTabWidget *) this->centralWidget();
    if (tw->count() == 0) return;

    // get objects
    int currentIndex = tw->currentIndex();
    libblockdia::ViewBlockEditor *editor = static_cast<libblockdia::ViewBlockEditor*>(tw->currentWidget());
    libblockdia::Block *block = editor->block();

    QFile *f = Q_NULLPTR;

    // file path is already known
    if (this->openFilePathHash.contains(block)) {
        f = new QFile(this->openFilePathHash[block]);
    }

    // open file dialog
    else {
        QString fileName = QFileDialog::getSaveFileName(this, "Save Block", this->blockBrowser->currentRootPath(), "XML (*.xml)");
        this->openFilePathHash[block] = fileName;
        f = new QFile(fileName);
    }

    // check if file is valid
    if (!f || !f->open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::critical(this, "Error", "Cannot open file for writing!");
    }

    // export block
    block->exportBlockDef(f);

    // close file
    if (f) {
        f->close();
        f->deleteLater();
        f = Q_NULLPTR;
    }

    // update tab text
    tw->setTabText(currentIndex, block->typeId());
}

void MainWindow::slotActionSaveAs()
{
    THIS IS THE CURRENT WORKING LOCATION

    // get tab widget
    QTabWidget *tw = (QTabWidget *) this->centralWidget();
    if (tw->count() == 0) return;

    // get objects
    int currentIndex = tw->currentIndex();
    libblockdia::ViewBlockEditor *editor = static_cast<libblockdia::ViewBlockEditor*>(tw->currentWidget());
    libblockdia::Block *block = editor->block();

    QFile *f = Q_NULLPTR;

    // open file dialog
    QString fileName = QFileDialog::getSaveFileName(this, "Save Block", this->blockBrowser->currentRootPath(), "XML (*.xml)");
    this->openFilePathHash[block] = fileName;
    f = new QFile(fileName);

    // file path is already known
    if (this->openFilePathHash.contains(block)) {
        f = new QFile(this->openFilePathHash[block]);
    }

    // check if file is valid
    if (!f || !f->open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::critical(this, "Error", "Cannot open file for writing!");
    }

    // export block
    block->exportBlockDef(f);

    // close file
    if (f) {
        f->close();
        f->deleteLater();
        f = Q_NULLPTR;
    }

    // update tab text
    tw->setTabText(currentIndex, block->typeId());
}

void MainWindow::slotActionQuit()
{
    this->close();
}

void MainWindow::slotBlockChanged(libblockdia::Block *block)
{
    // check if the block was just created
    // In this case ignore the change signal
    // because it is emitted because of instantiating the block
    if (this->ignoreChangedBlocks.contains(block)) {
        this->ignoreChangedBlocks.removeAll(block);
        return;
    }

    // add astresik to tab name if it contains unsaved changes
    QTabWidget *tw = (QTabWidget *) this->centralWidget();
    for (int i=0; i < tw->count(); ++i) {
        libblockdia::ViewBlockEditor *editor = static_cast<libblockdia::ViewBlockEditor*>(tw->widget(i));
        if (editor->block() == block) {
            tw->setTabText(i, block->typeId() + "*");
        }
    }
}
<commit_msg>finish save as<commit_after>#include "mainwindow.h"

#include <QLabel>
#include <QDockWidget>
#include <QSettings>
#include <QAction>
#include <QMenuBar>
#include <QMenu>
#include <QFile>
#include <QMessageBox>
#include <QFileDialog>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // menu - file
    QMenu *menuFile = new QMenu("File", this);
    this->menuBar()->addMenu(menuFile);

    // action - new block
    QAction *actNewBlock = new QAction("new block", this);
    menuFile->addAction(actNewBlock);
    actNewBlock->setShortcut(Qt::Key_N | Qt::CTRL);
    connect(actNewBlock, SIGNAL(triggered(bool)), this, SLOT(slotActionNewBlock()));

    // action - save
    QAction *actSave = new QAction("save block", this);
    menuFile->addAction(actSave);
    actSave->setShortcut(Qt::Key_S | Qt::CTRL);
    connect(actSave, SIGNAL(triggered(bool)), this, SLOT(slotActionSave()));

    // action - save as
    QAction *actSaveAs = new QAction("save block as", this);
    menuFile->addAction(actSaveAs);
    actSaveAs->setShortcut(Qt::Key_S | Qt::CTRL | Qt::SHIFT);
    connect(actSaveAs, SIGNAL(triggered(bool)), this, SLOT(slotActionSaveAs()));

    // action - quit
    QAction *actQuit = new QAction("quit", this);
    menuFile->addAction(actQuit);
    actQuit->setShortcut(Qt::Key_Q | Qt::CTRL);
    connect(actQuit, SIGNAL(triggered(bool)), this, SLOT(slotActionQuit()));

    // central widget
    this->widgetMain = new QTabWidget(this);
    this->setCentralWidget(this->widgetMain);

    // block browser
    this->blockBrowser = new BlockBrowser(this);
    connect(this->blockBrowser, SIGNAL(signalFileOpen(QString)), this, SLOT(slotFileOpen(QString)));

    // block browser dock
    QDockWidget *dock = new QDockWidget("", this);
    dock->setObjectName("BlockBrowser");
    dock->setAllowedAreas(Qt::LeftDockWidgetArea);
    dock->setWidget(this->blockBrowser);
    dock->setFloating(false);
    dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
    this->addDockWidget(Qt::LeftDockWidgetArea, dock);

    // restore window state
    QSettings s;
    this->restoreState(s.value("Mainwindow/State").toByteArray());
    this->restoreGeometry(s.value("MainWindow/Geometry").toByteArray());
}

MainWindow::~MainWindow()
{
    // save window state
    QSettings s;
    s.setValue("MainWindow/State", this->saveState());
    s.setValue("MainWindow/Geometry", this->saveGeometry());
}

void MainWindow::slotFileOpen(QString filePath)
{
    // open file
    QFile f(filePath);
    if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QMessageBox::critical(this, "Error", "Cannot open file!");
        return;
    }

    // parse block
    libblockdia::Block * block = libblockdia::Block::parseBlockDef(&f);
    f.close();
    if (!block) {
        QMessageBox::critical(this, "Error", "Error on parsing file!");
        return;
    }

    // remember opened file
    this->openFilePathHash[block] = filePath;

    // Ignore the first change signal for just created block
    // Because instantiating the block causes the signal.
    this->ignoreChangedBlocks.append(block);

    // open new tab for block
    QTabWidget *tw = (QTabWidget *) this->centralWidget();
    int index = tw->addTab(new libblockdia::ViewBlockEditor(block), block->typeId());
    tw->setCurrentIndex(index);

    // catch changes inside the block
    connect(block, SIGNAL(signalSomethingChanged(libblockdia::Block*)), this, SLOT(slotBlockChanged(libblockdia::Block*)));
}

void MainWindow::slotActionNewBlock()
{
    // create new block
    libblockdia::Block *block = new libblockdia::Block(this);
    block->setTypeName("New Block Type *");
    block->setTypeId("NBT");

    // create new block editor
    libblockdia::ViewBlockEditor *bEditor = new libblockdia::ViewBlockEditor(block);

    // add block editor to central widget
    QTabWidget *tw = (QTabWidget *) this->centralWidget();
    int index = tw->addTab(bEditor, block->typeId() + "*");
    tw->setCurrentIndex(index);

    // catch changes inside the block
    connect(block, SIGNAL(signalSomethingChanged(libblockdia::Block*)), this, SLOT(slotBlockChanged(libblockdia::Block*)));
}

void MainWindow::slotActionSave()
{
    // get tab widget
    QTabWidget *tw = (QTabWidget *) this->centralWidget();
    if (tw->count() == 0) return;

    // get objects
    int currentIndex = tw->currentIndex();
    libblockdia::ViewBlockEditor *editor = static_cast<libblockdia::ViewBlockEditor*>(tw->currentWidget());
    libblockdia::Block *block = editor->block();

    QFile *f = Q_NULLPTR;

    // file path is already known
    if (this->openFilePathHash.contains(block)) {
        f = new QFile(this->openFilePathHash[block]);
    }

    // open file dialog
    else {
        QString fileName = QFileDialog::getSaveFileName(this, "Save Block", this->blockBrowser->currentRootPath(), "XML (*.xml)");
        this->openFilePathHash[block] = fileName;
        f = new QFile(fileName);
    }

    // check if file is valid
    if (!f || !f->open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::critical(this, "Error", "Cannot open file for writing!");
    }

    // export block
    block->exportBlockDef(f);

    // close file
    if (f) {
        f->close();
        f->deleteLater();
        f = Q_NULLPTR;
    }

    // update tab text
    tw->setTabText(currentIndex, block->typeId());
}

void MainWindow::slotActionSaveAs()
{
    // get tab widget
    QTabWidget *tw = (QTabWidget *) this->centralWidget();
    if (tw->count() == 0) return;

    // get objects
    int currentIndex = tw->currentIndex();
    libblockdia::ViewBlockEditor *editor = static_cast<libblockdia::ViewBlockEditor*>(tw->currentWidget());
    libblockdia::Block *block = editor->block();

    QFile *f = Q_NULLPTR;

    // open file dialog
    QString fileName = QFileDialog::getSaveFileName(this, "Save Block As", this->blockBrowser->currentRootPath(), "XML (*.xml)");
    this->openFilePathHash[block] = fileName;
    f = new QFile(fileName);

    // file path is already known
    if (this->openFilePathHash.contains(block)) {
        f = new QFile(this->openFilePathHash[block]);
    }

    // check if file is valid
    if (!f || !f->open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::critical(this, "Error", "Cannot open file for writing!");
    }

    // export block
    block->exportBlockDef(f);

    // close file
    if (f) {
        f->close();
        f->deleteLater();
        f = Q_NULLPTR;
    }

    // remember file path
    this->openFilePathHash[block] = fileName;

    // update tab text
    tw->setTabText(currentIndex, block->typeId());
}

void MainWindow::slotActionQuit()
{
    this->close();
}

void MainWindow::slotBlockChanged(libblockdia::Block *block)
{
    // check if the block was just created
    // In this case ignore the change signal
    // because it is emitted because of instantiating the block
    if (this->ignoreChangedBlocks.contains(block)) {
        this->ignoreChangedBlocks.removeAll(block);
        return;
    }

    // add astresik to tab name if it contains unsaved changes
    QTabWidget *tw = (QTabWidget *) this->centralWidget();
    for (int i=0; i < tw->count(); ++i) {
        libblockdia::ViewBlockEditor *editor = static_cast<libblockdia::ViewBlockEditor*>(tw->widget(i));
        if (editor->block() == block) {
            tw->setTabText(i, block->typeId() + "*");
        }
    }
}
<|endoftext|>


<commit_before>/*
 * THE NEW CHRONOTEXT TOOLKIT: https://github.com/arielm/new-chronotext-toolkit
 * COPYRIGHT (C) 2012-2015, ARIEL MALKA ALL RIGHTS RESERVED.
 *
 * THE FOLLOWING SOURCE-CODE IS DISTRIBUTED UNDER THE SIMPLIFIED BSD LICENSE:
 * https://github.com/arielm/new-chronotext-toolkit/blob/master/LICENSE.md
 */

#include "chronotext/utils/Utils.h"

#include "rapidxml/rapidxml_print.hpp"

#if defined(CINDER_ANDROID)
#   include "boost/date_time/local_time/local_time.hpp" // TODO IN FUTURE ANDROID REWORK: REMOVE DEPENDENCY ON boost/date_time
#else
#   include <chrono>
#endif

using namespace std;
using namespace ci;

namespace chr
{
    namespace utils
    {
        template <>
        string readText(InputSource::Ref inputSource)
        {
            /*
             * SUB-OPTIMAL (IDEALLY: TEXT SHOULD BE LOADED "DIRECTLY" INTO STRING-STORAGE
             */
            Buffer buffer(inputSource->loadDataSource());
            return string(static_cast<const char*>(buffer.getData()), buffer.getDataSize());
        }

        template <>
        u16string readText(InputSource::Ref inputSource)
        {
            Buffer buffer(inputSource->loadDataSource());
            const char *begin = static_cast<const char*>(buffer.getData());
            const char *end = begin + buffer.getDataSize();

            u16string result;
            utf8::unchecked::utf8to16(begin, end, back_inserter(result));
            return result;
        }

        template <>
        vector<string> readLines(InputSource::Ref inputSource)
        {
            vector<string> lines;
            IStreamRef in = inputSource->loadDataSource()->createStream();

            while (!in->isEof())
            {
                lines.emplace_back(in->readLine()); // TODO: CHECK IF MOVE-CONSTRUCTION IS ACTUALLY TAKING PLACE
            }

            return lines;
        }

        template <>
        vector<u16string> readLines(InputSource::Ref inputSource)
        {
            vector<u16string> lines;
            IStreamRef in = inputSource->loadDataSource()->createStream();

            while (!in->isEof())
            {
                lines.emplace_back(to<u16string>(in->readLine())); // TODO: CHECK IF MOVE-CONSTRUCTION IS ACTUALLY TAKING PLACE
            }

            return lines;
        }

        vector<string> readInstructions(InputSource::Ref inputSource)
        {
            vector<string> instructions;

            for (const auto &line : readLines<string>(inputSource))
            {
                auto trimmed = boost::algorithm::trim_copy(line);

                if (!trimmed.empty() && !boost::starts_with(trimmed, "#"))
                {
                    instructions.emplace_back(move(trimmed));
                }
            }

            return instructions;
        }

        string readTextFile(const fs::path &filePath)
        {
            fs::ifstream in(filePath, ios::in | ios::binary | ios::ate);

            auto fileSize = in.tellg();
            in.seekg(0, ios::beg);

            string result(fileSize, 0);
            in.read(&result[0], fileSize);

            return result;
        }

        void writeTextFile(const fs::path &filePath, const string &text)
        {
            fs::ofstream out(filePath);
            out << text;
        }

        XmlTree readXmlFile(const fs::path &filePath, XmlTree::ParseOptions parseOptions)
        {
            return XmlTree(readTextFile(filePath), parseOptions);
        }

        void writeXmlFile(const fs::path &filePath, const XmlTree &tree)
        {
            fs::ofstream out(filePath);
            out << *tree.createRapidXmlDoc(true);
        }

        // ---

        namespace time
        {
            uint64_t millisSinceEpoch()
            {
#if defined(CINDER_ANDROID)
                using namespace boost::gregorian;
                using namespace boost::local_time;
                using namespace boost::posix_time;

                auto now = microsec_clock::local_time();
                auto diff = now - ptime(date(1970, 1, 1));
                return diff.total_milliseconds();
#else
                using namespace chrono;

                auto now = system_clock::now();
                auto diff = now.time_since_epoch();
                return duration_cast<milliseconds>(diff).count();
#endif
            }
        }

        namespace format
        {
            /*
             * REFERENCE: http://stackoverflow.com/a/10096779/50335
             */
            const string bytes(int64_t bytes, int precision, const string &separator)
            {
                static const vector<string> abbrevs {"TB", "GB", "MB", "KB"};
                double maximum = pow(1024.0, abbrevs.size());

                double value = fabs(bytes);

                stringstream ss;
                if (bytes < 0) ss << "-";

                for (auto &abbrev : abbrevs)
                {
                    if (value > maximum)
                    {
                        ss << fixed << setprecision(precision);
                        ss << (value / maximum) << separator << abbrev;
                        return ss.str(); // TODO: CONSIDER ADAPTING TO RVO [1/2]
                    }

                    maximum /= 1024;
                }

                ss << value << separator << "B";
                return ss.str(); // TODO: CONSIDER ADAPTING TO RVO [2/2]
            }

            const string duration(double seconds, int precision, const string &separator)
            {
                if (fabs(seconds) >= 60)
                {
                    return time(seconds, true); // TODO: CONSIDER ADAPTING TO RVO [1/3]
                }

                static const vector<string> abbrevs {"s", "ms", "μs"};
                double maximum = pow(1000.0, abbrevs.size());

                double value = fabs(seconds) * maximum;

                stringstream ss;
                if (value < 0) ss << "-";
                ss << fixed << setprecision(precision);

                for (auto &abbrev : abbrevs)
                {
                    if (value > maximum)
                    {
                        ss << (value / maximum) << separator << abbrev;
                        return ss.str(); // TODO: CONSIDER ADAPTING TO RVO [2/3]
                    }

                    maximum /= 1000;
                }

                ss << value << separator << "ns";
                return ss.str(); // TODO: CONSIDER ADAPTING TO RVO [3/3]
            }

            const string time(double seconds, bool rounded)
            {
                int time = fabs(seconds) + (rounded ? 0.5 : 0); // ROUNDING IS NOT APPROPRIATE FOR CLOCKS, SCORES, ETC.
                int hour = time / 3600;

                time = time % 3600;
                int min = time / 60;

                time = time % 60;
                int sec = time;

                stringstream ss;
                if (seconds < 0) ss << "-";
                ss << setfill('0');

                if (hour > 0) ss << hour << ":";
                ss << setw(2) << min << ":";
                ss << setw(2) << sec;

                return ss.str(); // TODO: CONSIDER ADAPTING TO RVO
            }

            const string percent(double ratio, int precision, const string &separator)
            {
                stringstream ss;
                ss << fixed << setprecision(precision);
                ss << (fabs(ratio) * 100) << separator << "%";

                return ss.str(); // TODO: CONSIDER ADAPTING TO RVO
            }
        }
    }
}
<commit_msg>utils.Utils.cpp: REMOVING DEPENDENCY ON boost/date_time IN TOOLKIT (TESTED ON ANDROID...) TODO: REMOVE BOOST DEPENDENCIES IN  os/Task.cpp<commit_after>/*
 * THE NEW CHRONOTEXT TOOLKIT: https://github.com/arielm/new-chronotext-toolkit
 * COPYRIGHT (C) 2012-2015, ARIEL MALKA ALL RIGHTS RESERVED.
 *
 * THE FOLLOWING SOURCE-CODE IS DISTRIBUTED UNDER THE SIMPLIFIED BSD LICENSE:
 * https://github.com/arielm/new-chronotext-toolkit/blob/master/LICENSE.md
 */

#include "chronotext/utils/Utils.h"

#include "rapidxml/rapidxml_print.hpp"

#include <chrono>

using namespace std;
using namespace ci;

namespace chr
{
    namespace utils
    {
        template <>
        string readText(InputSource::Ref inputSource)
        {
            /*
             * SUB-OPTIMAL (IDEALLY: TEXT SHOULD BE LOADED "DIRECTLY" INTO STRING-STORAGE
             */
            Buffer buffer(inputSource->loadDataSource());
            return string(static_cast<const char*>(buffer.getData()), buffer.getDataSize());
        }

        template <>
        u16string readText(InputSource::Ref inputSource)
        {
            Buffer buffer(inputSource->loadDataSource());
            const char *begin = static_cast<const char*>(buffer.getData());
            const char *end = begin + buffer.getDataSize();

            u16string result;
            utf8::unchecked::utf8to16(begin, end, back_inserter(result));
            return result;
        }

        template <>
        vector<string> readLines(InputSource::Ref inputSource)
        {
            vector<string> lines;
            IStreamRef in = inputSource->loadDataSource()->createStream();

            while (!in->isEof())
            {
                lines.emplace_back(in->readLine()); // TODO: CHECK IF MOVE-CONSTRUCTION IS ACTUALLY TAKING PLACE
            }

            return lines;
        }

        template <>
        vector<u16string> readLines(InputSource::Ref inputSource)
        {
            vector<u16string> lines;
            IStreamRef in = inputSource->loadDataSource()->createStream();

            while (!in->isEof())
            {
                lines.emplace_back(to<u16string>(in->readLine())); // TODO: CHECK IF MOVE-CONSTRUCTION IS ACTUALLY TAKING PLACE
            }

            return lines;
        }

        vector<string> readInstructions(InputSource::Ref inputSource)
        {
            vector<string> instructions;

            for (const auto &line : readLines<string>(inputSource))
            {
                auto trimmed = boost::algorithm::trim_copy(line);

                if (!trimmed.empty() && !boost::starts_with(trimmed, "#"))
                {
                    instructions.emplace_back(move(trimmed));
                }
            }

            return instructions;
        }

        string readTextFile(const fs::path &filePath)
        {
            fs::ifstream in(filePath, ios::in | ios::binary | ios::ate);

            auto fileSize = in.tellg();
            in.seekg(0, ios::beg);

            string result(fileSize, 0);
            in.read(&result[0], fileSize);

            return result;
        }

        void writeTextFile(const fs::path &filePath, const string &text)
        {
            fs::ofstream out(filePath);
            out << text;
        }

        XmlTree readXmlFile(const fs::path &filePath, XmlTree::ParseOptions parseOptions)
        {
            return XmlTree(readTextFile(filePath), parseOptions);
        }

        void writeXmlFile(const fs::path &filePath, const XmlTree &tree)
        {
            fs::ofstream out(filePath);
            out << *tree.createRapidXmlDoc(true);
        }

        // ---

        namespace time
        {
            uint64_t millisSinceEpoch()
            {
                using namespace chrono;

                auto now = system_clock::now();
                auto diff = now.time_since_epoch();
                return duration_cast<milliseconds>(diff).count();
            }
        }

        namespace format
        {
            /*
             * REFERENCE: http://stackoverflow.com/a/10096779/50335
             */
            const string bytes(int64_t bytes, int precision, const string &separator)
            {
                static const vector<string> abbrevs {"TB", "GB", "MB", "KB"};
                double maximum = pow(1024.0, abbrevs.size());

                double value = fabs(bytes);

                stringstream ss;
                if (bytes < 0) ss << "-";

                for (auto &abbrev : abbrevs)
                {
                    if (value > maximum)
                    {
                        ss << fixed << setprecision(precision);
                        ss << (value / maximum) << separator << abbrev;
                        return ss.str(); // TODO: CONSIDER ADAPTING TO RVO [1/2]
                    }

                    maximum /= 1024;
                }

                ss << value << separator << "B";
                return ss.str(); // TODO: CONSIDER ADAPTING TO RVO [2/2]
            }

            const string duration(double seconds, int precision, const string &separator)
            {
                if (fabs(seconds) >= 60)
                {
                    return time(seconds, true); // TODO: CONSIDER ADAPTING TO RVO [1/3]
                }

                static const vector<string> abbrevs {"s", "ms", "μs"};
                double maximum = pow(1000.0, abbrevs.size());

                double value = fabs(seconds) * maximum;

                stringstream ss;
                if (value < 0) ss << "-";
                ss << fixed << setprecision(precision);

                for (auto &abbrev : abbrevs)
                {
                    if (value > maximum)
                    {
                        ss << (value / maximum) << separator << abbrev;
                        return ss.str(); // TODO: CONSIDER ADAPTING TO RVO [2/3]
                    }

                    maximum /= 1000;
                }

                ss << value << separator << "ns";
                return ss.str(); // TODO: CONSIDER ADAPTING TO RVO [3/3]
            }

            const string time(double seconds, bool rounded)
            {
                int time = fabs(seconds) + (rounded ? 0.5 : 0); // ROUNDING IS NOT APPROPRIATE FOR CLOCKS, SCORES, ETC.
                int hour = time / 3600;

                time = time % 3600;
                int min = time / 60;

                time = time % 60;
                int sec = time;

                stringstream ss;
                if (seconds < 0) ss << "-";
                ss << setfill('0');

                if (hour > 0) ss << hour << ":";
                ss << setw(2) << min << ":";
                ss << setw(2) << sec;

                return ss.str(); // TODO: CONSIDER ADAPTING TO RVO
            }

            const string percent(double ratio, int precision, const string &separator)
            {
                stringstream ss;
                ss << fixed << setprecision(precision);
                ss << (fabs(ratio) * 100) << separator << "%";

                return ss.str(); // TODO: CONSIDER ADAPTING TO RVO
            }
        }
    }
}
<|endoftext|>