<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This test performs a series false positive checks using a list of URLs
// against a known set of SafeBrowsing data.
//
// It uses a normal SafeBrowsing database to create a bloom filter where it
// looks up all the URLs in the url file. A URL that has a prefix found in the
// bloom filter and found in the database is considered a hit: a valid lookup
// that will result in a gethash request. A URL that has a prefix found in the
// bloom filter but not in the database is a miss: a false positive lookup that
// will result in an unnecessary gethash request.
//
// By varying the size of the bloom filter and using a constant set of
// SafeBrowsing data, we can check a known set of URLs against the filter and
// determine the false positive rate.
//
// False positive calculation usage:
//   $ ./perf_tests.exe --gtest_filter=SafeBrowsingBloomFilter.FalsePositives
//                      --filter-start=<integer>
//                      --filter-steps=<integer>
//                      --filter-verbose
//
//  --filter-start:   The filter multiplier to begin with. This represents the
//                    number of bits per prefix of memory to use in the filter.
//                    The default value is identical to the current SafeBrowsing
//                    database value.
//  --filter-steps:   The number of iterations to run, with each iteration
//                    increasing the filter multiplier by 1. The default value
//                    is 1.
//  --filter-verbose: Used to print out the hit / miss results per URL.
//  --filter-csv:     The URL file contains information about the number of
//                    unique views (the popularity) of each URL. See the format
//                    description below.
//
//
// Hash compute time usage:
//   $ ./perf_tests.exe --gtest_filter=SafeBrowsingBloomFilter.HashTime
//                      --filter-num-checks=<integer>
//
//  --filter-num-checks: The number of hash look ups to perform on the bloom
//                       filter. The default is 10 million.
//
// Data files:
//    chrome/test/data/safe_browsing/filter/database
//    chrome/test/data/safe_browsing/filter/urls
//
// database: A normal SafeBrowsing database.
// urls:     A text file containing a list of URLs, one per line. If the option
//           --filter-csv is specified, the format of each line in the file is
//           <url>,<weight> where weight is an integer indicating the number of
//           unique views for the URL.

#include <algorithm>
#include <fstream>
#include <vector>

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/sha2.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/time.h"
#include "chrome/browser/safe_browsing/bloom_filter.h"
#include "chrome/browser/safe_browsing/safe_browsing_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/sqlite_compiled_statement.h"
#include "chrome/common/sqlite_utils.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::Time;
using base::TimeDelta;

namespace {

// Ensures the SafeBrowsing database is closed properly.
class ScopedPerfDatabase {
 public:
  explicit ScopedPerfDatabase(sqlite3* db) : db_(db) {}
  ~ScopedPerfDatabase() {
    sqlite3_close(db_);
  }

 private:
  sqlite3* db_;

  DISALLOW_COPY_AND_ASSIGN(ScopedPerfDatabase);
};

// Command line flags.
const char kFilterVerbose[] = "filter-verbose";
const char kFilterStart[] = "filter-start";
const char kFilterSteps[] = "filter-steps";
const char kFilterCsv[] = "filter-csv";
const char kFilterNumChecks[] = "filter-num-checks";

// Number of hash checks to make during performance testing.
static const int kNumHashChecks = 10000000;

// Returns the path to the data used in this test, relative to the top of the
// source directory.
FilePath GetFullDataPath() {
  FilePath full_path;
  CHECK(PathService::Get(chrome::DIR_TEST_DATA, &full_path));
  full_path = full_path.Append(FILE_PATH_LITERAL("safe_browsing"));
  full_path = full_path.Append(FILE_PATH_LITERAL("filter"));
  CHECK(file_util::PathExists(full_path));
  return full_path;
}

// Constructs a bloom filter of the appropriate size from the provided prefixes.
void BuildBloomFilter(int size_multiplier,
                      const std::vector<SBPrefix>& prefixes,
                      BloomFilter** bloom_filter) {
  // Create a BloomFilter with the specified size.
  const int key_count = std::max(static_cast<int>(prefixes.size()),
                                 BloomFilter::kBloomFilterMinSize);
  const int filter_size = key_count * size_multiplier;
  *bloom_filter = new BloomFilter(filter_size);

  // Add the prefixes to it.
  for (size_t i = 0; i < prefixes.size(); ++i)
    (*bloom_filter)->Insert(prefixes[i]);

  std::cout << "Bloom filter with prefixes: " << prefixes.size()
            << ", multiplier: " << size_multiplier
            << ", size (bytes): " << (*bloom_filter)->size()
            << std::endl;
}

// Reads the set of add prefixes contained in a SafeBrowsing database into a
// sorted array suitable for fast searching. This takes significantly less time
// to look up a given prefix than performing SQL queries.
bool ReadDatabase(const FilePath& path, std::vector<SBPrefix>* prefixes) {
  FilePath database_file = path.Append(FILE_PATH_LITERAL("database"));
  sqlite3* db = NULL;
  if (sqlite_utils::OpenSqliteDb(database_file, &db) != SQLITE_OK) {
    sqlite3_close(db);
    return false;
  }

  ScopedPerfDatabase database(db);
  scoped_ptr<SqliteStatementCache> sql_cache(new SqliteStatementCache(db));

  // Get the number of items in the add_prefix table.
  std::string sql = "SELECT COUNT(*) FROM add_prefix";
  SQLITE_UNIQUE_STATEMENT(count_statement, *sql_cache, sql.c_str());
  if (!count_statement.is_valid())
    return false;

  if (count_statement->step() != SQLITE_ROW)
    return false;

  const int count = count_statement->column_int(0);

  // Load them into a prefix vector and sort
  prefixes->reserve(count);
  sql = "SELECT prefix FROM add_prefix";
  SQLITE_UNIQUE_STATEMENT(prefix_statement, *sql_cache, sql.c_str());
  if (!prefix_statement.is_valid())
    return false;

  while (prefix_statement->step() == SQLITE_ROW)
    prefixes->push_back(prefix_statement->column_int(0));

  DCHECK(static_cast<int>(prefixes->size()) == count);
  sort(prefixes->begin(), prefixes->end());

  return true;
}

// Generates all legal SafeBrowsing prefixes for the specified URL, and returns
// the set of Prefixes that exist in the bloom filter. The function returns the
// number of host + path combinations checked.
int GeneratePrefixHits(const std::string url,
                       BloomFilter* bloom_filter,
                       std::vector<SBPrefix>* prefixes) {
  GURL url_check(url);
  std::vector<std::string> hosts;
  if (url_check.HostIsIPAddress()) {
    hosts.push_back(url_check.host());
  } else {
    safe_browsing_util::GenerateHostsToCheck(url_check, &hosts);
  }

  std::vector<std::string> paths;
  safe_browsing_util::GeneratePathsToCheck(url_check, &paths);

  for (size_t i = 0; i < hosts.size(); ++i) {
    for (size_t j = 0; j < paths.size(); ++j) {
      SBPrefix prefix;
      base::SHA256HashString(hosts[i] + paths[j], &prefix, sizeof(prefix));
      if (bloom_filter->Exists(prefix))
        prefixes->push_back(prefix);
    }
  }

  return hosts.size() * paths.size();
}

// Binary search of sorted prefixes.
bool IsPrefixInDatabase(SBPrefix prefix,
                        const std::vector<SBPrefix>& prefixes) {
  if (prefixes.empty())
    return false;

  int low = 0;
  int high = prefixes.size() - 1;
  while (low <= high) {
    int mid = ((unsigned int)low + (unsigned int)high) >> 1;
    SBPrefix prefix_mid = prefixes[mid];
    if (prefix_mid == prefix)
      return true;
    if (prefix_mid < prefix)
      low = mid + 1;
    else
      high = mid - 1;
  }

  return false;
}

// Construct a bloom filter with the given prefixes and multiplier, and test the
// false positive rate (misses) against a URL list.
void CalculateBloomFilterFalsePositives(
    int size_multiplier,
    const FilePath& data_dir,
    const std::vector<SBPrefix>& prefix_list) {
  BloomFilter* bloom_filter = NULL;
  BuildBloomFilter(size_multiplier, prefix_list, &bloom_filter);
  scoped_refptr<BloomFilter> scoped_filter(bloom_filter);

  // Read in data file line at a time.
  FilePath url_file = data_dir.Append(FILE_PATH_LITERAL("urls"));
  std::ifstream url_stream(url_file.value().c_str());

  // Keep track of stats
  int hits = 0;
  int misses = 0;
  int weighted_hits = 0;
  int weighted_misses = 0;
  int url_count = 0;
  int prefix_count = 0;

  // Print out volumes of data (per URL hit and miss information).
  bool verbose = CommandLine::ForCurrentProcess()->HasSwitch(kFilterVerbose);
  bool use_weights = CommandLine::ForCurrentProcess()->HasSwitch(kFilterCsv);

  std::string url;
  while (std::getline(url_stream, url)) {
    ++url_count;

    // Handle a format that contains URLs weighted by unique views.
    int weight = 1;
    if (use_weights) {
      std::string::size_type pos = url.find_last_of(",");
      if (pos != std::string::npos) {
        base::StringToInt(url.begin() + pos + 1, url.end(), &weight);
        url = url.substr(0, pos);
      }
    }

    // See if the URL is in the bloom filter.
    std::vector<SBPrefix> prefixes;
    prefix_count += GeneratePrefixHits(url, bloom_filter, &prefixes);

    // See if the prefix is actually in the database (in-memory prefix list).
    for (size_t i = 0; i < prefixes.size(); ++i) {
      if (IsPrefixInDatabase(prefixes[i], prefix_list)) {
        ++hits;
        weighted_hits += weight;
        if (verbose) {
          std::cout << "Hit for URL: " << url
                    << " (prefix = "   << prefixes[i] << ")"
                    << std::endl;
        }
      } else {
        ++misses;
        weighted_misses += weight;
        if (verbose) {
          std::cout << "Miss for URL: " << url
                    << " (prefix = "    << prefixes[i] << ")"
                    << std::endl;
        }
      }
    }
  }

  // Print out the results for this test.
  std::cout << "URLs checked: "      << url_count
            << ", prefix compares: " << prefix_count
            << ", hits: "            << hits
            << ", misses: "          << misses;
  if (use_weights) {
    std::cout << ", weighted hits: "   << weighted_hits
              << ", weighted misses: " << weighted_misses;
  }
  std::cout << std::endl;
}

}  // namespace

// This test can take several minutes to perform its calculations, so it should
// be disabled until you need to run it.
TEST(SafeBrowsingBloomFilter, FalsePositives) {
  std::vector<SBPrefix> prefix_list;
  FilePath data_dir = GetFullDataPath();
  ASSERT_TRUE(ReadDatabase(data_dir, &prefix_list));

  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();

  int start = BloomFilter::kBloomFilterSizeRatio;
  if (cmd_line.HasSwitch(kFilterStart)) {
    ASSERT_TRUE(base::StringToInt(cmd_line.GetSwitchValueASCII(kFilterStart),
                                  &start));
  }

  int steps = 1;
  if (cmd_line.HasSwitch(kFilterSteps)) {
    ASSERT_TRUE(base::StringToInt(cmd_line.GetSwitchValueASCII(kFilterSteps),
                                  &steps));
  }

  int stop = start + steps;

  for (int multiplier = start; multiplier < stop; ++multiplier)
    CalculateBloomFilterFalsePositives(multiplier, data_dir, prefix_list);
}

// Computes the time required for performing a number of look ups in a bloom
// filter. This is useful for measuring the performance of new hash functions.
TEST(SafeBrowsingBloomFilter, HashTime) {
  // Read the data from the database.
  std::vector<SBPrefix> prefix_list;
  FilePath data_dir = GetFullDataPath();
  ASSERT_TRUE(ReadDatabase(data_dir, &prefix_list));

  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();

  int num_checks = kNumHashChecks;
  if (cmd_line.HasSwitch(kFilterNumChecks)) {
    ASSERT_TRUE(
        base::StringToInt(cmd_line.GetSwitchValueASCII(kFilterNumChecks),
                          &num_checks));
  }

  // Populate the bloom filter and measure the time.
  BloomFilter* bloom_filter = NULL;
  Time populate_before = Time::Now();
  BuildBloomFilter(BloomFilter::kBloomFilterSizeRatio,
                   prefix_list, &bloom_filter);
  TimeDelta populate = Time::Now() - populate_before;

  // Check a large number of random prefixes against the filter.
  int hits = 0;
  Time check_before = Time::Now();
  for (int i = 0; i < num_checks; ++i) {
    uint32 prefix = static_cast<uint32>(base::RandUint64());
    if (bloom_filter->Exists(prefix))
      ++hits;
  }
  TimeDelta check = Time::Now() - check_before;

  int64 time_per_insert = populate.InMicroseconds() /
                          static_cast<int>(prefix_list.size());
  int64 time_per_check = check.InMicroseconds() / num_checks;

  std::cout << "Time results for checks: " << num_checks
            << ", prefixes: "              << prefix_list.size()
            << ", populate time (ms): "    << populate.InMilliseconds()
            << ", check time (ms): "       << check.InMilliseconds()
            << ", hits: "                  << hits
            << ", per-populate (us): "     << time_per_insert
            << ", per-check (us): "        << time_per_check
            << std::endl;
}
<commit_msg>Cleanup: Remove sqlite_utils.h from filter_false_positive_perftest.cc.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This test performs a series false positive checks using a list of URLs
// against a known set of SafeBrowsing data.
//
// It uses a normal SafeBrowsing database to create a bloom filter where it
// looks up all the URLs in the url file. A URL that has a prefix found in the
// bloom filter and found in the database is considered a hit: a valid lookup
// that will result in a gethash request. A URL that has a prefix found in the
// bloom filter but not in the database is a miss: a false positive lookup that
// will result in an unnecessary gethash request.
//
// By varying the size of the bloom filter and using a constant set of
// SafeBrowsing data, we can check a known set of URLs against the filter and
// determine the false positive rate.
//
// False positive calculation usage:
//   $ ./perf_tests.exe --gtest_filter=SafeBrowsingBloomFilter.FalsePositives
//                      --filter-start=<integer>
//                      --filter-steps=<integer>
//                      --filter-verbose
//
//  --filter-start:   The filter multiplier to begin with. This represents the
//                    number of bits per prefix of memory to use in the filter.
//                    The default value is identical to the current SafeBrowsing
//                    database value.
//  --filter-steps:   The number of iterations to run, with each iteration
//                    increasing the filter multiplier by 1. The default value
//                    is 1.
//  --filter-verbose: Used to print out the hit / miss results per URL.
//  --filter-csv:     The URL file contains information about the number of
//                    unique views (the popularity) of each URL. See the format
//                    description below.
//
//
// Hash compute time usage:
//   $ ./perf_tests.exe --gtest_filter=SafeBrowsingBloomFilter.HashTime
//                      --filter-num-checks=<integer>
//
//  --filter-num-checks: The number of hash look ups to perform on the bloom
//                       filter. The default is 10 million.
//
// Data files:
//    chrome/test/data/safe_browsing/filter/database
//    chrome/test/data/safe_browsing/filter/urls
//
// database: A normal SafeBrowsing database.
// urls:     A text file containing a list of URLs, one per line. If the option
//           --filter-csv is specified, the format of each line in the file is
//           <url>,<weight> where weight is an integer indicating the number of
//           unique views for the URL.

#include <algorithm>
#include <fstream>
#include <vector>

#include "app/sql/statement.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/sha2.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/time.h"
#include "chrome/browser/safe_browsing/bloom_filter.h"
#include "chrome/browser/safe_browsing/safe_browsing_util.h"
#include "chrome/common/chrome_paths.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::Time;
using base::TimeDelta;

namespace {

// Command line flags.
const char kFilterVerbose[] = "filter-verbose";
const char kFilterStart[] = "filter-start";
const char kFilterSteps[] = "filter-steps";
const char kFilterCsv[] = "filter-csv";
const char kFilterNumChecks[] = "filter-num-checks";

// Number of hash checks to make during performance testing.
const int kNumHashChecks = 10000000;

// Returns the path to the data used in this test, relative to the top of the
// source directory.
FilePath GetFullDataPath() {
  FilePath full_path;
  CHECK(PathService::Get(chrome::DIR_TEST_DATA, &full_path));
  full_path = full_path.Append(FILE_PATH_LITERAL("safe_browsing"));
  full_path = full_path.Append(FILE_PATH_LITERAL("filter"));
  CHECK(file_util::PathExists(full_path));
  return full_path;
}

// Constructs a bloom filter of the appropriate size from the provided prefixes.
void BuildBloomFilter(int size_multiplier,
                      const std::vector<SBPrefix>& prefixes,
                      BloomFilter** bloom_filter) {
  // Create a BloomFilter with the specified size.
  const int key_count = std::max(static_cast<int>(prefixes.size()),
                                 BloomFilter::kBloomFilterMinSize);
  const int filter_size = key_count * size_multiplier;
  *bloom_filter = new BloomFilter(filter_size);

  // Add the prefixes to it.
  for (size_t i = 0; i < prefixes.size(); ++i)
    (*bloom_filter)->Insert(prefixes[i]);

  std::cout << "Bloom filter with prefixes: " << prefixes.size()
            << ", multiplier: " << size_multiplier
            << ", size (bytes): " << (*bloom_filter)->size()
            << std::endl;
}

// Reads the set of add prefixes contained in a SafeBrowsing database into a
// sorted array suitable for fast searching. This takes significantly less time
// to look up a given prefix than performing SQL queries.
bool ReadDatabase(const FilePath& path, std::vector<SBPrefix>* prefixes) {
  FilePath database_file = path.Append(FILE_PATH_LITERAL("database"));
  sql::Connection db;
  if (!db.Open(database_file))
    return false;

  // Get the number of items in the add_prefix table.
  const char* query = "SELECT COUNT(*) FROM add_prefix";
  sql::Statement count_statement(db.GetCachedStatement(SQL_FROM_HERE, query));
  if (!count_statement)
    return false;

  if (!count_statement.Step())
    return false;

  const int count = count_statement.ColumnInt(0);

  // Load them into a prefix vector and sort.
  prefixes->reserve(count);
  query = "SELECT prefix FROM add_prefix";
  sql::Statement prefix_statement(db.GetCachedStatement(SQL_FROM_HERE, query));
  if (!prefix_statement)
    return false;

  while (prefix_statement.Step())
    prefixes->push_back(prefix_statement.ColumnInt(0));

  DCHECK(static_cast<int>(prefixes->size()) == count);
  sort(prefixes->begin(), prefixes->end());

  return true;
}

// Generates all legal SafeBrowsing prefixes for the specified URL, and returns
// the set of Prefixes that exist in the bloom filter. The function returns the
// number of host + path combinations checked.
int GeneratePrefixHits(const std::string url,
                       BloomFilter* bloom_filter,
                       std::vector<SBPrefix>* prefixes) {
  GURL url_check(url);
  std::vector<std::string> hosts;
  if (url_check.HostIsIPAddress()) {
    hosts.push_back(url_check.host());
  } else {
    safe_browsing_util::GenerateHostsToCheck(url_check, &hosts);
  }

  std::vector<std::string> paths;
  safe_browsing_util::GeneratePathsToCheck(url_check, &paths);

  for (size_t i = 0; i < hosts.size(); ++i) {
    for (size_t j = 0; j < paths.size(); ++j) {
      SBPrefix prefix;
      base::SHA256HashString(hosts[i] + paths[j], &prefix, sizeof(prefix));
      if (bloom_filter->Exists(prefix))
        prefixes->push_back(prefix);
    }
  }

  return hosts.size() * paths.size();
}

// Binary search of sorted prefixes.
bool IsPrefixInDatabase(SBPrefix prefix,
                        const std::vector<SBPrefix>& prefixes) {
  if (prefixes.empty())
    return false;

  int low = 0;
  int high = prefixes.size() - 1;
  while (low <= high) {
    int mid = ((unsigned int)low + (unsigned int)high) >> 1;
    SBPrefix prefix_mid = prefixes[mid];
    if (prefix_mid == prefix)
      return true;
    if (prefix_mid < prefix)
      low = mid + 1;
    else
      high = mid - 1;
  }

  return false;
}

// Construct a bloom filter with the given prefixes and multiplier, and test the
// false positive rate (misses) against a URL list.
void CalculateBloomFilterFalsePositives(
    int size_multiplier,
    const FilePath& data_dir,
    const std::vector<SBPrefix>& prefix_list) {
  BloomFilter* bloom_filter = NULL;
  BuildBloomFilter(size_multiplier, prefix_list, &bloom_filter);
  scoped_refptr<BloomFilter> scoped_filter(bloom_filter);

  // Read in data file line at a time.
  FilePath url_file = data_dir.Append(FILE_PATH_LITERAL("urls"));
  std::ifstream url_stream(url_file.value().c_str());

  // Keep track of stats
  int hits = 0;
  int misses = 0;
  int weighted_hits = 0;
  int weighted_misses = 0;
  int url_count = 0;
  int prefix_count = 0;

  // Print out volumes of data (per URL hit and miss information).
  bool verbose = CommandLine::ForCurrentProcess()->HasSwitch(kFilterVerbose);
  bool use_weights = CommandLine::ForCurrentProcess()->HasSwitch(kFilterCsv);

  std::string url;
  while (std::getline(url_stream, url)) {
    ++url_count;

    // Handle a format that contains URLs weighted by unique views.
    int weight = 1;
    if (use_weights) {
      std::string::size_type pos = url.find_last_of(",");
      if (pos != std::string::npos) {
        base::StringToInt(url.begin() + pos + 1, url.end(), &weight);
        url = url.substr(0, pos);
      }
    }

    // See if the URL is in the bloom filter.
    std::vector<SBPrefix> prefixes;
    prefix_count += GeneratePrefixHits(url, bloom_filter, &prefixes);

    // See if the prefix is actually in the database (in-memory prefix list).
    for (size_t i = 0; i < prefixes.size(); ++i) {
      if (IsPrefixInDatabase(prefixes[i], prefix_list)) {
        ++hits;
        weighted_hits += weight;
        if (verbose) {
          std::cout << "Hit for URL: " << url
                    << " (prefix = "   << prefixes[i] << ")"
                    << std::endl;
        }
      } else {
        ++misses;
        weighted_misses += weight;
        if (verbose) {
          std::cout << "Miss for URL: " << url
                    << " (prefix = "    << prefixes[i] << ")"
                    << std::endl;
        }
      }
    }
  }

  // Print out the results for this test.
  std::cout << "URLs checked: "      << url_count
            << ", prefix compares: " << prefix_count
            << ", hits: "            << hits
            << ", misses: "          << misses;
  if (use_weights) {
    std::cout << ", weighted hits: "   << weighted_hits
              << ", weighted misses: " << weighted_misses;
  }
  std::cout << std::endl;
}

}  // namespace

// This test can take several minutes to perform its calculations, so it should
// be disabled until you need to run it.
TEST(SafeBrowsingBloomFilter, FalsePositives) {
  std::vector<SBPrefix> prefix_list;
  FilePath data_dir = GetFullDataPath();
  ASSERT_TRUE(ReadDatabase(data_dir, &prefix_list));

  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();

  int start = BloomFilter::kBloomFilterSizeRatio;
  if (cmd_line.HasSwitch(kFilterStart)) {
    ASSERT_TRUE(base::StringToInt(cmd_line.GetSwitchValueASCII(kFilterStart),
                                  &start));
  }

  int steps = 1;
  if (cmd_line.HasSwitch(kFilterSteps)) {
    ASSERT_TRUE(base::StringToInt(cmd_line.GetSwitchValueASCII(kFilterSteps),
                                  &steps));
  }

  int stop = start + steps;

  for (int multiplier = start; multiplier < stop; ++multiplier)
    CalculateBloomFilterFalsePositives(multiplier, data_dir, prefix_list);
}

// Computes the time required for performing a number of look ups in a bloom
// filter. This is useful for measuring the performance of new hash functions.
TEST(SafeBrowsingBloomFilter, HashTime) {
  // Read the data from the database.
  std::vector<SBPrefix> prefix_list;
  FilePath data_dir = GetFullDataPath();
  ASSERT_TRUE(ReadDatabase(data_dir, &prefix_list));

  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();

  int num_checks = kNumHashChecks;
  if (cmd_line.HasSwitch(kFilterNumChecks)) {
    ASSERT_TRUE(
        base::StringToInt(cmd_line.GetSwitchValueASCII(kFilterNumChecks),
                          &num_checks));
  }

  // Populate the bloom filter and measure the time.
  BloomFilter* bloom_filter = NULL;
  Time populate_before = Time::Now();
  BuildBloomFilter(BloomFilter::kBloomFilterSizeRatio,
                   prefix_list, &bloom_filter);
  TimeDelta populate = Time::Now() - populate_before;

  // Check a large number of random prefixes against the filter.
  int hits = 0;
  Time check_before = Time::Now();
  for (int i = 0; i < num_checks; ++i) {
    uint32 prefix = static_cast<uint32>(base::RandUint64());
    if (bloom_filter->Exists(prefix))
      ++hits;
  }
  TimeDelta check = Time::Now() - check_before;

  int64 time_per_insert = populate.InMicroseconds() /
                          static_cast<int>(prefix_list.size());
  int64 time_per_check = check.InMicroseconds() / num_checks;

  std::cout << "Time results for checks: " << num_checks
            << ", prefixes: "              << prefix_list.size()
            << ", populate time (ms): "    << populate.InMilliseconds()
            << ", check time (ms): "       << check.InMilliseconds()
            << ", hits: "                  << hits
            << ", per-populate (us): "     << time_per_insert
            << ", per-check (us): "        << time_per_check
            << std::endl;
}
<|endoftext|>


<commit_before>/**************************************************************************
 *
 * Copyright 2008-2010 VMware, Inc.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 **************************************************************************/

/*
 * Image I/O.
 */

#ifndef _IMAGE_HPP_
#define _IMAGE_HPP_

#include <iostream>

namespace image {

enum ChannelType {
    TYPE_UNORM8 = 0,
    TYPE_FLOAT
};

class Image {
public:
    unsigned width;
    unsigned height;
    unsigned channels;
    ChannelType channelType;
    unsigned bytesPerPixel;

    // Flipped vertically or not
    bool flipped;

    // Pixels in RGBA format
    unsigned char *pixels;

    inline Image(unsigned w, unsigned h, unsigned c = 4, bool f = false, ChannelType t = TYPE_UNORM8) :
        width(w),
        height(h),
        channels(c),
        channelType(t),
        bytesPerPixel(channels * (t == TYPE_FLOAT ? 4 : 1)),
        flipped(f),
        pixels(new unsigned char[h*w*c])
    {}

    inline ~Image() {
        delete [] pixels;
    }

    // Absolute stride
    inline unsigned
    _stride() const {
        return width*bytesPerPixel;
    }

    inline unsigned char *start(void) {
        return flipped ? pixels + (height - 1)*_stride() : pixels;
    }

    inline const unsigned char *start(void) const {
        return flipped ? pixels + (height - 1)*_stride() : pixels;
    }

    inline unsigned char *end(void) {
        return flipped ? pixels - _stride() : pixels + height*_stride();
    }

    inline const unsigned char *end(void) const {
        return flipped ? pixels - _stride() : pixels + height*_stride();
    }

    inline signed stride(void) const {
        return flipped ? -(signed)_stride() : _stride();
    }

    bool
    writeBMP(const char *filename) const;

    void
    writePNM(std::ostream &os, const char *comment = NULL) const;

    bool
    writePNM(const char *filename, const char *comment = NULL) const;

    bool
    writePNG(std::ostream &os) const;

    bool
    writePNG(const char *filename) const;

    void
    writeRAW(std::ostream &os) const;

    bool
    writeRAW(const char *filename) const;
};

Image *
readPNG(std::istream &is);

Image *
readPNG(const char *filename);

const char *
readPNMHeader(const char *buffer, size_t size, unsigned *channels, unsigned *width, unsigned *height);

} /* namespace image */

#endif /* _IMAGE_HPP_ */
<commit_msg>image: Fix allocation of floating point images.<commit_after>/**************************************************************************
 *
 * Copyright 2008-2010 VMware, Inc.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 **************************************************************************/

/*
 * Image I/O.
 */

#ifndef _IMAGE_HPP_
#define _IMAGE_HPP_

#include <iostream>

namespace image {

enum ChannelType {
    TYPE_UNORM8 = 0,
    TYPE_FLOAT
};

class Image {
public:
    unsigned width;
    unsigned height;
    unsigned channels;
    ChannelType channelType;
    unsigned bytesPerPixel;

    // Flipped vertically or not
    bool flipped;

    // Pixels in RGBA format
    unsigned char *pixels;

    inline Image(unsigned w, unsigned h, unsigned c = 4, bool f = false, ChannelType t = TYPE_UNORM8) :
        width(w),
        height(h),
        channels(c),
        channelType(t),
        bytesPerPixel(channels * (t == TYPE_FLOAT ? 4 : 1)),
        flipped(f),
        pixels(new unsigned char[h*w*bytesPerPixel])
    {}

    inline ~Image() {
        delete [] pixels;
    }

    // Absolute stride
    inline unsigned
    _stride() const {
        return width*bytesPerPixel;
    }

    inline unsigned char *start(void) {
        return flipped ? pixels + (height - 1)*_stride() : pixels;
    }

    inline const unsigned char *start(void) const {
        return flipped ? pixels + (height - 1)*_stride() : pixels;
    }

    inline unsigned char *end(void) {
        return flipped ? pixels - _stride() : pixels + height*_stride();
    }

    inline const unsigned char *end(void) const {
        return flipped ? pixels - _stride() : pixels + height*_stride();
    }

    inline signed stride(void) const {
        return flipped ? -(signed)_stride() : _stride();
    }

    bool
    writeBMP(const char *filename) const;

    void
    writePNM(std::ostream &os, const char *comment = NULL) const;

    bool
    writePNM(const char *filename, const char *comment = NULL) const;

    bool
    writePNG(std::ostream &os) const;

    bool
    writePNG(const char *filename) const;

    void
    writeRAW(std::ostream &os) const;

    bool
    writeRAW(const char *filename) const;
};

Image *
readPNG(std::istream &is);

Image *
readPNG(const char *filename);

const char *
readPNMHeader(const char *buffer, size_t size, unsigned *channels, unsigned *width, unsigned *height);

} /* namespace image */

#endif /* _IMAGE_HPP_ */
<|endoftext|>


<commit_before>#ifndef READER_H
#define READER_H

#include <istream>
#include <string>
#include "objects.hpp"
// #include <vector>

#include "symbols.hpp"

// /*
//  * Intermediate bytecode representation constructed by the reader
//  * The execution engine should assemble it in a representation suitable
//  * for execution.
//  */

// // the argument of a bytecode
// class BytecodeArg { public: virtual ~BytecodeArg() {}};

// /*
//  * a simple argument is a value that can fit in a pointer
//  * it could be an int, a scaled int, an offset, a character, a pointer
//  * to a Symbol, etc.
//  */
// class SimpleArg : public BytecodeArg {
// private:
//   Object::ref val;
// public:
//   SimpleArg() {}
//   template <class T>
//   void setVal(T v) { val = Object::to_ref(v); }
//   Object::ref getVal() { return val; }
// };

// // a single bytecode
// typedef std::pair<Symbol*, BytecodeArg*> bytecode;

// /*
//  * bytecode sequence
//  * owns all the bytecode args and frees them
//  */
// class BytecodeSeq : public std::vector<bytecode>, public BytecodeArg {
// public:
//   ~BytecodeSeq() {}
// };

// /*
//  * Argument of bytecode that takes a simple argument and a sequence
//  */
// class SimpleArgAndSeq : public BytecodeArg {
// private:
//   SimpleArg *sa;
//   BytecodeSeq *seq;
// public:
//   SimpleArgAndSeq(SimpleArg *s, BytecodeSeq *bs) : sa(s), seq(bs) {}
//   ~SimpleArgAndSeq() {
//     delete seq;
//     delete sa;
//   }
//   SimpleArg* getSimple() { return sa; }
//   BytecodeSeq* getSeq() { return seq; }
// };

// // exception thrown by the reader
// class ReadError : public std::string {
// public:
//   ReadError(const char *str) : std::string(str) {}
// };

// /*
//  * Bytecode reader
//  * extends bc with a bytecode read from in
//  */
// static std::istream& operator>>(std::istream & in, BytecodeSeq & bc) { return in; }

class Process;
// leaves read bytecode on the stack
void read_bytecode(Process & proc, std::istream & in);
void read_sequence(Process & proc, std::istream & in);

// simple printer for debugging
std::ostream& operator<<(std::ostream & out, Object::ref obj);

#endif // READER_H
<commit_msg>reader.hpp: removed useless code<commit_after>#ifndef READER_H
#define READER_H

#include <istream>
#include <string>
#include "objects.hpp"
#include "symbols.hpp"

class Process;
// leaves read bytecode on the stack
void read_bytecode(Process & proc, std::istream & in);
void read_sequence(Process & proc, std::istream & in);

// simple printer for debugging
std::ostream& operator<<(std::ostream & out, Object::ref obj);

#endif // READER_H
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: pm_index.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2003-06-30 15:27:10 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <precomp.h>
#include "pm_index.hxx"

// NOT FULLY DEFINED SERVICES
#include <ary/cpp/c_disply.hxx>
#include <ary/cpp/c_class.hxx>
#include <ary/cpp/c_define.hxx>
#include <ary/cpp/c_enum.hxx>
#include <ary/cpp/c_tydef.hxx>
#include <ary/cpp/c_funct.hxx>
#include <ary/cpp/c_macro.hxx>
#include <ary/cpp/c_namesp.hxx>
#include <ary/cpp/c_vari.hxx>
#include <ary/cpp/c_enuval.hxx>
#include <ary/info/codeinfo.hxx>
#include "aryattrs.hxx"
#include "hd_chlst.hxx"
#include "hd_docu.hxx"
#include "html_kit.hxx"
#include "navibar.hxx"
#include "opageenv.hxx"
#include "pagemake.hxx"
#include "strconst.hxx"

using namespace csi;

namespace
{

inline const char *
F_CK_Text( ary::cpp::E_ClassKey i_eCK )
{
    switch (i_eCK)
    {
         case ary::cpp::CK_class:    return "class";
         case ary::cpp::CK_struct:   return "struct";
         case ary::cpp::CK_union:    return "union";
    }   // end switch
    return "";
}

template <class CE>
inline const char *
F_OwnerType( const CE & i_rData, const ary::cpp::DisplayGate & i_rGate )
{
     if ( i_rData.Protection() == ary::cpp::PROTECT_global )
        return "namespace ";

    const ary::cpp::Class *
        pClass = dynamic_cast< const ary::cpp::Class* >(
                    i_rGate.Find_Ce(i_rData.Owner()) );
    if (pClass != 0)
        return F_CK_Text(pClass->ClassKey());
    return "";
}

}   // anonymous namespace

PageMaker_Index::PageMaker_Index( PageDisplay & io_rPage,
                                  char          i_c )
    :   SpecializedPageMaker(io_rPage),
        pNavi(0),
        c(i_c),
        pCurIndex(0)
{
}

PageMaker_Index::~PageMaker_Index()
{
}

void
PageMaker_Index::MakePage()
{
    pNavi = new NavigationBar( Env(), NavigationBar::LOC_Index );

    Write_NavBar();
    Write_TopArea();
    Write_CompleteAlphabeticalList();
}

void
PageMaker_Index::Display_Namespace( const ary::cpp::Namespace & i_rData )
{
    Write_CeIndexEntry( i_rData, "namespace", "namespace" );
}

void
PageMaker_Index::Display_Class( const ary::cpp::Class & i_rData )
{
    // KORR_FUTURE
    //  Really throw out all anonymous classes from index?

    if ( strncmp(i_rData.LocalName().c_str()+1,"_Anonymous",10) == 0 )
        return;

    Write_CeIndexEntry( i_rData,
                        F_CK_Text(i_rData.ClassKey()),
                        F_OwnerType(i_rData, Env().Gate()) );
}

void
PageMaker_Index::Display_Enum( const ary::cpp::Enum & i_rData )
{
    Write_CeIndexEntry( i_rData, "enum", F_OwnerType(i_rData, Env().Gate()) );
}

void
PageMaker_Index::Display_Typedef( const ary::cpp::Typedef & i_rData )
{
    Write_CeIndexEntry( i_rData, "typedef", F_OwnerType(i_rData, Env().Gate()) );
}

void
PageMaker_Index::Display_Function( const ary::cpp::Function & i_rData )
{
    Write_CeIndexEntry( i_rData, "function", F_OwnerType(i_rData, Env().Gate()) );
}

void
PageMaker_Index::Display_Variable( const ary::cpp::Variable & i_rData )
{
    Write_CeIndexEntry( i_rData, "variable", F_OwnerType(i_rData, Env().Gate()) );
}

void
PageMaker_Index::Display_EnumValue( const ary::cpp::EnumValue & i_rData )
{
    Write_CeIndexEntry( i_rData, "enum value", "" );
}

void
PageMaker_Index::Display_Define( const ary::cpp::Define & i_rData )
{
    udmstri sFileName;

    pCurIndex->AddEntry();
    pCurIndex->Term()
        >> *new html::Link( Link2CppDefinition(Env(), i_rData) )
            >> *new html::Bold
                <<  i_rData.DefinedName()
                << " - define";

    // KORR FUTURE
//    pCurIndex->Term()
//                <<  " - "
//                <<  " define in file "
//                << sFileName;

    pCurIndex->Def() << " ";
}

void
PageMaker_Index::Display_Macro( const ary::cpp::Macro & i_rData )
{
    udmstri sFileName;

    pCurIndex->AddEntry();
    pCurIndex->Term()
        >> *new html::Link( Link2CppDefinition(Env(), i_rData) )
            >> *new html::Bold
                <<  i_rData.DefinedName()
                << " - macro";

    // KORR FUTURE
//    pCurIndex->Term()
//                <<  " - "
//                <<  " macro in file "
//                << sFileName;

    pCurIndex->Def() << " ";
}

void
PageMaker_Index::Write_NavBar()
{
    pNavi->Write( CurOut() );
    CurOut() << new html::HorizontalLine;
}

const udmstri  C_sAlphabet(
"A B C D E "
"F G H I J "
"K L M N O "
"P Q R S T "
"U V W X Y "
"Z _" );

void
PageMaker_Index::Write_TopArea()
{
    udmstri sLetter(&c, 1);

    adcdisp::PageTitle_Std fTitle;
    fTitle( CurOut(), "Global Index", sLetter );

    CurOut() >>* new html::Paragraph
                 << new html::AlignAttr("center")
                 << new xml::XmlCode(C_sAlphabet);

    CurOut() << new html::HorizontalLine;
}

void
PageMaker_Index::Write_CompleteAlphabeticalList()
{
    std::vector<ary::Rid>
        aThisPagesItems;
    const ary::cpp::DisplayGate &
        rGate = Env().Gate();

    static char sBegin[] = "X";
    static char sEnd[] = "Y";

    switch ( c )
    {
         case 'Z':   sBegin[0] = 'Z';
                    sEnd[0] = '_';
                    break;
        case '_':   sBegin[0] = '_';
                    sEnd[0] = '0';
                    break;
        default:    sBegin[0] = c;
                    sEnd[0] = char(c + 1);
                    break;
    }

    uintt nCount = rGate.Get_AlphabeticalList( aThisPagesItems, sBegin, sEnd );
    if (nCount > 0 )
    {
        adcdisp::IndexList
            aIndex(CurOut());
        pCurIndex = &aIndex;

        std::vector<ary::Rid>::const_iterator itEnd = aThisPagesItems.end();
        for ( std::vector<ary::Rid>::const_iterator it = aThisPagesItems.begin();
              it != itEnd;
              ++it )
        {
            const ary::RepositoryEntity *
                pRe = rGate.Find_Re( *it );
            if ( pRe != 0 )
                pRe->StoreAt(*this);
        }   // end for

        pCurIndex = 0;
    }   // endif (nCount > 0)
}

void
PageMaker_Index::Write_CeIndexEntry( const ary::CodeEntity & i_rCe,
                                     const char *            i_sType,
                                     const char *            i_sOwnerType )
{
    if ( Ce_IsInternal(i_rCe) )
        return;

    static csv::StreamStr aQualification(500);

    const ary::CodeEntity & rOwner = Env().Gate().Ref_Ce(i_rCe.Owner());

    pCurIndex->AddEntry();
    pCurIndex->Term()
        >> *new html::Link( Link2Ce(Env(), i_rCe) )
            >> *new html::Bold
                <<  i_rCe.LocalName();
    pCurIndex->Term()
        <<  " - "
        <<  i_sType;

    if ( rOwner.Owner() != 0 )
    {
        aQualification.seekp(0);
        Env().Gate().Get_QualifiedName( aQualification,
                                        rOwner.LocalName(),
                                        rOwner.Owner() );

        pCurIndex->Term()
            <<  " in "
            << i_sOwnerType
            << " "
            << aQualification.c_str();
    }

    pCurIndex->Def() << " ";
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.4.96); FILE MERGED 2005/09/05 13:10:50 rt 1.4.96.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pm_index.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 17:36:19 $
 *
 *  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
 *
 ************************************************************************/

#include <precomp.h>
#include "pm_index.hxx"

// NOT FULLY DEFINED SERVICES
#include <ary/cpp/c_disply.hxx>
#include <ary/cpp/c_class.hxx>
#include <ary/cpp/c_define.hxx>
#include <ary/cpp/c_enum.hxx>
#include <ary/cpp/c_tydef.hxx>
#include <ary/cpp/c_funct.hxx>
#include <ary/cpp/c_macro.hxx>
#include <ary/cpp/c_namesp.hxx>
#include <ary/cpp/c_vari.hxx>
#include <ary/cpp/c_enuval.hxx>
#include <ary/info/codeinfo.hxx>
#include "aryattrs.hxx"
#include "hd_chlst.hxx"
#include "hd_docu.hxx"
#include "html_kit.hxx"
#include "navibar.hxx"
#include "opageenv.hxx"
#include "pagemake.hxx"
#include "strconst.hxx"

using namespace csi;

namespace
{

inline const char *
F_CK_Text( ary::cpp::E_ClassKey i_eCK )
{
    switch (i_eCK)
    {
         case ary::cpp::CK_class:    return "class";
         case ary::cpp::CK_struct:   return "struct";
         case ary::cpp::CK_union:    return "union";
    }   // end switch
    return "";
}

template <class CE>
inline const char *
F_OwnerType( const CE & i_rData, const ary::cpp::DisplayGate & i_rGate )
{
     if ( i_rData.Protection() == ary::cpp::PROTECT_global )
        return "namespace ";

    const ary::cpp::Class *
        pClass = dynamic_cast< const ary::cpp::Class* >(
                    i_rGate.Find_Ce(i_rData.Owner()) );
    if (pClass != 0)
        return F_CK_Text(pClass->ClassKey());
    return "";
}

}   // anonymous namespace

PageMaker_Index::PageMaker_Index( PageDisplay & io_rPage,
                                  char          i_c )
    :   SpecializedPageMaker(io_rPage),
        pNavi(0),
        c(i_c),
        pCurIndex(0)
{
}

PageMaker_Index::~PageMaker_Index()
{
}

void
PageMaker_Index::MakePage()
{
    pNavi = new NavigationBar( Env(), NavigationBar::LOC_Index );

    Write_NavBar();
    Write_TopArea();
    Write_CompleteAlphabeticalList();
}

void
PageMaker_Index::Display_Namespace( const ary::cpp::Namespace & i_rData )
{
    Write_CeIndexEntry( i_rData, "namespace", "namespace" );
}

void
PageMaker_Index::Display_Class( const ary::cpp::Class & i_rData )
{
    // KORR_FUTURE
    //  Really throw out all anonymous classes from index?

    if ( strncmp(i_rData.LocalName().c_str()+1,"_Anonymous",10) == 0 )
        return;

    Write_CeIndexEntry( i_rData,
                        F_CK_Text(i_rData.ClassKey()),
                        F_OwnerType(i_rData, Env().Gate()) );
}

void
PageMaker_Index::Display_Enum( const ary::cpp::Enum & i_rData )
{
    Write_CeIndexEntry( i_rData, "enum", F_OwnerType(i_rData, Env().Gate()) );
}

void
PageMaker_Index::Display_Typedef( const ary::cpp::Typedef & i_rData )
{
    Write_CeIndexEntry( i_rData, "typedef", F_OwnerType(i_rData, Env().Gate()) );
}

void
PageMaker_Index::Display_Function( const ary::cpp::Function & i_rData )
{
    Write_CeIndexEntry( i_rData, "function", F_OwnerType(i_rData, Env().Gate()) );
}

void
PageMaker_Index::Display_Variable( const ary::cpp::Variable & i_rData )
{
    Write_CeIndexEntry( i_rData, "variable", F_OwnerType(i_rData, Env().Gate()) );
}

void
PageMaker_Index::Display_EnumValue( const ary::cpp::EnumValue & i_rData )
{
    Write_CeIndexEntry( i_rData, "enum value", "" );
}

void
PageMaker_Index::Display_Define( const ary::cpp::Define & i_rData )
{
    udmstri sFileName;

    pCurIndex->AddEntry();
    pCurIndex->Term()
        >> *new html::Link( Link2CppDefinition(Env(), i_rData) )
            >> *new html::Bold
                <<  i_rData.DefinedName()
                << " - define";

    // KORR FUTURE
//    pCurIndex->Term()
//                <<  " - "
//                <<  " define in file "
//                << sFileName;

    pCurIndex->Def() << " ";
}

void
PageMaker_Index::Display_Macro( const ary::cpp::Macro & i_rData )
{
    udmstri sFileName;

    pCurIndex->AddEntry();
    pCurIndex->Term()
        >> *new html::Link( Link2CppDefinition(Env(), i_rData) )
            >> *new html::Bold
                <<  i_rData.DefinedName()
                << " - macro";

    // KORR FUTURE
//    pCurIndex->Term()
//                <<  " - "
//                <<  " macro in file "
//                << sFileName;

    pCurIndex->Def() << " ";
}

void
PageMaker_Index::Write_NavBar()
{
    pNavi->Write( CurOut() );
    CurOut() << new html::HorizontalLine;
}

const udmstri  C_sAlphabet(
"A B C D E "
"F G H I J "
"K L M N O "
"P Q R S T "
"U V W X Y "
"Z _" );

void
PageMaker_Index::Write_TopArea()
{
    udmstri sLetter(&c, 1);

    adcdisp::PageTitle_Std fTitle;
    fTitle( CurOut(), "Global Index", sLetter );

    CurOut() >>* new html::Paragraph
                 << new html::AlignAttr("center")
                 << new xml::XmlCode(C_sAlphabet);

    CurOut() << new html::HorizontalLine;
}

void
PageMaker_Index::Write_CompleteAlphabeticalList()
{
    std::vector<ary::Rid>
        aThisPagesItems;
    const ary::cpp::DisplayGate &
        rGate = Env().Gate();

    static char sBegin[] = "X";
    static char sEnd[] = "Y";

    switch ( c )
    {
         case 'Z':   sBegin[0] = 'Z';
                    sEnd[0] = '_';
                    break;
        case '_':   sBegin[0] = '_';
                    sEnd[0] = '0';
                    break;
        default:    sBegin[0] = c;
                    sEnd[0] = char(c + 1);
                    break;
    }

    uintt nCount = rGate.Get_AlphabeticalList( aThisPagesItems, sBegin, sEnd );
    if (nCount > 0 )
    {
        adcdisp::IndexList
            aIndex(CurOut());
        pCurIndex = &aIndex;

        std::vector<ary::Rid>::const_iterator itEnd = aThisPagesItems.end();
        for ( std::vector<ary::Rid>::const_iterator it = aThisPagesItems.begin();
              it != itEnd;
              ++it )
        {
            const ary::RepositoryEntity *
                pRe = rGate.Find_Re( *it );
            if ( pRe != 0 )
                pRe->StoreAt(*this);
        }   // end for

        pCurIndex = 0;
    }   // endif (nCount > 0)
}

void
PageMaker_Index::Write_CeIndexEntry( const ary::CodeEntity & i_rCe,
                                     const char *            i_sType,
                                     const char *            i_sOwnerType )
{
    if ( Ce_IsInternal(i_rCe) )
        return;

    static csv::StreamStr aQualification(500);

    const ary::CodeEntity & rOwner = Env().Gate().Ref_Ce(i_rCe.Owner());

    pCurIndex->AddEntry();
    pCurIndex->Term()
        >> *new html::Link( Link2Ce(Env(), i_rCe) )
            >> *new html::Bold
                <<  i_rCe.LocalName();
    pCurIndex->Term()
        <<  " - "
        <<  i_sType;

    if ( rOwner.Owner() != 0 )
    {
        aQualification.seekp(0);
        Env().Gate().Get_QualifiedName( aQualification,
                                        rOwner.LocalName(),
                                        rOwner.Owner() );

        pCurIndex->Term()
            <<  " in "
            << i_sOwnerType
            << " "
            << aQualification.c_str();
    }

    pCurIndex->Def() << " ";
}

<|endoftext|>


<commit_before>/*
 * Created by kunjesh virani on 7 February, 2017
 * On the Platform Linux (Ubuntu Xenial xerus) 64bit
 *
 */

/*
 * Description
 *
 * This file contain the code of native activity with very simple and basic use of EGL and OpenGL ES libraries.
 */

#include <android_native_app_glue.h>
#include <android/log.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
#include "linedraw.h"
#define LOGW(x...) __android_log_print(ANDROID_LOG_WARN, "OnlyBlankNativeActivity",x)

struct egl {
    EGLDisplay display;
    EGLSurface surface;
    EGLContext context;
};
linedraw lineDraw;  // calling a class which is defined in "linedraw" class.

static void egl_init(struct android_app* app, struct egl* egl) {

    // below is the code for attributes of EGL which will be stored in configurations (config).
    const EGLint attributes[] = {
            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
            EGL_RED_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE, 8,
            EGL_NONE
    };

    // declare the several variables which will assigned to main egl struct members

    EGLint format, numConfigs;
    EGLDisplay display;
    EGLContext context;
    EGLSurface surface;
    EGLConfig config;

    // first get the EGL display connection.
    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    // after getting display connection must initialize the EGL
    eglInitialize(display, 0, 0);

    // when initialization will complete egl take a watch for choosing its configuration.
    // below function will save the choosen configuration in config and return the number of configuration in numConfig.
    eglChooseConfig(display, attributes, &config, 1, &numConfigs);

    // get the choosen configurations and set the format for native display.
    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);

    // Set the geometry of native window via format returned.
    ANativeWindow_setBuffersGeometry(app->window, 0, 0, format);

    // Initialize the surface and context of EGL for render the rendering API like OpenGL ES..
    surface = eglCreateWindowSurface(display, config, app->window, 0);
    context = eglCreateContext(display, config, 0, 0);

    // make the surface and context active to the current thread which will be used in the process.
    eglMakeCurrent(display, surface, surface, context);
    egl->display = display;
    egl->surface = surface;
    egl->context = context;
}

static void engine_for_draw(struct egl* egl) {
    if(egl->display == NULL)
        return;

    glClearColor(0.0, 0.0, 0.0, 1.0);

    glClear(GL_COLOR_BUFFER_BIT);
    lineDraw.draw();  // calling a class member function.
    // this will post the color buffer created vua glClearColor() to native window.
    // without use of below code will output nothing except blank screen, and will not generate error.
    eglSwapBuffers(egl->display, egl->surface);
}

static void engine_terminate(struct egl* egl) {
    if(egl->display != EGL_NO_DISPLAY) {
        eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        if(egl->surface != EGL_NO_SURFACE)
            eglDestroySurface(egl->display, egl->surface);
        if(egl->context != EGL_NO_CONTEXT)
            eglDestroyContext(egl->display, egl->context);
        eglTerminate(egl->display);
    }
    egl->display = EGL_NO_DISPLAY;
    egl->surface = EGL_NO_SURFACE;
    egl->context = EGL_NO_CONTEXT;
}

// below function for control display via various commands

static void handle_command_android(struct android_app* app, int32_t cmd) {

    struct egl* egl = (struct egl*)app->userData;

    switch (cmd) {
        case APP_CMD_INIT_WINDOW:
            egl_init(app, egl);
            engine_for_draw(egl);
            LOGW("App Window has been initiated..");
            break;
        case APP_CMD_TERM_WINDOW:
            engine_terminate(egl);
            LOGW("App Window has been terminated..");
            break;
        case APP_CMD_SAVE_STATE:
            // here sometime you have to remove the termination code from here due to large number of drawing in 1 or 2 seconds.
            // using termination code here will manage the usage of RAM when application's activity has been paused.
            engine_terminate(egl);
            LOGW("App window's state has been saved.. or Window has been minimized");
            break;
        default:
            break;
    }
}
static int32_t handle_input_android(struct android_app* app, AInputEvent* event) {

    // below code is for catch handle input.

    if(AInputEvent_getType(event)==AINPUT_EVENT_TYPE_MOTION) {
        LOGW("Coordinates X = %f, Y = %f ", AMotionEvent_getX(event,0), AMotionEvent_getY(event,0));
        return 1;
    }
    return 0;
}

// below code is for android_main() which is the entry point of our execution.

void android_main(struct android_app* app_state) {

    // below code is for determine that glue is not stripped, because if it is stripped it will remove the module android_native_app_glue.o which will stop the execution. So use of app_dummy() function will embed it.
    app_dummy();

    // below variable declaration is for catch the events and process it.

    struct egl egl;

    // memset(&egl, 0, sizeof(egl));
    int events;
    app_state->userData = &egl;
    app_state->onAppCmd = handle_command_android;
    app_state->onInputEvent = handle_input_android;

    while(1) {

        struct android_poll_source* source;

        while(ALooper_pollAll(-1, NULL, &events, (void**)&source)>=0) {
            if(source != NULL)
                source->process(app_state, source);
            if(app_state->destroyRequested != 0) {
                LOGW("We are exiting from app.");
                return;
            }
        }
    }
}

<commit_msg>Update native-lib.cpp<commit_after>/*
 * Created by KV on 7 February, 2017
 * On the Platform Linux (Ubuntu Xenial xerus) 64bit
 *
 * hellowwoor@gmail.com
 */

/*
 * Description
 *
 * This file contain the code of native activity with very simple and basic use of EGL and OpenGL ES libraries.
 */

#include <android_native_app_glue.h>
#include <android/log.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
#include "linedraw.h"
#define LOGW(x...) __android_log_print(ANDROID_LOG_WARN, "OnlyBlankNativeActivity",x)

struct egl {
    EGLDisplay display;
    EGLSurface surface;
    EGLContext context;
};
linedraw lineDraw;  // calling a class which is defined in "linedraw" class.

static void egl_init(struct android_app* app, struct egl* egl) {

    // below is the code for attributes of EGL which will be stored in configurations (config).
    const EGLint attributes[] = {
            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
            EGL_RED_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE, 8,
            EGL_NONE
    };

    // declare the several variables which will assigned to main egl struct members

    EGLint format, numConfigs;
    EGLDisplay display;
    EGLContext context;
    EGLSurface surface;
    EGLConfig config;

    // first get the EGL display connection.
    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    // after getting display connection must initialize the EGL
    eglInitialize(display, 0, 0);

    // when initialization will complete egl take a watch for choosing its configuration.
    // below function will save the choosen configuration in config and return the number of configuration in numConfig.
    eglChooseConfig(display, attributes, &config, 1, &numConfigs);

    // get the choosen configurations and set the format for native display.
    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);

    // Set the geometry of native window via format returned.
    ANativeWindow_setBuffersGeometry(app->window, 0, 0, format);

    // Initialize the surface and context of EGL for render the rendering API like OpenGL ES..
    surface = eglCreateWindowSurface(display, config, app->window, 0);
    context = eglCreateContext(display, config, 0, 0);

    // make the surface and context active to the current thread which will be used in the process.
    eglMakeCurrent(display, surface, surface, context);
    egl->display = display;
    egl->surface = surface;
    egl->context = context;
}

static void engine_for_draw(struct egl* egl) {
    if(egl->display == NULL)
        return;

    glClearColor(0.0, 0.0, 0.0, 1.0);

    glClear(GL_COLOR_BUFFER_BIT);
    lineDraw.draw();  // calling a class member function.
    // this will post the color buffer created vua glClearColor() to native window.
    // without use of below code will output nothing except blank screen, and will not generate error.
    eglSwapBuffers(egl->display, egl->surface);
}

static void engine_terminate(struct egl* egl) {
    if(egl->display != EGL_NO_DISPLAY) {
        eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        if(egl->surface != EGL_NO_SURFACE)
            eglDestroySurface(egl->display, egl->surface);
        if(egl->context != EGL_NO_CONTEXT)
            eglDestroyContext(egl->display, egl->context);
        eglTerminate(egl->display);
    }
    egl->display = EGL_NO_DISPLAY;
    egl->surface = EGL_NO_SURFACE;
    egl->context = EGL_NO_CONTEXT;
}

// below function for control display via various commands

static void handle_command_android(struct android_app* app, int32_t cmd) {

    struct egl* egl = (struct egl*)app->userData;

    switch (cmd) {
        case APP_CMD_INIT_WINDOW:
            egl_init(app, egl);
            engine_for_draw(egl);
            LOGW("App Window has been initiated..");
            break;
        case APP_CMD_TERM_WINDOW:
            engine_terminate(egl);
            LOGW("App Window has been terminated..");
            break;
        case APP_CMD_SAVE_STATE:
            // here sometime you have to remove the termination code from here due to large number of drawing in 1 or 2 seconds.
            // using termination code here will manage the usage of RAM when application's activity has been paused.
            engine_terminate(egl);
            LOGW("App window's state has been saved.. or Window has been minimized");
            break;
        default:
            break;
    }
}
static int32_t handle_input_android(struct android_app* app, AInputEvent* event) {

    // below code is for catch handle input.

    if(AInputEvent_getType(event)==AINPUT_EVENT_TYPE_MOTION) {
        LOGW("Coordinates X = %f, Y = %f ", AMotionEvent_getX(event,0), AMotionEvent_getY(event,0));
        return 1;
    }
    return 0;
}

// below code is for android_main() which is the entry point of our execution.

void android_main(struct android_app* app_state) {

    // below code is for determine that glue is not stripped, because if it is stripped it will remove the module android_native_app_glue.o which will stop the execution. So use of app_dummy() function will embed it.
    app_dummy();

    // below variable declaration is for catch the events and process it.

    struct egl egl;

    // memset(&egl, 0, sizeof(egl));
    int events;
    app_state->userData = &egl;
    app_state->onAppCmd = handle_command_android;
    app_state->onInputEvent = handle_input_android;

    while(1) {

        struct android_poll_source* source;

        while(ALooper_pollAll(-1, NULL, &events, (void**)&source)>=0) {
            if(source != NULL)
                source->process(app_state, source);
            if(app_state->destroyRequested != 0) {
                LOGW("We are exiting from app.");
                return;
            }
        }
    }
}

<|endoftext|>


<commit_before>/**
* @file SimulationTest.cpp
* @author Benjamin Schlotter
* Implementation of class SimulationTest
*/

#include "SimulationTest.h"

using namespace naoth;
using namespace std;

SimulationTest::SimulationTest()
{
  simulationModule = registerModule<Simulation>(std::string("Simulation"), true);
	DEBUG_REQUEST_REGISTER("SimulationTest:draw_decision","draw_decision", false);

	//Set Rotation
	globRot = 0.0;
}

SimulationTest::~SimulationTest(){}

void SimulationTest::execute()
{
	DEBUG_REQUEST("SimulationTest:draw_decision",
		globRot = globRot+1.0;

		// hack
		static std::vector<Vector3d> function;
		function.clear();

		// ball just in front of the robot
		getBallModel().position = Vector2d(150, 0);
		getBallModel().valid = true;
		getBallModel().setFrameInfoWhenBallWasSeen(getFrameInfo());

		getRobotPose().isValid = true;

		// iterate over robot pose
    functionMulticolor.clear();
		Pose2D p(0.0, getFieldInfo().carpetRect.min());
		for(p.translation.x = getFieldInfo().carpetRect.min().x; p.translation.x < getFieldInfo().carpetRect.max().x; p.translation.x += 200)
		{
			for(p.translation.y = getFieldInfo().carpetRect.min().y; p.translation.y < getFieldInfo().carpetRect.max().y; p.translation.y += 200)
			{
        MultiColorValue v(KickActionModel::numOfActions);
        v.position = p*getBallModel().position; //Draw the ball position later

        for(size_t i=0;i<10;i++)
        {
				  p.rotation =  Math::fromDegrees(globRot);
				  getRobotPose() = p;
				  simulationModule->execute();
          v.values[getKickActionModel().bestAction]++;
        }

        functionMulticolor.push_back(v);
			}
		}
    draw_function_multicolor(functionMulticolor);
		//draw_function(function);
	);
}//end execute

void SimulationTest::draw_function(const std::vector<Vector3d>& function) const
{
  if(function.empty()) {
    return;
  }

  double maxValue = function.front().z;
  double minValue = function.front().z;
  for(size_t i = 0; i < function.size(); ++i) {
    if(function[i].z > maxValue) {
      maxValue = function[i].z;
    } else if(function[i].z < minValue) {
      minValue = function[i].z;
    }
  }

  if(maxValue - minValue == 0) return;

  FIELD_DRAWING_CONTEXT;
  Color white(1.0,1.0,1.0,0.0); // transparent
  Color black(0.0,0.0,0.0,1.0);

  for(size_t i = 0; i < function.size(); ++i) {
    double t = (function[i].z - minValue) / (maxValue - minValue);
    //Color color = black*t + white*(1-t);
	  Color color;

	  if(function[i].z == 0){
		  color = Color(1.0,1.0,1.0,0.7); //White - None
	  }
	  else if(function[i].z == 1){
		  color = Color(255.0/255,172.0/255,18.0/255,0.7); //orange - kick_short
	  }
	  else if(function[i].z == 2){
		  color = Color(232.0/255,43.0/255,0.0/255,0.7); //red - kick_long
	  }
	  else if(function[i].z == 3){
		  color = Color(0.0/255,13.0/255,191.0/255,0.7); //blue - sidekick_left
	  }
	  else if(function[i].z == 4){
		  color = Color(0.0/255,191.0/255,51.0/255,0.7);//green - sidekick_right
	  }
      PEN(color, 20);
      FILLBOX(function[i].x - 50, function[i].y - 50, function[i].x+50, function[i].y+50);
  }
	//Draw Arrow instead
	Pose2D q;
	q.translation.x = 0.0;
	q.translation.y = 0.0;
	q.rotation = Math::fromDegrees(globRot);

	Vector2d ArrowStart = q * Vector2d(0, 0);
	Vector2d ArrowEnd = q * Vector2d(500, 0);

	PEN("000000", 50);
	ARROW(ArrowStart.x,ArrowStart.y,ArrowEnd.x,ArrowEnd.y);
}//end draw_closest_points

void SimulationTest::draw_difference(const std::vector<Vector3d>& function)const{
  if(function.empty()) {
    return;
  }

  double maxValue = function.front().z;
  double minValue = function.front().z;
  for(size_t i = 0; i < function.size(); ++i)
  {
    if(function[i].z > maxValue) {
      maxValue = function[i].z;
    } else if(function[i].z < minValue)
    {
      minValue = function[i].z;
    }
  }

  if(maxValue - minValue == 0) return;

  FIELD_DRAWING_CONTEXT;
  Color white(1.0,1.0,1.0,0.0); // transparent
  Color black(0.0,0.0,0.0,1.0);

  for(size_t i = 0; i < function.size(); ++i)
  {
	  Color color;
    //Test for difference of kick decisions
    if(function[i].z == 0)
    {
		  color = Color(1.0,1.0,1.0,0.7);//White Kick Decision is the same
    }
    else if(function[i].z == 1)
    {
      color = Color(0.0,0.0,0.0,0.7); //Black - Kick Decision is not the same
    }
      PEN(color, 20);
      FILLBOX(function[i].x - 50, function[i].y - 50, function[i].x+50, function[i].y+50);
  }
  //Draw Arrow
	Pose2D q;
	q.translation.x = 0.0;
	q.translation.y = 0.0;
	q.rotation = Math::fromDegrees(globRot);

	Vector2d ArrowStart = q * Vector2d(0, 0);
	Vector2d ArrowEnd = q * Vector2d(500, 0);

	PEN("000000", 50);
	ARROW(ArrowStart.x,ArrowStart.y,ArrowEnd.x,ArrowEnd.y);
}

void SimulationTest::draw_function_multicolor(const std::vector<SimulationTest::MultiColorValue>& function) const
{
  if(function.empty()) {
    return;
  }

  FIELD_DRAWING_CONTEXT;
  std::vector<Color> colors;
  colors.push_back(Color(1.0,1.0,0.0,0.7)); //none
  colors.push_back(Color(255.0/255,172.0/255,18.0/255,0.7));//short
  colors.push_back(Color(232.0/255,43.0/255,0.0/255,0.7));  //long
  colors.push_back(Color(0.0/255,13.0/255,191.0/255,0.7));  //left
  colors.push_back(Color(0.0/255,191.0/255,51.0/255,0.7));  //right

  for(size_t i = 0; i < function.size(); ++i)
  {
    const MultiColorValue& v = function[i];
    double sum = 0;
    for(size_t j = 0; j < v.values.size(); ++j) {
      sum += v.values[j];
    }

    Color color(0.0,0.0,0.0,0.0);
    for(size_t j = 0; j < v.values.size(); ++j) {
      color += v.values[j]/sum*colors[j];
    }

    PEN(color, 0);
    FILLBOX(v.position.x - 100, v.position.y - 100, v.position.x+100, v.position.y+100);
  }

	//Draw Arrow
	Pose2D q;
	q.translation.x = 0.0;
	q.translation.y = 0.0;
	q.rotation = Math::fromDegrees(globRot);

	Vector2d ArrowStart = q * Vector2d(0, 0);
	Vector2d ArrowEnd = q * Vector2d(500, 0);

	PEN("000000", 50);
	ARROW(ArrowStart.x,ArrowStart.y,ArrowEnd.x,ArrowEnd.y);
}<commit_msg>cleanup<commit_after>/**
* @file SimulationTest.cpp
* @author Benjamin Schlotter
* Implementation of class SimulationTest
*/

#include "SimulationTest.h"

using namespace naoth;
using namespace std;

SimulationTest::SimulationTest()
{
  simulationModule = registerModule<Simulation>(std::string("Simulation"), true);
	DEBUG_REQUEST_REGISTER("SimulationTest:draw_decision","draw_decision", false);

	//Set Rotation
	globRot = 0.0;
}

SimulationTest::~SimulationTest(){}

void SimulationTest::execute()
{
	DEBUG_REQUEST("SimulationTest:draw_decision",
		globRot = globRot+1.0;

		// hack
		static std::vector<Vector3d> function;
		function.clear();

		// ball just in front of the robot
		getBallModel().position = Vector2d(150, 0);
		getBallModel().valid = true;
		getBallModel().setFrameInfoWhenBallWasSeen(getFrameInfo());

		getRobotPose().isValid = true;

		// iterate over robot pose
    functionMulticolor.clear();
		Vector2d p(getFieldInfo().carpetRect.min());

		for(p.x = getFieldInfo().carpetRect.min().x; p.x < getFieldInfo().carpetRect.max().x; p.x += 200) {
			for(p.y = getFieldInfo().carpetRect.min().y; p.y < getFieldInfo().carpetRect.max().y; p.y += 200)
			{
        MultiColorValue v(KickActionModel::numOfActions);
        v.position = p; //Draw the ball position later

        for(size_t i=0; i<10; ++i)
        {
          getRobotPose().translation = p;
				  getRobotPose().rotation =  Math::fromDegrees(globRot);

				  simulationModule->execute();
          v.values[getKickActionModel().bestAction]++;
        }

        functionMulticolor.push_back(v);
			}
		}
    draw_function_multicolor(functionMulticolor);
		//draw_function(function);
	);
}//end execute

void SimulationTest::draw_function(const std::vector<Vector3d>& function) const
{
  if(function.empty()) {
    return;
  }

  double maxValue = function.front().z;
  double minValue = function.front().z;
  for(size_t i = 0; i < function.size(); ++i) {
    if(function[i].z > maxValue) {
      maxValue = function[i].z;
    } else if(function[i].z < minValue) {
      minValue = function[i].z;
    }
  }

  if(maxValue - minValue == 0) return;

  FIELD_DRAWING_CONTEXT;
  Color white(1.0,1.0,1.0,0.0); // transparent
  Color black(0.0,0.0,0.0,1.0);

  for(size_t i = 0; i < function.size(); ++i) {
    double t = (function[i].z - minValue) / (maxValue - minValue);
    //Color color = black*t + white*(1-t);
	  Color color;

	  if(function[i].z == 0){
		  color = Color(1.0,1.0,1.0,0.7); //White - None
	  }
	  else if(function[i].z == 1){
		  color = Color(255.0/255,172.0/255,18.0/255,0.7); //orange - kick_short
	  }
	  else if(function[i].z == 2){
		  color = Color(232.0/255,43.0/255,0.0/255,0.7); //red - kick_long
	  }
	  else if(function[i].z == 3){
		  color = Color(0.0/255,13.0/255,191.0/255,0.7); //blue - sidekick_left
	  }
	  else if(function[i].z == 4){
		  color = Color(0.0/255,191.0/255,51.0/255,0.7);//green - sidekick_right
	  }
      PEN(color, 20);
      FILLBOX(function[i].x - 50, function[i].y - 50, function[i].x+50, function[i].y+50);
  }
	//Draw Arrow instead
	Pose2D q;
	q.translation.x = 0.0;
	q.translation.y = 0.0;
	q.rotation = Math::fromDegrees(globRot);

	Vector2d ArrowStart = q * Vector2d(0, 0);
	Vector2d ArrowEnd = q * Vector2d(500, 0);

	PEN("000000", 50);
	ARROW(ArrowStart.x,ArrowStart.y,ArrowEnd.x,ArrowEnd.y);
}//end draw_closest_points

void SimulationTest::draw_difference(const std::vector<Vector3d>& function)const{
  if(function.empty()) {
    return;
  }

  double maxValue = function.front().z;
  double minValue = function.front().z;
  for(size_t i = 0; i < function.size(); ++i)
  {
    if(function[i].z > maxValue) {
      maxValue = function[i].z;
    } else if(function[i].z < minValue)
    {
      minValue = function[i].z;
    }
  }

  if(maxValue - minValue == 0) return;

  FIELD_DRAWING_CONTEXT;
  Color white(1.0,1.0,1.0,0.0); // transparent
  Color black(0.0,0.0,0.0,1.0);

  for(size_t i = 0; i < function.size(); ++i)
  {
	  Color color;
    //Test for difference of kick decisions
    if(function[i].z == 0)
    {
		  color = Color(1.0,1.0,1.0,0.7);//White Kick Decision is the same
    }
    else if(function[i].z == 1)
    {
      color = Color(0.0,0.0,0.0,0.7); //Black - Kick Decision is not the same
    }
      PEN(color, 20);
      FILLBOX(function[i].x - 50, function[i].y - 50, function[i].x+50, function[i].y+50);
  }
  //Draw Arrow
	Pose2D q;
	q.translation.x = 0.0;
	q.translation.y = 0.0;
	q.rotation = Math::fromDegrees(globRot);

	Vector2d ArrowStart = q * Vector2d(0, 0);
	Vector2d ArrowEnd = q * Vector2d(500, 0);

	PEN("000000", 50);
	ARROW(ArrowStart.x,ArrowStart.y,ArrowEnd.x,ArrowEnd.y);
}

void SimulationTest::draw_function_multicolor(const std::vector<SimulationTest::MultiColorValue>& function) const
{
  if(function.empty()) {
    return;
  }

  FIELD_DRAWING_CONTEXT;
  std::vector<Color> colors;
  colors.push_back(Color(1.0,1.0,0.0,0.7)); //none
  colors.push_back(Color(255.0/255,172.0/255,18.0/255,0.7));//short
  colors.push_back(Color(232.0/255,43.0/255,0.0/255,0.7));  //long
  colors.push_back(Color(0.0/255,13.0/255,191.0/255,0.7));  //left
  colors.push_back(Color(0.0/255,191.0/255,51.0/255,0.7));  //right

  for(size_t i = 0; i < function.size(); ++i)
  {
    const MultiColorValue& v = function[i];
    double sum = 0;
    for(size_t j = 0; j < v.values.size(); ++j) {
      sum += v.values[j];
    }

    Color color(0.0,0.0,0.0,0.0);
    for(size_t j = 0; j < v.values.size(); ++j) {
      color += v.values[j]/sum*colors[j];
    }

    PEN(color, 0);
    FILLBOX(v.position.x - 100, v.position.y - 100, v.position.x+100, v.position.y+100);
  }

	//Draw Arrow
	Pose2D q;
	q.translation.x = 0.0;
	q.translation.y = 0.0;
	q.rotation = Math::fromDegrees(globRot);

	Vector2d ArrowStart = q * Vector2d(0, 0);
	Vector2d ArrowEnd = q * Vector2d(500, 0);

	PEN("000000", 50);
	ARROW(ArrowStart.x,ArrowStart.y,ArrowEnd.x,ArrowEnd.y);
}<|endoftext|>


<commit_before>//-----------------------------------------------------------
//
//    Copyright (C) 2015 by the deal2lkit authors
//
//    This file is part of the deal2lkit library.
//
//    The deal2lkit library is free software; you can use it, 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.
//    The full text of the license can be found in the file LICENSE at
//    the top level of the deal2lkit distribution.
//
//-----------------------------------------------------------

#include <deal2lkit/sundials_interface.h>
#include <deal2lkit/imex_stepper.h>
#ifdef D2K_WITH_SUNDIALS

#include <deal.II/base/utilities.h>
#include <deal.II/lac/block_vector.h>
#ifdef DEAL_II_WITH_TRILINOS
#include <deal.II/lac/trilinos_block_vector.h>
#include <deal.II/lac/trilinos_parallel_block_vector.h>
#include <deal.II/lac/trilinos_vector.h>
#endif
#include <deal.II/base/utilities.h>

#include <iostream>
#include <iomanip>

#ifdef DEAL_II_WITH_MPI
#include <nvector/nvector_parallel.h>
#endif

using namespace dealii;

D2K_NAMESPACE_OPEN

template <typename VEC>
IMEXStepper<VEC>::IMEXStepper(SundialsInterface<VEC> &interface,
                              const double &step_size,
                              const double &initial_time,
                              const double &final_time) :
  ParameterAcceptor("IMEX Parameters"),
  interface(interface),
  step_size(step_size),
  initial_time(initial_time),
  final_time(final_time),
  pout(std::cout, Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0)
{
  abs_tol = 1e-6;
  rel_tol = 1e-8;
  output_period = 1;
  newton_alpha = 1.0;
  max_outer_non_linear_iterations = 5;
  max_inner_non_linear_iterations = 3;
}

template <typename VEC>
void IMEXStepper<VEC>::declare_parameters(ParameterHandler &prm)
{
  add_parameter(prm, &step_size,
                "Step size", std::to_string(step_size), Patterns::Double());

  add_parameter(prm, &abs_tol,
                "Absolute error tolerance", std::to_string(abs_tol),
                Patterns::Double());

  add_parameter(prm, &rel_tol,
                "Relative error tolerance", std::to_string(rel_tol),
                Patterns::Double());

  add_parameter(prm, &initial_time,
                "Initial time", std::to_string(initial_time),
                Patterns::Double());

  add_parameter(prm, &final_time,
                "Final time", std::to_string(final_time),
                Patterns::Double());

  add_parameter(prm, &output_period,
                "Intervals between outputs", std::to_string(output_period),
                Patterns::Integer());

  add_parameter(prm, &max_outer_non_linear_iterations,
                "Maximum number of outer nonlinear iterations", std::to_string(max_outer_non_linear_iterations),
                Patterns::Integer(),
                "At each outer iteration the Jacobian is updated if it is set that the \n"
                "Jacobian is continuously updated and a cycle of inner iterations is \n"
                "perfomed.");

  add_parameter(prm, &max_inner_non_linear_iterations,
                "Maximum number of inner nonlinear iterations", std::to_string(max_inner_non_linear_iterations),
                Patterns::Integer(),
                "At each inner iteration the Jacobian is NOT updated.");

  add_parameter(prm, &newton_alpha,
                "Newton relaxation parameter", std::to_string(newton_alpha),
                Patterns::Double());

  add_parameter(prm, &update_jacobian_continuously,
                "Update continuously Jacobian", "true",
                Patterns::Bool());
}

template <typename VEC>
unsigned int IMEXStepper<VEC>::start_ode(VEC &solution, VEC &solution_dot)
{
  AssertDimension(solution.size(), interface.n_dofs());

  unsigned int step_number = 0;

  auto previous_solution = interface.create_new_vector();
  auto solution_update = interface.create_new_vector();
  auto residual = interface.create_new_vector();
  auto rhs = interface.create_new_vector();

  *previous_solution = solution;

  double t = initial_time;
  double alpha;

  // check if it is a stationary problem
  if (initial_time == final_time)
    alpha = 0.0;
  else
    alpha = 1./step_size;

  interface.output_step( 0, solution, solution_dot, 0, step_size);

  // Initialization of the state of the boolean variable
  // responsible to keep track of the requirement that the
  // system's Jacobian be updated.
  bool update_Jacobian = true;

  bool restart=false;
  // The overall cycle over time begins here.
  for (; t<=final_time+1e-15; t+= step_size, ++step_number)
    {
      pout << "Time = " << t << std::endl;
      // Implicit Euler scheme.
      solution_dot = solution;
      solution_dot -= *previous_solution;
      solution_dot *= alpha;

      // Initialization of two counters for the monitoring of
      // progress of the nonlinear solver.
      unsigned int inner_iter = 0;
      unsigned int outer_iter = 0;
      unsigned int nonlin_iter = 0;
      interface.residual(t, solution, solution_dot, *residual);
      double res_norm = 0.0;
      double solution_norm = 0.0;

      if (abs_tol>0.0||rel_tol>0.0)
        res_norm = interface.vector_norm(*residual);
      if (rel_tol>0.0)
        solution_norm = interface.vector_norm(solution);

      // The nonlinear solver iteration cycle begins here.
      while (outer_iter < max_outer_non_linear_iterations &&
             res_norm > abs_tol &&
             res_norm > rel_tol*solution_norm)
        {
          outer_iter += 1;
          if (update_Jacobian == true)
            {
              interface.setup_jacobian(t, solution, solution_dot,
                                       *residual, alpha);
            }

          inner_iter = 0;
          while (inner_iter < max_inner_non_linear_iterations &&
                 res_norm > abs_tol &&
                 res_norm > rel_tol*solution_norm)
            {
              inner_iter += 1;

              *rhs = *residual;
              *rhs *= -1.0;

              interface.solve_jacobian_system(t, solution, solution_dot,
                                              *residual, alpha,
                                              *rhs, *solution_update);
              solution.sadd(1.0,
                            newton_alpha, *solution_update);

              // Implicit Euler scheme.
              solution_dot = solution;
              solution_dot -= *previous_solution;
              solution_dot *= alpha;

              interface.residual(t, solution, solution_dot, *residual);

              if (abs_tol>0.0||rel_tol>0.0)
                res_norm = interface.vector_norm(*solution_update);
              if (rel_tol>0.0)
                solution_norm = interface.vector_norm(solution);

            }

          nonlin_iter += inner_iter;

          if (std::fabs(res_norm) < abs_tol ||
              std::fabs(res_norm) < rel_tol*solution_norm)
            {
              pout << std::endl
                   << "   "
                   << std::setw(19) << std::scientific << res_norm
                   << " (converged in "
                   << nonlin_iter
                   << " iterations)\n\n"
                   << std::endl;
              break; // Break of the while cycle ... after this a time advancement happens.
            }
          else if (outer_iter == max_outer_non_linear_iterations)
            {
              pout << std::endl
                   << "   "
                   << std::setw(19) << std::scientific << res_norm
                   << " (not converged in "
                   << std::setw(3) << nonlin_iter
                   << " iterations)\n\n"
                   << std::endl;
              AssertThrow(false,
                          ExcMessage ("No convergence in nonlinear solver"));
            }

        } // The nonlinear solver iteration cycle ends here.

      restart = interface.solver_should_restart(t,step_number,step_size,solution,solution_dot);

      if (restart)
        {
          previous_solution->reinit(solution,false);
          solution_update->reinit(solution,false);
          residual->reinit(solution,false);
          rhs->reinit(solution,false);
          t -= step_size;
          --step_number;
        }
      else
        {

          if ((step_number % output_period) == 0)
            interface.output_step(t, solution, solution_dot,  step_number, step_size);
        }

      *previous_solution = solution;
      update_Jacobian = update_jacobian_continuously;

    } // End of the cycle over time.
  return 0;
}

D2K_NAMESPACE_CLOSE

template class deal2lkit::IMEXStepper<BlockVector<double> >;

#ifdef DEAL_II_WITH_MPI

#ifdef DEAL_II_WITH_TRILINOS
template class deal2lkit::IMEXStepper<TrilinosWrappers::MPI::Vector>;
template class deal2lkit::IMEXStepper<TrilinosWrappers::MPI::BlockVector>;
#endif

#endif

#endif
<commit_msg>new pointers<commit_after>//-----------------------------------------------------------
//
//    Copyright (C) 2015 by the deal2lkit authors
//
//    This file is part of the deal2lkit library.
//
//    The deal2lkit library is free software; you can use it, 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.
//    The full text of the license can be found in the file LICENSE at
//    the top level of the deal2lkit distribution.
//
//-----------------------------------------------------------

#include <deal2lkit/sundials_interface.h>
#include <deal2lkit/imex_stepper.h>
#ifdef D2K_WITH_SUNDIALS

#include <deal.II/base/utilities.h>
#include <deal.II/lac/block_vector.h>
#ifdef DEAL_II_WITH_TRILINOS
#include <deal.II/lac/trilinos_block_vector.h>
#include <deal.II/lac/trilinos_parallel_block_vector.h>
#include <deal.II/lac/trilinos_vector.h>
#endif
#include <deal.II/base/utilities.h>

#include <iostream>
#include <iomanip>

#ifdef DEAL_II_WITH_MPI
#include <nvector/nvector_parallel.h>
#endif

using namespace dealii;

D2K_NAMESPACE_OPEN

template <typename VEC>
IMEXStepper<VEC>::IMEXStepper(SundialsInterface<VEC> &interface,
                              const double &step_size,
                              const double &initial_time,
                              const double &final_time) :
  ParameterAcceptor("IMEX Parameters"),
  interface(interface),
  step_size(step_size),
  initial_time(initial_time),
  final_time(final_time),
  pout(std::cout, Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0)
{
  abs_tol = 1e-6;
  rel_tol = 1e-8;
  output_period = 1;
  newton_alpha = 1.0;
  max_outer_non_linear_iterations = 5;
  max_inner_non_linear_iterations = 3;
}

template <typename VEC>
void IMEXStepper<VEC>::declare_parameters(ParameterHandler &prm)
{
  add_parameter(prm, &step_size,
                "Step size", std::to_string(step_size), Patterns::Double());

  add_parameter(prm, &abs_tol,
                "Absolute error tolerance", std::to_string(abs_tol),
                Patterns::Double());

  add_parameter(prm, &rel_tol,
                "Relative error tolerance", std::to_string(rel_tol),
                Patterns::Double());

  add_parameter(prm, &initial_time,
                "Initial time", std::to_string(initial_time),
                Patterns::Double());

  add_parameter(prm, &final_time,
                "Final time", std::to_string(final_time),
                Patterns::Double());

  add_parameter(prm, &output_period,
                "Intervals between outputs", std::to_string(output_period),
                Patterns::Integer());

  add_parameter(prm, &max_outer_non_linear_iterations,
                "Maximum number of outer nonlinear iterations", std::to_string(max_outer_non_linear_iterations),
                Patterns::Integer(),
                "At each outer iteration the Jacobian is updated if it is set that the \n"
                "Jacobian is continuously updated and a cycle of inner iterations is \n"
                "perfomed.");

  add_parameter(prm, &max_inner_non_linear_iterations,
                "Maximum number of inner nonlinear iterations", std::to_string(max_inner_non_linear_iterations),
                Patterns::Integer(),
                "At each inner iteration the Jacobian is NOT updated.");

  add_parameter(prm, &newton_alpha,
                "Newton relaxation parameter", std::to_string(newton_alpha),
                Patterns::Double());

  add_parameter(prm, &update_jacobian_continuously,
                "Update continuously Jacobian", "true",
                Patterns::Bool());
}

template <typename VEC>
unsigned int IMEXStepper<VEC>::start_ode(VEC &solution, VEC &solution_dot)
{
  AssertDimension(solution.size(), interface.n_dofs());

  unsigned int step_number = 0;

  auto previous_solution = interface.create_new_vector();
  auto solution_update = interface.create_new_vector();
  auto residual = interface.create_new_vector();
  auto rhs = interface.create_new_vector();

  *previous_solution = solution;

  double t = initial_time;
  double alpha;

  // check if it is a stationary problem
  if (initial_time == final_time)
    alpha = 0.0;
  else
    alpha = 1./step_size;

  interface.output_step( 0, solution, solution_dot, 0, step_size);

  // Initialization of the state of the boolean variable
  // responsible to keep track of the requirement that the
  // system's Jacobian be updated.
  bool update_Jacobian = true;

  bool restart=false;
  // The overall cycle over time begins here.
  for (; t<=final_time+1e-15; t+= step_size, ++step_number)
    {
      pout << "Time = " << t << std::endl;
      // Implicit Euler scheme.
      solution_dot = solution;
      solution_dot -= *previous_solution;
      solution_dot *= alpha;

      // Initialization of two counters for the monitoring of
      // progress of the nonlinear solver.
      unsigned int inner_iter = 0;
      unsigned int outer_iter = 0;
      unsigned int nonlin_iter = 0;
      interface.residual(t, solution, solution_dot, *residual);
      double res_norm = 0.0;
      double solution_norm = 0.0;

      if (abs_tol>0.0||rel_tol>0.0)
        res_norm = interface.vector_norm(*residual);
      if (rel_tol>0.0)
        solution_norm = interface.vector_norm(solution);

      // The nonlinear solver iteration cycle begins here.
      while (outer_iter < max_outer_non_linear_iterations &&
             res_norm > abs_tol &&
             res_norm > rel_tol*solution_norm)
        {
          outer_iter += 1;
          if (update_Jacobian == true)
            {
              interface.setup_jacobian(t, solution, solution_dot,
                                       *residual, alpha);
            }

          inner_iter = 0;
          while (inner_iter < max_inner_non_linear_iterations &&
                 res_norm > abs_tol &&
                 res_norm > rel_tol*solution_norm)
            {
              inner_iter += 1;

              *rhs = *residual;
              *rhs *= -1.0;

              interface.solve_jacobian_system(t, solution, solution_dot,
                                              *residual, alpha,
                                              *rhs, *solution_update);
              solution.sadd(1.0,
                            newton_alpha, *solution_update);

              // Implicit Euler scheme.
              solution_dot = solution;
              solution_dot -= *previous_solution;
              solution_dot *= alpha;

              interface.residual(t, solution, solution_dot, *residual);

              if (abs_tol>0.0||rel_tol>0.0)
                res_norm = interface.vector_norm(*solution_update);
              if (rel_tol>0.0)
                solution_norm = interface.vector_norm(solution);

            }

          nonlin_iter += inner_iter;

          if (std::fabs(res_norm) < abs_tol ||
              std::fabs(res_norm) < rel_tol*solution_norm)
            {
              pout << std::endl
                   << "   "
                   << std::setw(19) << std::scientific << res_norm
                   << " (converged in "
                   << nonlin_iter
                   << " iterations)\n\n"
                   << std::endl;
              break; // Break of the while cycle ... after this a time advancement happens.
            }
          else if (outer_iter == max_outer_non_linear_iterations)
            {
              pout << std::endl
                   << "   "
                   << std::setw(19) << std::scientific << res_norm
                   << " (not converged in "
                   << std::setw(3) << nonlin_iter
                   << " iterations)\n\n"
                   << std::endl;
              AssertThrow(false,
                          ExcMessage ("No convergence in nonlinear solver"));
            }

        } // The nonlinear solver iteration cycle ends here.

      restart = interface.solver_should_restart(t,step_number,step_size,solution,solution_dot);

      if (restart)
        {
	  previous_solution = interface.create_new_vector();
	  solution_update = interface.create_new_vector();
	  residual = interface.create_new_vector();
	  rhs = interface.create_new_vector();

          t -= step_size;
          --step_number;
        }
      else
        {

          if ((step_number % output_period) == 0)
            interface.output_step(t, solution, solution_dot,  step_number, step_size);
        }

      *previous_solution = solution;
      update_Jacobian = update_jacobian_continuously;

    } // End of the cycle over time.
  return 0;
}

D2K_NAMESPACE_CLOSE

template class deal2lkit::IMEXStepper<BlockVector<double> >;

#ifdef DEAL_II_WITH_MPI

#ifdef DEAL_II_WITH_TRILINOS
template class deal2lkit::IMEXStepper<TrilinosWrappers::MPI::Vector>;
template class deal2lkit::IMEXStepper<TrilinosWrappers::MPI::BlockVector>;
#endif

#endif

#endif
<|endoftext|>


<commit_before><commit_msg>This CL fixes issue 17468 - Regression: Extra white rectangle showing when mouse hovering on every web page<commit_after><|endoftext|>


<commit_before>#include "worker.h"
#include <QTextStream>

Worker::Worker(QObject *parent) : QObject(parent){}

void Worker::worker_slot_loadFile(QFile *file)
{
    QString line = "";
    QString text = "";
    QTextStream in(file);
    while (!in.atEnd()) {
      line = in.readLine();
      text.append(line + "\n");
    }
    in.flush();
    file->close();

    text.remove(text.lastIndexOf("\n"),1);
    emit worker_signal_appendText(text);
}
<commit_msg>Update worker.cpp<commit_after>#include "worker.h"
#include <QTextStream>
#include <QDebug>

Worker::Worker(QObject *parent) : QObject(parent){
    giFileSize = 0;
}

void Worker::worker_slot_loadFile(QFile *file)
{
    QString line = "";
    QString text = "";
    QTextStream in(file);
    while (!in.atEnd()) {
      line = in.readLine();
      text.append(line + "\n");
    }
    in.flush();
    file->close();
    text.remove(text.lastIndexOf("\n"),1);
    emit worker_signal_appendText(text);
}

void Worker::worker_slot_tailFile(QFile *file)
{
    if(file->size() > giFileSize) {
        int liDiff = file->size() - giFileSize;
        if(file->open(QIODevice::ReadOnly | QIODevice::Text)) {
            if(file->seek(giFileSize)) {
                QString lsText = QString(file->read(liDiff));
                emit worker_signal_insertText(lsText);
                giFileSize = file->size();
            }
            file->close();
        }
    } else {
        giFileSize = file->size();
    }
}

void Worker::worker_slot_setCurrentFileSize(int aiFileSize)
{
    this->giFileSize = aiFileSize;
}

<|endoftext|>