<commit_before>#include <string>
#include <stdexcept>
#include <memory>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include "window.h"

//Initialize the unique_ptr's deleters here
std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> Window::mWindow
	= std::unique_ptr<SDL_Window, void (*)(SDL_Window*)>(nullptr, SDL_DestroyWindow);
std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> Window::mRenderer
	= std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)>(nullptr, SDL_DestroyRenderer);
//Other static members
SDL_Rect Window::mBox;

Window::Window(){
}
Window::~Window(){
}
void Window::Init(std::string title){
    //initialize all SDL subsystems
    if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
		throw std::runtime_error("SDL Init Failed");
    if (TTF_Init() == -1)
		throw std::runtime_error("TTF Init Failed");

    //Setup our window size
    mBox.x = 0;
    mBox.y = 0;
    mBox.w = 640;
    mBox.h = 480;
    //Create our window
    mWindow.reset(SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        mBox.w, mBox.h, SDL_WINDOW_SHOWN));
    //Make sure it created ok
    if (mWindow == nullptr)
        throw std::runtime_error("Failed to create window");

    //Create the renderer
    mRenderer.reset(SDL_CreateRenderer(mWindow.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC));
    //Make sure it created ok
    if (mRenderer == nullptr)
        throw std::runtime_error("Failed to create renderer");
}
void Window::Quit(){
    TTF_Quit();
    SDL_Quit();
}
void Window::Draw(SDL_Texture *tex, SDL_Rect &dstRect, SDL_Rect *clip, float angle,
                  int xPivot, int yPivot, SDL_RendererFlip flip)
{
    //Convert pivot pos from relative to object's center to screen space
    xPivot += dstRect.w / 2;
    yPivot += dstRect.h / 2;
    //SDL expects an SDL_Point as the pivot location
    SDL_Point pivot = { xPivot, yPivot };
    //Draw the texture
    SDL_RenderCopyEx(mRenderer.get(), tex, clip, &dstRect, angle, &pivot, flip);
}
SDL_Texture* Window::LoadImage(const std::string &file){
    SDL_Texture* tex = nullptr;
	tex = IMG_LoadTexture(mRenderer.get(), file.c_str());
	if (tex == nullptr)
		throw std::runtime_error("Failed to load image: " + file + IMG_GetError());
	return tex;
}
SDL_Texture* Window::RenderText(const std::string &message, const std::string &fontFile, SDL_Color color, int fontSize){
    //Open the font
	TTF_Font *font = nullptr;
	font = TTF_OpenFont(fontFile.c_str(), fontSize);
	if (font == nullptr)
		throw std::runtime_error("Failed to load font: " + fontFile + TTF_GetError());

	//Render the message to an SDL_Surface, as that's what TTF_RenderText_X returns
	SDL_Surface *surf = TTF_RenderText_Blended(font, message.c_str(), color);
	SDL_Texture *texture = SDL_CreateTextureFromSurface(mRenderer.get(), surf);
	//Clean up unneeded stuff
	SDL_FreeSurface(surf);
	TTF_CloseFont(font);

	return texture;
}
void Window::Clear(){
    SDL_RenderClear(mRenderer.get());
}
void Window::Present(){
    SDL_RenderPresent(mRenderer.get());
}
SDL_Rect Window::Box(){
    //Update mBox to match the current window size
    SDL_GetWindowSize(mWindow.get(), &mBox.w, &mBox.h);
    return mBox;
}
<commit_msg>cleaning some formatting issues<commit_after>#include <string>
#include <stdexcept>
#include <memory>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include "window.h"

//Initialize the unique_ptr's deleters here
std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> Window::mWindow
	= std::unique_ptr<SDL_Window, void (*)(SDL_Window*)>(nullptr, SDL_DestroyWindow);
std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> Window::mRenderer
	= std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)>(nullptr, SDL_DestroyRenderer);
//Other static members
SDL_Rect Window::mBox;

Window::Window(){
}
Window::~Window(){
}
void Window::Init(std::string title){
    //initialize all SDL subsystems
    if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
		throw std::runtime_error("SDL Init Failed");
    if (TTF_Init() == -1)
		throw std::runtime_error("TTF Init Failed");

    //Setup our window size
    mBox.x = 0;
    mBox.y = 0;
    mBox.w = 640;
    mBox.h = 480;
    //Create our window
    mWindow.reset(SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        mBox.w, mBox.h, SDL_WINDOW_SHOWN));
    //Make sure it created ok
    if (mWindow == nullptr)
        throw std::runtime_error("Failed to create window");

    //Create the renderer
    mRenderer.reset(SDL_CreateRenderer(mWindow.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC));
    //Make sure it created ok
    if (mRenderer == nullptr)
        throw std::runtime_error("Failed to create renderer");
}
void Window::Quit(){
    TTF_Quit();
    SDL_Quit();
}
void Window::Draw(SDL_Texture *tex, SDL_Rect &dstRect, SDL_Rect *clip, float angle,
                  int xPivot, int yPivot, SDL_RendererFlip flip)
{
    //Convert pivot pos from relative to object's center to screen space
    xPivot += dstRect.w / 2;
    yPivot += dstRect.h / 2;
    //SDL expects an SDL_Point as the pivot location
    SDL_Point pivot = { xPivot, yPivot };
    //Draw the texture
    SDL_RenderCopyEx(mRenderer.get(), tex, clip, &dstRect, angle, &pivot, flip);
}
SDL_Texture* Window::LoadImage(const std::string &file){
    SDL_Texture* tex = nullptr;
    tex = IMG_LoadTexture(mRenderer.get(), file.c_str());
    if (tex == nullptr)
        throw std::runtime_error("Failed to load image: " + file + IMG_GetError());
    return tex;
}
SDL_Texture* Window::RenderText(const std::string &message, const std::string &fontFile, SDL_Color color, int fontSize){
    //Open the font
    TTF_Font *font = nullptr;
    font = TTF_OpenFont(fontFile.c_str(), fontSize);
    if (font == nullptr)
        throw std::runtime_error("Failed to load font: " + fontFile + TTF_GetError());

    //Render the message to an SDL_Surface, as that's what TTF_RenderText_X returns
    SDL_Surface *surf = TTF_RenderText_Blended(font, message.c_str(), color);
    SDL_Texture *texture = SDL_CreateTextureFromSurface(mRenderer.get(), surf);
    //Clean up unneeded stuff
    SDL_FreeSurface(surf);
    TTF_CloseFont(font);

    return texture;
}
void Window::Clear(){
    SDL_RenderClear(mRenderer.get());
}
void Window::Present(){
    SDL_RenderPresent(mRenderer.get());
}
SDL_Rect Window::Box(){
    //Update mBox to match the current window size
    SDL_GetWindowSize(mWindow.get(), &mBox.w, &mBox.h);
    return mBox;
}
<|endoftext|>


<commit_before>/*
 * PrimeSieve.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2011 Kim Walisch, <kim.walisch@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#include "PrimeSieve.h"
#include "defs.h"
#include "ParallelPrimeSieve.h"
#include "pmath.h"
#include "ResetSieve.h"
#include "PrimeNumberFinder.h"
#include "PrimeNumberGenerator.h"

#include <stdexcept>
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>

PrimeSieve::PrimeSieve() :
  startNumber_(0), stopNumber_(0),
    sieveSize_(defs::SIEVESIZE_PRIMENUMBERFINDER), flags_(COUNT_PRIMES),
    timeElapsed_(0.0) {
  parent_ = this;
  this->reset();
}

/**
 * Is used by ParallelPrimeSieve which uses multiple PrimeSieve
 * objects and threads to sieve primes in parallel.
 * @see ParallelPrimeSieve::sieve()
 */
PrimeSieve::PrimeSieve(uint64_t startNumber, uint64_t stopNumber,
    ParallelPrimeSieve* parent) :
  sieveSize_(parent->sieveSize_), flags_(parent->flags_), timeElapsed_(0.0),
    callback_imp(parent->callback_imp),
    callback_oop(parent->callback_oop),
    cbObj_(parent->cbObj_),
    parent_(parent) {
  this->setStartNumber(startNumber);
  this->setStopNumber(stopNumber);
  this->reset();
}

uint64_t PrimeSieve::getStartNumber() const {
  return startNumber_;
}

uint64_t PrimeSieve::getStopNumber() const {
  return stopNumber_;
}

uint32_t PrimeSieve::getSieveSize() const {
  return sieveSize_ / 1024;
}

uint32_t PrimeSieve::getFlags() const {
  // hide internal flags
  return flags_ & ((1u << 20) - 1);
}

/**
 * Generate the prime numbers between startNumber and stopNumber and
 * call a callback function for each prime.
 */
void PrimeSieve::generatePrimes(uint64_t startNumber, uint64_t stopNumber,
    void (*callback)(uint64_t)) {
  if (callback == NULL)
    throw std::invalid_argument("callback must not be NULL");
  this->setStartNumber(startNumber);
  this->setStopNumber(stopNumber);
  this->setFlags(CALLBACK_PRIMES_IMP);
  callback_imp = callback;
  this->sieve();
}

/**
 * Generate the prime numbers between startNumber and stopNumber and
 * call an OOP style callback function for each prime.
 */
void PrimeSieve::generatePrimes(uint64_t startNumber, uint64_t stopNumber,
    void (*callback)(uint64_t, void*), void* cbObj) {
  if (callback == NULL)
    throw std::invalid_argument("callback must not be NULL");
  this->setStartNumber(startNumber);
  this->setStopNumber(stopNumber);
  this->setFlags(CALLBACK_PRIMES_OOP);
  callback_oop = callback;
  cbObj_ = cbObj;
  this->sieve();
}

/**
 * Get the count of prime numbers between startNumber and stopNumber.
 */
uint64_t PrimeSieve::getPrimeCount(uint64_t startNumber, uint64_t stopNumber) {
  this->setStartNumber(startNumber);
  this->setStopNumber(stopNumber);
  this->setFlags(COUNT_PRIMES);
  this->sieve();
  return this->getPrimeCount();
}

/**
 * Get the count of prime numbers between startNumber and stopNumber
 * after having called sieve().
 */
uint64_t PrimeSieve::getPrimeCount() const {
  return counts_[0];
}

/**
 * Get the count of twin primes between startNumber and stopNumber
 * after having called sieve().
 */
uint64_t PrimeSieve::getTwinCount() const {
  return counts_[1];
}

/**
 * Get the count of prime triplets between startNumber and stopNumber
 * after having called sieve().
 */
uint64_t PrimeSieve::getTripletCount() const {
  return counts_[2];
}

/**
 * Get the count of prime quadruplets between startNumber and
 * stopNumber after having called sieve().
 */
uint64_t PrimeSieve::getQuadrupletCount() const {
  return counts_[3];
}

/**
 * Get the count of prime quintuplets between startNumber and
 * stopNumber after having called sieve().
 */
uint64_t PrimeSieve::getQuintupletCount() const {
  return counts_[4];
}

/**
 * Get the count of prime sextuplets between startNumber and
 * stopNumber after having called sieve().
 */
uint64_t PrimeSieve::getSextupletCount() const {
  return counts_[5];
}

/**
 * Get the count of prime septuplets between startNumber and
 * stopNumber after having called sieve().
 */
uint64_t PrimeSieve::getSeptupletCount() const {
  return counts_[6];
}

/**
 * Get the count of prime numbers or prime k-tuplets between
 * startNumber and stopNumber after having called sieve().
 * e.g type = 0 for prime numbers,
 *     type = 1 for twin primes,
 *     type = 2 for prime triplets,
 *     ...
 * @param type <= 7
 */
uint64_t PrimeSieve::getCounts(uint32_t type) const {
  if (type >= COUNTS_SIZE)
    throw std::out_of_range("getCounts(uint32_t) type out of range");
  return counts_[type];
}

/**
 * Get the time elapsed in seconds of the last sieve session.
 */
double PrimeSieve::getTimeElapsed() const {
  return timeElapsed_;
}

/**
 * Set a start number for sieving.
 * @pre startNumber < (2^64-1) - (2^32-1) * 10
 */
void PrimeSieve::setStartNumber(uint64_t startNumber) {
  // EratBig and EratMedium stopNumber limit
  if (startNumber >= UINT64_MAX - UINT32_MAX * UINT64_C(10))
    throw std::invalid_argument("START must be < (2^64-1) - (2^32-1) * 10");
  startNumber_ = startNumber;
}

/**
 * Set a stop number for sieving.
 * @pre stopNumber < (2^64-1) - (2^32-1) * 10
 */
void PrimeSieve::setStopNumber(uint64_t stopNumber) {
  // EratBig and EratMedium stopNumber limit
  if (stopNumber >= UINT64_MAX - UINT32_MAX * UINT64_C(10))
    throw std::invalid_argument("STOP must be < (2^64-1) - (2^32-1) * 10");
  stopNumber_ = stopNumber;
}

/**
 * Set the size (in KiloBytes) of the sieve of Eratosthenes array.
 * The best performance is achieved with a sieve size that matches
 * the CPU's L1 cache size (usually 32 or 64 KB) when sieving < 10^14
 * and a sieve size of your CPU's L2 cache size above.
 *
 * Default sieveSize = 64 KiloBytes
 *
 * @pre sieveSize must be a power of 2,
 *      sieveSize >= 1 KiloByte,
 *      sieveSize <= 8192 KiloBytes.
 */
void PrimeSieve::setSieveSize(uint32_t sieveSize) {
  // SieveOfEratosthenes lower sieve size limit AND
  // EratBig upper sieveSize limit
  if (sieveSize < 1 || sieveSize > 8192)
    throw std::invalid_argument("sieve size must be >= 1 and <= 8192 KiloBytes");
  // EratBig requires a power of 2 sieve size
  if (!isPowerOf2(sieveSize))
    throw std::invalid_argument("sieve size must be a power of 2");
  // convert to Bytes
  sieveSize_ = sieveSize * 1024;
}

/**
 * Set the flags (settings) of PrimeSieve.
 * @param flags
 *   PrimeSieve::COUNT_PRIMES      OR (bitwise '|')
 *   PrimeSieve::COUNT_TWINS       OR
 *   PrimeSieve::COUNT_TRIPLETS    OR
 *   PrimeSieve::COUNT_QUADRUPLETS OR
 *   PrimeSieve::COUNT_QUINTUPLETS OR
 *   PrimeSieve::COUNT_SEXTUPLETS  OR
 *   PrimeSieve::COUNT_SEPTUPLETS  OR
 *   PrimeSieve::PRINT_PRIMES      OR
 *   PrimeSieve::PRINT_TWINS       OR
 *   PrimeSieve::PRINT_TRIPLETS    OR
 *   PrimeSieve::PRINT_QUADRUPLETS OR
 *   PrimeSieve::PRINT_QUINTUPLETS OR
 *   PrimeSieve::PRINT_SEXTUPLETS  OR
 *   PrimeSieve::PRINT_SEPTUPLETS  OR
 *   PrimeSieve::PRINT_STATUS.
 */
void PrimeSieve::setFlags(uint32_t flags) {
  if (flags >= (1u << 20))
    throw std::invalid_argument("invalid flags");
  flags_ = flags;
}

void PrimeSieve::reset() {
  segments_ = 0;
  for (uint32_t i = 0; i < COUNTS_SIZE; i++)
    counts_[i] = 0;
  status_ = -1.0;
  parent_->doStatus(0);
}

/**
 * Print the status (in percent) of the sieving process
 * to the standard output.
 */
void PrimeSieve::doStatus(uint64_t segment) {
  segments_ += segment;
  double old = status_;
  status_ = static_cast<double> (segments_) /
            static_cast<double> (1 + stopNumber_ - startNumber_) * 100.0;
  if (static_cast<int> (status_) > 99)
    status_ = 100.0;
  if ((flags_ & PRINT_STATUS) &&
      static_cast<int> (status_) > static_cast<int> (old)) {
    std::cout << '\r' << static_cast<int> (status_) << '%' << std::flush;
  }
}

void PrimeSieve::doSmallPrime(uint32_t low, uint32_t high, uint32_t type,
    std::string prime) {
  if (startNumber_ <= low && stopNumber_ >= high) {
    if (flags_ & (COUNT_PRIMES << type))
      counts_[type]++;
    if (flags_ & (PRINT_PRIMES << type))
      std::cout << prime << std::endl;
    else if (flags_ & CALLBACK_PRIMES_IMP)
      this->callback_imp(prime[0]-'0');
    else if (flags_ & CALLBACK_PRIMES_OOP)
      this->callback_oop(prime[0]-'0', cbObj_);
  }
}

/**
 * Sieve the prime numbers and/or prime k-tuplets between startNumber
 * and stopNumber.
 */
void PrimeSieve::sieve() {
  if (stopNumber_ < startNumber_)
    throw std::invalid_argument("STOP must be >= START");
  timeElapsed_ = static_cast<double> (std::clock());
  this->reset();

  // small primes have to be examined manually
  if (startNumber_ <= 5) {
    this->doSmallPrime(2,  2, 0, "2");
    this->doSmallPrime(3,  3, 0, "3");
    this->doSmallPrime(5,  5, 0, "5");
    this->doSmallPrime(3,  5, 1, "(3, 5)");
    this->doSmallPrime(5,  7, 1, "(5, 7)");
    this->doSmallPrime(5, 11, 2, "(5, 7, 11)");
    this->doSmallPrime(5, 13, 3, "(5, 7, 11, 13)");
    this->doSmallPrime(5, 17, 4, "(5, 7, 11, 13, 17)");
  }

  if (stopNumber_ >= 7) {
    // needed by primeNumberGenerator and primeNumberFinder to
    // reset their sieve arrays
    ResetSieve resetSieve(this);
    // used to sieve the prime numbers and prime k-tuplets between
    // startNumber_ and stopNumber_
    PrimeNumberFinder primeNumberFinder(this, &resetSieve);

    if (isqrt(stopNumber_) > resetSieve.getLimit()) {
      // used to generate the prime numbers up to sqrt(stopNumber_)
      // needed for sieving by primeNumberFinder
      PrimeNumberGenerator primeNumberGenerator(&primeNumberFinder);
      std::vector<uint32_t> primes16Bit;
      primes16Bit.push_back(3);
      uint32_t stop = isqrt(primeNumberGenerator.getStopNumber());
      uint32_t keep = isqrt(stop);
      // the following trial division algorithm is used to generate the
      // prime numbers up to stopNumber_^0.25 needed for sieving by
      // primeNumberGenerator. Although the algorithm is never
      // used > 65536 it finds the prime numbers up to 10^7 in 1 second
      // on an Intel Core i5-670 3.46GHz
      for (uint32_t n = 5; n <= stop; n += 2) {
        uint32_t s = isqrt(n);
        uint32_t i = 0;
        for (; primes16Bit[i] <= s && (n % primes16Bit[i]) != 0; i++)
          ;
        if (primes16Bit[i] > s) {
          if (primes16Bit[i] <= keep)
            primes16Bit.push_back(n);
          if (n > resetSieve.getLimit())
            // generate the prime numbers up to n^2 and call
            // primeNumberFinder.sieve(p) for each generated prime
            primeNumberGenerator.sieve(n);
        }
      }
      primeNumberGenerator.finish();
    }
    primeNumberFinder.finish();
  }

  // set status_ to 100.0 (percent)
  parent_->doStatus(10);
  timeElapsed_ = (static_cast<double> (std::clock()) - timeElapsed_) /
      static_cast<double> (CLOCKS_PER_SEC);
}
<commit_msg>updated documentation<commit_after>/*
 * PrimeSieve.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2011 Kim Walisch, <kim.walisch@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#include "PrimeSieve.h"
#include "defs.h"
#include "ParallelPrimeSieve.h"
#include "pmath.h"
#include "ResetSieve.h"
#include "PrimeNumberFinder.h"
#include "PrimeNumberGenerator.h"

#include <stdexcept>
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>

PrimeSieve::PrimeSieve() :
  startNumber_(0), stopNumber_(0),
    sieveSize_(defs::SIEVESIZE_PRIMENUMBERFINDER), flags_(COUNT_PRIMES),
    timeElapsed_(0.0) {
  parent_ = this;
  this->reset();
}

/**
 * Is used by ParallelPrimeSieve which uses multiple PrimeSieve
 * objects and threads to sieve primes in parallel.
 * @see ParallelPrimeSieve::sieve()
 */
PrimeSieve::PrimeSieve(uint64_t startNumber, uint64_t stopNumber,
    ParallelPrimeSieve* parent) :
  sieveSize_(parent->sieveSize_), flags_(parent->flags_), timeElapsed_(0.0),
    callback_imp(parent->callback_imp),
    callback_oop(parent->callback_oop),
    cbObj_(parent->cbObj_),
    parent_(parent) {
  this->setStartNumber(startNumber);
  this->setStopNumber(stopNumber);
  this->reset();
}

uint64_t PrimeSieve::getStartNumber() const {
  return startNumber_;
}

uint64_t PrimeSieve::getStopNumber() const {
  return stopNumber_;
}

uint32_t PrimeSieve::getSieveSize() const {
  return sieveSize_ / 1024;
}

uint32_t PrimeSieve::getFlags() const {
  // hide internal flags
  return flags_ & ((1u << 20) - 1);
}

/**
 * Generate the prime numbers between startNumber and stopNumber and
 * call a callback function for each prime.
 */
void PrimeSieve::generatePrimes(uint64_t startNumber, uint64_t stopNumber,
    void (*callback)(uint64_t)) {
  if (callback == NULL)
    throw std::invalid_argument("callback must not be NULL");
  this->setStartNumber(startNumber);
  this->setStopNumber(stopNumber);
  this->setFlags(CALLBACK_PRIMES_IMP);
  callback_imp = callback;
  this->sieve();
}

/**
 * Generate the prime numbers between startNumber and stopNumber and
 * call an OOP style callback function for each prime.
 */
void PrimeSieve::generatePrimes(uint64_t startNumber, uint64_t stopNumber,
    void (*callback)(uint64_t, void*), void* cbObj) {
  if (callback == NULL)
    throw std::invalid_argument("callback must not be NULL");
  this->setStartNumber(startNumber);
  this->setStopNumber(stopNumber);
  this->setFlags(CALLBACK_PRIMES_OOP);
  callback_oop = callback;
  cbObj_ = cbObj;
  this->sieve();
}

/**
 * Get the count of prime numbers between startNumber and stopNumber.
 */
uint64_t PrimeSieve::getPrimeCount(uint64_t startNumber, uint64_t stopNumber) {
  this->setStartNumber(startNumber);
  this->setStopNumber(stopNumber);
  this->setFlags(COUNT_PRIMES);
  this->sieve();
  return this->getPrimeCount();
}

/**
 * Get the count of prime numbers between startNumber and stopNumber
 * after having called sieve().
 */
uint64_t PrimeSieve::getPrimeCount() const {
  return counts_[0];
}

/**
 * Get the count of twin primes between startNumber and stopNumber
 * after having called sieve().
 */
uint64_t PrimeSieve::getTwinCount() const {
  return counts_[1];
}

/**
 * Get the count of prime triplets between startNumber and stopNumber
 * after having called sieve().
 */
uint64_t PrimeSieve::getTripletCount() const {
  return counts_[2];
}

/**
 * Get the count of prime quadruplets between startNumber and
 * stopNumber after having called sieve().
 */
uint64_t PrimeSieve::getQuadrupletCount() const {
  return counts_[3];
}

/**
 * Get the count of prime quintuplets between startNumber and
 * stopNumber after having called sieve().
 */
uint64_t PrimeSieve::getQuintupletCount() const {
  return counts_[4];
}

/**
 * Get the count of prime sextuplets between startNumber and
 * stopNumber after having called sieve().
 */
uint64_t PrimeSieve::getSextupletCount() const {
  return counts_[5];
}

/**
 * Get the count of prime septuplets between startNumber and
 * stopNumber after having called sieve().
 */
uint64_t PrimeSieve::getSeptupletCount() const {
  return counts_[6];
}

/**
 * Get the count of prime numbers or prime k-tuplets between
 * startNumber and stopNumber after having called sieve().
 * e.g type = 0 for prime numbers,
 *     type = 1 for twin primes,
 *     type = 2 for prime triplets,
 *     ...
 * @param type <= 7
 */
uint64_t PrimeSieve::getCounts(uint32_t type) const {
  if (type >= COUNTS_SIZE)
    throw std::out_of_range("getCounts(uint32_t) type out of range");
  return counts_[type];
}

/**
 * Get the time elapsed in seconds of the last sieve session.
 */
double PrimeSieve::getTimeElapsed() const {
  return timeElapsed_;
}

/**
 * Set a start number for sieving.
 * @pre startNumber < (2^64-1) - (2^32-1) * 10
 */
void PrimeSieve::setStartNumber(uint64_t startNumber) {
  // EratBig and EratMedium stopNumber limit
  if (startNumber >= UINT64_MAX - UINT32_MAX * UINT64_C(10))
    throw std::invalid_argument("START must be < (2^64-1) - (2^32-1) * 10");
  startNumber_ = startNumber;
}

/**
 * Set a stop number for sieving.
 * @pre stopNumber < (2^64-1) - (2^32-1) * 10
 */
void PrimeSieve::setStopNumber(uint64_t stopNumber) {
  // EratBig and EratMedium stopNumber limit
  if (stopNumber >= UINT64_MAX - UINT32_MAX * UINT64_C(10))
    throw std::invalid_argument("STOP must be < (2^64-1) - (2^32-1) * 10");
  stopNumber_ = stopNumber;
}

/**
 * Set the size (in KiloBytes) of the sieve of Eratosthenes array.
 * The best performance is achieved with a sieve size that matches
 * the CPU's L1 cache size (usually 32 or 64 KB) when sieving < 10^14
 * and a sieve size of the CPU's L2 cache size above.
 *
 * Default sieveSize = 64 KiloBytes
 *
 * @pre sieveSize must be a power of 2,
 *      sieveSize >= 1 KiloByte,
 *      sieveSize <= 8192 KiloBytes.
 */
void PrimeSieve::setSieveSize(uint32_t sieveSize) {
  // SieveOfEratosthenes lower sieve size limit AND
  // EratBig upper sieveSize limit
  if (sieveSize < 1 || sieveSize > 8192)
    throw std::invalid_argument("sieve size must be >= 1 and <= 8192 KiloBytes");
  // EratBig requires a power of 2 sieve size
  if (!isPowerOf2(sieveSize))
    throw std::invalid_argument("sieve size must be a power of 2");
  // convert to Bytes
  sieveSize_ = sieveSize * 1024;
}

/**
 * Set the flags (settings) of PrimeSieve.
 * @param flags
 *   PrimeSieve::COUNT_PRIMES      OR (bitwise '|')
 *   PrimeSieve::COUNT_TWINS       OR
 *   PrimeSieve::COUNT_TRIPLETS    OR
 *   PrimeSieve::COUNT_QUADRUPLETS OR
 *   PrimeSieve::COUNT_QUINTUPLETS OR
 *   PrimeSieve::COUNT_SEXTUPLETS  OR
 *   PrimeSieve::COUNT_SEPTUPLETS  OR
 *   PrimeSieve::PRINT_PRIMES      OR
 *   PrimeSieve::PRINT_TWINS       OR
 *   PrimeSieve::PRINT_TRIPLETS    OR
 *   PrimeSieve::PRINT_QUADRUPLETS OR
 *   PrimeSieve::PRINT_QUINTUPLETS OR
 *   PrimeSieve::PRINT_SEXTUPLETS  OR
 *   PrimeSieve::PRINT_SEPTUPLETS  OR
 *   PrimeSieve::PRINT_STATUS.
 */
void PrimeSieve::setFlags(uint32_t flags) {
  if (flags >= (1u << 20))
    throw std::invalid_argument("invalid flags");
  flags_ = flags;
}

void PrimeSieve::reset() {
  segments_ = 0;
  for (uint32_t i = 0; i < COUNTS_SIZE; i++)
    counts_[i] = 0;
  status_ = -1.0;
  parent_->doStatus(0);
}

/**
 * Print the status (in percent) of the sieving process
 * to the standard output.
 */
void PrimeSieve::doStatus(uint64_t segment) {
  segments_ += segment;
  double old = status_;
  status_ = static_cast<double> (segments_) /
            static_cast<double> (1 + stopNumber_ - startNumber_) * 100.0;
  if (static_cast<int> (status_) > 99)
    status_ = 100.0;
  if ((flags_ & PRINT_STATUS) &&
      static_cast<int> (status_) > static_cast<int> (old)) {
    std::cout << '\r' << static_cast<int> (status_) << '%' << std::flush;
  }
}

void PrimeSieve::doSmallPrime(uint32_t low, uint32_t high, uint32_t type,
    std::string prime) {
  if (startNumber_ <= low && stopNumber_ >= high) {
    if (flags_ & (COUNT_PRIMES << type))
      counts_[type]++;
    if (flags_ & (PRINT_PRIMES << type))
      std::cout << prime << std::endl;
    else if (flags_ & CALLBACK_PRIMES_IMP)
      this->callback_imp(prime[0]-'0');
    else if (flags_ & CALLBACK_PRIMES_OOP)
      this->callback_oop(prime[0]-'0', cbObj_);
  }
}

/**
 * Sieve the prime numbers and/or prime k-tuplets between startNumber
 * and stopNumber.
 */
void PrimeSieve::sieve() {
  if (stopNumber_ < startNumber_)
    throw std::invalid_argument("STOP must be >= START");
  timeElapsed_ = static_cast<double> (std::clock());
  this->reset();

  // small primes have to be examined manually
  if (startNumber_ <= 5) {
    this->doSmallPrime(2,  2, 0, "2");
    this->doSmallPrime(3,  3, 0, "3");
    this->doSmallPrime(5,  5, 0, "5");
    this->doSmallPrime(3,  5, 1, "(3, 5)");
    this->doSmallPrime(5,  7, 1, "(5, 7)");
    this->doSmallPrime(5, 11, 2, "(5, 7, 11)");
    this->doSmallPrime(5, 13, 3, "(5, 7, 11, 13)");
    this->doSmallPrime(5, 17, 4, "(5, 7, 11, 13, 17)");
  }

  if (stopNumber_ >= 7) {
    // needed by primeNumberGenerator and primeNumberFinder to
    // reset their sieve arrays
    ResetSieve resetSieve(this);
    // used to sieve the prime numbers and prime k-tuplets between
    // startNumber_ and stopNumber_
    PrimeNumberFinder primeNumberFinder(this, &resetSieve);

    if (isqrt(stopNumber_) > resetSieve.getLimit()) {
      // used to generate the prime numbers up to sqrt(stopNumber_)
      // needed for sieving by primeNumberFinder
      PrimeNumberGenerator primeNumberGenerator(&primeNumberFinder);
      std::vector<uint32_t> primes16Bit;
      primes16Bit.push_back(3);
      uint32_t stop = isqrt(primeNumberGenerator.getStopNumber());
      uint32_t keep = isqrt(stop);
      // the following trial division algorithm is used to generate the
      // prime numbers up to stopNumber_^0.25 needed for sieving by
      // primeNumberGenerator. Although the algorithm is never
      // used > 65536 it finds the prime numbers up to 10^7 in 1 second
      // on an Intel Core i5-670 3.46GHz
      for (uint32_t n = 5; n <= stop; n += 2) {
        uint32_t s = isqrt(n);
        uint32_t i = 0;
        for (; primes16Bit[i] <= s && (n % primes16Bit[i]) != 0; i++)
          ;
        if (primes16Bit[i] > s) {
          if (primes16Bit[i] <= keep)
            primes16Bit.push_back(n);
          if (n > resetSieve.getLimit())
            // generate the prime numbers up to n^2 and call
            // primeNumberFinder.sieve(p) for each generated prime
            primeNumberGenerator.sieve(n);
        }
      }
      primeNumberGenerator.finish();
    }
    primeNumberFinder.finish();
  }

  // set status_ to 100.0 (percent)
  parent_->doStatus(10);
  timeElapsed_ = (static_cast<double> (std::clock()) - timeElapsed_) /
      static_cast<double> (CLOCKS_PER_SEC);
}
<|endoftext|>


<commit_before>/**
 *       \file  py_calc_model.cpp
 *      \brief  Python wrappers for calc_model, calc_model_data
 *     \author  Sergey Miryanov
 *       \date  02.12.2009
 *  \copyright  This source code is released under the terms of
 *              the BSD License. See LICENSE for more details.
 * */
#include "boost_array_adapter.h"
#include "stdafx.h"

#include "calc_model.h"
#include "py_calc_model.h"

#include BS_FORCE_PLUGIN_IMPORT ()
#include "py_scal_wrapper.h"
#include "py_data_class.h"
#include BS_STOP_PLUGIN_IMPORT ()

// WTF??
#include "well_results_storage.h"
#include "fip_results_storage.h"

#include "export_python_wrapper.h"

using namespace boost::python;

namespace blue_sky
  {
  namespace python
    {

    template <typename T> int get_n_phases  (T *t) { return t->n_phases; }
    template <typename T> bool get_is_water (T *t) { return t->is_water (); }
    template <typename T> bool get_is_gas   (T *t) { return t->is_gas (); }
    template <typename T> bool get_is_oil   (T *t) { return t->is_oil (); }

    template <typename T>
    smart_ptr <named_pbase, true>
    get_params (T *t)
    {
      return t->ts_params;
    }

    PY_EXPORTER (calc_model_exporter, default_exporter)
      .add_property ("n_phases",    get_n_phases <T>)
      .add_property ("is_water",    get_is_water <T>)
      .add_property ("is_gas",      get_is_gas <T>)
      .add_property ("is_oil",      get_is_oil <T>)
      .add_property ("params",      get_params <T>)
      .add_property ("data",        &T::data)
      .add_property ("saturation",  &T::saturation_3p)
      .add_property ("pressure",    &T::pressure)
      .add_property ("pvt_num",     &T::n_pvt_regions)
      .add_property ("sat_num",     &T::n_sat_regions)
      .add_property ("fip_num",     &T::n_fip_regions)
      .add_property ("scal",        &T::scal_prop)
      .add_property ("pvt_regions", &T::pvt_regions)
      .add_property ("sat_regions", &T::sat_regions)
      .add_property ("fip_regions", &T::fip_regions)
      .add_property ("rock_regions",&T::rock_regions)
      .add_property ("pvt_water",   &T::pvt_water_array)
      .add_property ("pvt_gas",     &T::pvt_gas_array)
      .add_property ("pvt_oil",     &T::pvt_oil_array)
    PY_EXPORTER_END;

    PY_EXPORTER (calc_model_data_exporter, empty_exporter)
      .add_property ("cap_pressure",              detail::boost_array_adapter (&T::cap_pressure))
      .add_property ("s_deriv_cap_pressure",      detail::boost_array_adapter (&T::s_deriv_cap_pressure))
      .add_property ("relative_perm",             detail::boost_array_adapter (&T::relative_perm))
      .add_property ("s_deriv_relative_perm",     detail::boost_array_adapter (&T::s_deriv_relative_perm))
      .add_property ("p_deriv_gas_oil_ratio",     &T::p_deriv_gas_oil_ratio)
      .add_property ("invers_fvf",                detail::boost_array_adapter (&T::invers_fvf))
      .add_property ("p_deriv_invers_fvf",        detail::boost_array_adapter (&T::p_deriv_invers_fvf))
      .add_property ("gor_deriv_invers_fvf",      &T::gor_deriv_invers_fvf)
      .add_property ("invers_visc",               detail::boost_array_adapter (&T::invers_viscosity))
      .add_property ("p_deriv_invers_visc",       detail::boost_array_adapter (&T::p_deriv_invers_viscosity))
      .add_property ("gor_deriv_invers_visc",     &T::gor_deriv_invers_viscosity)
      .add_property ("invers_visc_fvf",           detail::boost_array_adapter (&T::invers_visc_fvf))
      .add_property ("p_deriv_invers_visc_fvf",   detail::boost_array_adapter (&T::p_deriv_invers_visc_fvf))
      .add_property ("gor_deriv_invers_visc_fvf", &T::gor_deriv_invers_visc_fvf)
      .add_property ("density",                   detail::boost_array_adapter (&T::density))
      .add_property ("p_deriv_density",           detail::boost_array_adapter (&T::p_deriv_density))
      .add_property ("gor_deriv_density",         &T::gor_deriv_density)
      .add_property ("porosity",                  &T::porosity)
      .add_property ("p_deriv_porosity",          &T::p_deriv_porosity)
      .add_property ("truns_mult",                &T::truns_mult)
      .add_property ("p_deriv_truns_mult",        &T::p_deriv_truns_mult)
      .add_property ("mobility",                  detail::boost_array_adapter (&T::mobility))
      .add_property ("p_deriv_mobility",          detail::boost_array_adapter (&T::p_deriv_mobility))
      .add_property ("s_deriv_mobility",          detail::boost_array_adapter (&T::s_deriv_mobility))
      .add_property ("prev_fluid_volume",         detail::boost_array_adapter (&T::prev_fluid_volume))
    PY_EXPORTER_END;

    template <typename T>
    void
    export_calc_model_data_vector (const char *name)
    {
      class_ <T> (name)
        .def (vector_indexing_suite <T> ())
        ;
    }

    void py_export_calc_model()
    {
      strategy_exporter::export_base_ext <calc_model_data, calc_model_data_exporter, class_type::concrete_class> ("calc_model_data");

      export_calc_model_data_vector <shared_vector <calc_model_data <base_strategy_di> > >   ("calc_model_data_vector_di");
      export_calc_model_data_vector <shared_vector <calc_model_data <base_strategy_fi> > >   ("calc_model_data_vector_fi");
      export_calc_model_data_vector <shared_vector <calc_model_data <base_strategy_mixi> > > ("calc_model_data_vector_mixi");

      strategy_exporter::export_base <calc_model, calc_model_exporter> ("calc_model");
    }

  } //ns python
} //ns bs

<commit_msg>Edit: Fix export of scal_prop member<commit_after>/**
 *       \file  py_calc_model.cpp
 *      \brief  Python wrappers for calc_model, calc_model_data
 *     \author  Sergey Miryanov
 *       \date  02.12.2009
 *  \copyright  This source code is released under the terms of
 *              the BSD License. See LICENSE for more details.
 * */
#include "boost_array_adapter.h"
#include "stdafx.h"

#include "calc_model.h"
#include "py_calc_model.h"

#include BS_FORCE_PLUGIN_IMPORT ()
#include "py_scal_wrapper.h"
#include "py_data_class.h"
#include BS_STOP_PLUGIN_IMPORT ()

// WTF??
#include "well_results_storage.h"
#include "fip_results_storage.h"

#include "export_python_wrapper.h"

using namespace boost::python;

namespace blue_sky
  {
  namespace python
    {

    template <typename T> int get_n_phases  (T *t) { return t->n_phases; }
    template <typename T> bool get_is_water (T *t) { return t->is_water (); }
    template <typename T> bool get_is_gas   (T *t) { return t->is_gas (); }
    template <typename T> bool get_is_oil   (T *t) { return t->is_oil (); }

    template <typename T>
    smart_ptr <named_pbase, true>
    get_params (T *t)
    {
      return t->ts_params;
    }

    template <typename T>
    smart_ptr <typename T::scal_3p_t, true>
    get_scal_3p (T *t)
    {
      return t->scal_prop;
    }

    PY_EXPORTER (calc_model_exporter, default_exporter)
      .add_property ("n_phases",    get_n_phases <T>)
      .add_property ("is_water",    get_is_water <T>)
      .add_property ("is_gas",      get_is_gas <T>)
      .add_property ("is_oil",      get_is_oil <T>)
      .add_property ("params",      get_params <T>)
      .add_property ("data",        &T::data)
      .add_property ("saturation",  &T::saturation_3p)
      .add_property ("pressure",    &T::pressure)
      .add_property ("pvt_num",     &T::n_pvt_regions)
      .add_property ("sat_num",     &T::n_sat_regions)
      .add_property ("fip_num",     &T::n_fip_regions)
      .add_property ("scal",        get_scal_3p <T>)
      .add_property ("pvt_regions", &T::pvt_regions)
      .add_property ("sat_regions", &T::sat_regions)
      .add_property ("fip_regions", &T::fip_regions)
      .add_property ("rock_regions",&T::rock_regions)
      .add_property ("pvt_water",   &T::pvt_water_array)
      .add_property ("pvt_gas",     &T::pvt_gas_array)
      .add_property ("pvt_oil",     &T::pvt_oil_array)
    PY_EXPORTER_END;

    PY_EXPORTER (calc_model_data_exporter, empty_exporter)
      .add_property ("cap_pressure",              detail::boost_array_adapter (&T::cap_pressure))
      .add_property ("s_deriv_cap_pressure",      detail::boost_array_adapter (&T::s_deriv_cap_pressure))
      .add_property ("relative_perm",             detail::boost_array_adapter (&T::relative_perm))
      .add_property ("s_deriv_relative_perm",     detail::boost_array_adapter (&T::s_deriv_relative_perm))
      .add_property ("p_deriv_gas_oil_ratio",     &T::p_deriv_gas_oil_ratio)
      .add_property ("invers_fvf",                detail::boost_array_adapter (&T::invers_fvf))
      .add_property ("p_deriv_invers_fvf",        detail::boost_array_adapter (&T::p_deriv_invers_fvf))
      .add_property ("gor_deriv_invers_fvf",      &T::gor_deriv_invers_fvf)
      .add_property ("invers_visc",               detail::boost_array_adapter (&T::invers_viscosity))
      .add_property ("p_deriv_invers_visc",       detail::boost_array_adapter (&T::p_deriv_invers_viscosity))
      .add_property ("gor_deriv_invers_visc",     &T::gor_deriv_invers_viscosity)
      .add_property ("invers_visc_fvf",           detail::boost_array_adapter (&T::invers_visc_fvf))
      .add_property ("p_deriv_invers_visc_fvf",   detail::boost_array_adapter (&T::p_deriv_invers_visc_fvf))
      .add_property ("gor_deriv_invers_visc_fvf", &T::gor_deriv_invers_visc_fvf)
      .add_property ("density",                   detail::boost_array_adapter (&T::density))
      .add_property ("p_deriv_density",           detail::boost_array_adapter (&T::p_deriv_density))
      .add_property ("gor_deriv_density",         &T::gor_deriv_density)
      .add_property ("porosity",                  &T::porosity)
      .add_property ("p_deriv_porosity",          &T::p_deriv_porosity)
      .add_property ("truns_mult",                &T::truns_mult)
      .add_property ("p_deriv_truns_mult",        &T::p_deriv_truns_mult)
      .add_property ("mobility",                  detail::boost_array_adapter (&T::mobility))
      .add_property ("p_deriv_mobility",          detail::boost_array_adapter (&T::p_deriv_mobility))
      .add_property ("s_deriv_mobility",          detail::boost_array_adapter (&T::s_deriv_mobility))
      .add_property ("prev_fluid_volume",         detail::boost_array_adapter (&T::prev_fluid_volume))
    PY_EXPORTER_END;

    template <typename T>
    void
    export_calc_model_data_vector (const char *name)
    {
      class_ <T> (name)
        .def (vector_indexing_suite <T> ())
        ;
    }

    void py_export_calc_model()
    {
      strategy_exporter::export_base_ext <calc_model_data, calc_model_data_exporter, class_type::concrete_class> ("calc_model_data");

      export_calc_model_data_vector <shared_vector <calc_model_data <base_strategy_di> > >   ("calc_model_data_vector_di");
      export_calc_model_data_vector <shared_vector <calc_model_data <base_strategy_fi> > >   ("calc_model_data_vector_fi");
      export_calc_model_data_vector <shared_vector <calc_model_data <base_strategy_mixi> > > ("calc_model_data_vector_mixi");

      strategy_exporter::export_base <calc_model, calc_model_exporter> ("calc_model");
    }

  } //ns python
} //ns bs

<|endoftext|>


<commit_before>#include <MetaAttribute.h>
#include <MetaFactory.h>
#include <AttributeType.h>
#include <IDIO.h>
#include <IO.h>

#include <memory>
#include <ostream>

using namespace std;

using std::move;

MetaAttribute::MetaAttribute(const AttributeType& at) {
	mValue = MetaFactory::instance().create(at.value());
	mUnit = at.unit();
	mScale = at.scale();
	mID = at.id();
}

MetaAttribute& MetaAttribute::operator+=(const MetaAttribute& b) {
	if(!(mUnit == b.mUnit)) {
		mValue = MetaValue();
		return *this;
	}
	if(!(mScale == b.mScale)) {
		MetaValue sumB = b.value();
		sumB*=(b.mScale / mScale);
		mValue = mValue + sumB;
	} else
		mValue = mValue + b.value();
	return *this;
}

MetaAttribute& MetaAttribute::operator*=(const MetaScale& scale){
  this->scale() *= scale;
  this->value() /= scale;
  return *this;
}
MetaAttribute MetaAttribute::operator*(const MetaScale& scale) const {
  MetaAttribute temp(*this);
  return temp*=scale;
}

bool MetaAttribute::operator==(const MetaAttribute& b) const {
	return id() == b.id() &&  (ValueType)value() == (ValueType)b.value() && unit() == b.unit() && scale() == b.scale();
}

MetaAttribute::operator AttributeType() const {
  return AttributeType(id(), ValueType(value()), scale(), unit());
}

ostream& operator<<(ostream& o, const MetaAttribute& ma) {
  return o << id::attribute::name(ma.id()) << ": " << ma.value() << " " << ma.scale() << " " << ma.unit();
}
<commit_msg>MetaAttribute: fixed wrong comparision<commit_after>#include <MetaAttribute.h>
#include <MetaFactory.h>
#include <AttributeType.h>
#include <IDIO.h>
#include <IO.h>

#include <memory>
#include <ostream>

using namespace std;

using std::move;

MetaAttribute::MetaAttribute(const AttributeType& at) {
	mValue = MetaFactory::instance().create(at.value());
	mUnit = at.unit();
	mScale = at.scale();
	mID = at.id();
}

MetaAttribute& MetaAttribute::operator+=(const MetaAttribute& b) {
	if(!(mUnit == b.mUnit)) {
		mValue = MetaValue();
		return *this;
	}
	if(!(mScale == b.mScale)) {
		MetaValue sumB = b.value();
		sumB*=(b.mScale / mScale);
		mValue = mValue + sumB;
	} else
		mValue = mValue + b.value();
	return *this;
}

MetaAttribute& MetaAttribute::operator*=(const MetaScale& scale){
  this->scale() *= scale;
  this->value() /= scale;
  return *this;
}

MetaAttribute MetaAttribute::operator*(const MetaScale& scale) const {
  MetaAttribute temp(*this);
  return temp*=scale;
}

bool MetaAttribute::operator==(const MetaAttribute& b) const {
	return id() == b.id() &&  value() == b.value() && unit() == b.unit() && scale() == b.scale();
}

MetaAttribute::operator AttributeType() const {
  return AttributeType(id(), ValueType(value()), scale(), unit());
}

ostream& operator<<(ostream& o, const MetaAttribute& ma) {
  return o << id::attribute::name(ma.id()) << ": " << ma.value() << " " << ma.scale() << " " << ma.unit();
}
<|endoftext|>


<commit_before>/**
 * @file dpdk.cpp
 * @author Han Wang
 * @brief Connectal API for Intel DPDK
 */
#include <sys/mman.h>
#include <assert.h>

#include "dmaManager.h"
#include "MMURequest.h"
#include "MMUIndication.h"
#include "MemServerRequest.h"
#include "MemServerIndication.h"
#include "GeneratedTypes.h" //ChannelType!!

#include "SonicUserRequest.h"
#include "SonicUserIndication.h"

#define PLATFORM_TILE 0
#define PAGE_SHIFT0 12
#define PAGE_SHIFT4 16
#define PAGE_SHIFT8 20
#define PAGE_SHIFT12 24
#define LENGTH (1024UL * 1024 * 1024)
static int shifts[] = {PAGE_SHIFT12, PAGE_SHIFT8, PAGE_SHIFT4, PAGE_SHIFT0, 0};
static int trace_memory = 1;

static sem_t test_sem;
static int mismatchCount = 0;
class SonicUserIndication : public SonicUserIndicationWrapper
{
	public:
		virtual void sonic_read_version_resp(uint32_t a) {
			fprintf(stderr, "read version %d\n", a);
		}
		virtual void readDone(uint32_t a) {
			fprintf(stderr, "SonicUser::readDone(%x)\n", a);
			mismatchCount += a;
			sem_post(&test_sem);
		}
		void started(uint32_t words) {
			fprintf(stderr, "Memwrite::started: words=%x\n", words);
		}
		void writeDone ( uint32_t srcGen ) {
			fprintf(stderr, "Memwrite::writeDone (%08x)\n", srcGen);
			sem_post(&test_sem);
		}
		void reportStateDbg(uint32_t streamWrCnt, uint32_t srcGen) {
			fprintf(stderr, "Memwrite::reportStateDbg: streamWrCnt=%08x srcGen=%d\n", streamWrCnt, srcGen);
		}
		SonicUserIndication(unsigned int id) : SonicUserIndicationWrapper(id){}
		SonicUserIndication(unsigned int id, PortalPoller *poller) : SonicUserIndicationWrapper(id, poller){}
};

static int mmu_error_limit = 20;
static int mem_error_limit = 20;
class MMUIndication : public MMUIndicationWrapper
{
    DmaManager *portalMemory;
    public:
    MMUIndication(DmaManager *pm, unsigned int  id, struct PortalPoller *poller) : MMUIndicationWrapper(id, poller), portalMemory(pm) {}
    virtual void configResp(uint32_t pointer){
        fprintf(stderr, "MMUIndication::configResp: %x\n", pointer);
        portalMemory->confResp(pointer);
    }
    virtual void error (uint32_t code, uint32_t pointer, uint64_t offset, uint64_t extra) {
        fprintf(stderr, "MMUIndication::error(code=0x%x, pointer=0x%x, offset=0x%"PRIx64" extra=-0x%"PRIx64"\n", code, pointer, offset, extra);
        if (--mmu_error_limit < 0)
            exit(-1);
    }
    virtual void idResponse(uint32_t sglId){
        portalMemory->sglIdResp(sglId);
    }
};

class MemServerIndication : public MemServerIndicationWrapper
{
    MemServerRequestProxy *memServerRequestProxy;
    sem_t mtSem;
    uint64_t mtCnt;
    void init(){
        if (sem_init(&mtSem, 0, 0))
            PORTAL_PRINTF("MemServerIndication::init failed to init mtSem\n");
    }
    public:
    MemServerIndication(MemServerRequestProxy *p, unsigned int  id, struct PortalPoller *poller) : MemServerIndicationWrapper(id,poller), memServerRequestProxy(p) {init();}
    virtual void addrResponse(uint64_t physAddr){
        fprintf(stderr, "DmaIndication::addrResponse(physAddr=%"PRIx64")\n", physAddr);
    }
    virtual void reportStateDbg(const DmaDbgRec rec){
        fprintf(stderr, "MemServerIndication::reportStateDbg: {x:%08x y:%08x z:%08x w:%08x}\n", rec.x,rec.y,rec.z,rec.w);
    }
    virtual void reportMemoryTraffic(uint64_t words){
        //fprintf(stderr, "reportMemoryTraffic: words=%"PRIx64"\n", words);
        mtCnt = words;
        sem_post(&mtSem);
    }
    virtual void error (uint32_t code, uint32_t pointer, uint64_t offset, uint64_t extra) {
        fprintf(stderr, "MemServerIndication::error(code=%x, pointer=%x, offset=%"PRIx64" extra=%"PRIx64"\n", code, pointer, offset, extra);
        if (--mem_error_limit < 0)
            exit(-1);
    }
    uint64_t receiveMemoryTraffic(){
        sem_wait(&mtSem);
        return mtCnt;
    }
    uint64_t getMemoryTraffic(const ChannelType rc){
        assert(memServerRequestProxy);
        memServerRequestProxy->memoryTraffic(rc);
        return receiveMemoryTraffic();
    }
};

static DmaManager *dma = 0;
static SonicUserRequestProxy *device = 0;
static SonicUserIndication *indication = 0;
static MemServerRequestProxy *hostMemServerRequest;
static MemServerIndication *hostMemServerIndication;
static MMUIndication *mmuIndication;
DmaManager *sonicPlatformInit(struct PortalPoller *poller)
{
    fprintf(stderr, "[%s:%d]\n", __func__, __LINE__);
    hostMemServerRequest = new MemServerRequestProxy(IfcNames_MemServerRequestS2H, PLATFORM_TILE);
    fprintf(stderr, "[%s:%d]\n", __func__, __LINE__);
    MMURequestProxy *dmap = new MMURequestProxy(IfcNames_MMURequestS2H, PLATFORM_TILE);
    fprintf(stderr, "[%s:%d]\n", __func__, __LINE__);
    DmaManager *dma = new DmaManager(dmap);
    fprintf(stderr, "[%s:%d]\n", __func__, __LINE__);
    hostMemServerIndication = new MemServerIndication(hostMemServerRequest, IfcNames_MemServerIndicationH2S,  poller);
    fprintf(stderr, "[%s:%d]\n", __func__, __LINE__);
    mmuIndication = new MMUIndication(dma, IfcNames_MMUIndicationH2S, poller);

    return dma;
}
/**
 * @brief
 */
int snd_fd_to_portal(PortalInternal *device, int fd, int id, size_t sz)
{
    int rc = 0;
    int i, j;
    uint32_t regions[4] = {0, 0,0,0};
    uint64_t border = 0;
    unsigned char entryCount = 0;
    uint64_t borderVal[4];
    uint32_t indexVal[4];
    unsigned char idxOffset;
    int size_accum = 0;
    rc = id;
    long len = 1 << PAGE_SHIFT12; // 16MB pages
    unsigned entries = sz >> PAGE_SHIFT12;

    PORTAL_PRINTF("%s: nb_entries %d\n", __FUNCTION__, entries);
    for(i = 0; 1; i++){
        long addr;
        if (!entries)
            break;
        if (!len)
            break;
        addr = size_accum;
        size_accum += len;
        addr |= ((long)id) << 32; //[39:32] = truncate(pref);

        for(j = 0; j < 4; j++)
            if (len == 1<<shifts[j]) {
                regions[j]++;
                if (addr & ((1L<<shifts[j]) - 1))
                    PORTAL_PRINTF("%s: addr %lx shift %x *********\n", __FUNCTION__, addr, shifts[j]);
                addr >>= shifts[j];
                break;
            }
        if (j >= 4)
            PORTAL_PRINTF("DmaManager:unsupported sglist size %lx\n", len);
        if (trace_memory)
            PORTAL_PRINTF("DmaManager:sglist(id=%08x, i=%d dma_addr=%08lx, len=%08lx)\n", id, i, (long)addr, len);
        MMURequest_sglist(device, id, i, addr, len);
        entries--;
    } // balance }

    // HW interprets zeros as end of sglist
    if (trace_memory)
        PORTAL_PRINTF("DmaManager:sglist(id=%08x, i=%d end of list)\n", id, i);
    MMURequest_sglist(device, id, i, 0, 0); // end list

    for(i = 0; i < 4; i++){
        idxOffset = entryCount - border;
        entryCount += regions[i];
        border += regions[i];
        borderVal[i] = border;
        indexVal[i] = idxOffset;
        border <<= (shifts[i] - shifts[i+1]);
    }

    if (trace_memory) {
        PORTAL_PRINTF("regions %d (%x %x %x %x)\n", id,regions[0], regions[1], regions[2], regions[3]);
        PORTAL_PRINTF("borders %d (%"PRIx64" %"PRIx64" %"PRIx64" %"PRIx64")\n", id,borderVal[0], borderVal[1], borderVal[2], borderVal[3], indexVal[3]);
    }
    MMURequest_region(device, id, borderVal[0], indexVal[0], borderVal[1], indexVal[1], borderVal[2], indexVal[2], borderVal[3], indexVal[3]);
    PORTAL_PRINTF("[%s:%d]\n", __FUNCTION__, __LINE__);
    /* ifdefs here to supress warning during kernel build */
    return rc;
}

/**
 * @brief dma reference
 */
int dma_reference (DmaManagerPrivate* priv, int fd, size_t sz) {
    int id = 0;
    int rc = 0;
    PORTAL_PRINTF("[%s:%d] fd=%d\n", __FUNCTION__, __LINE__, fd);
    MMURequest_idRequest(priv->sglDevice, (SpecialTypeForSendingFd)fd);
    printf("[%s:%d] polling function %p\n", __FUNCTION__, __LINE__, priv->poll);
    if (priv->poll) {
        int rc = priv->poll(priv->shared_mmu_indication, &priv->sglId);
        printf("[%s:%d] return after idrequest %d %d\n", __FUNCTION__, __LINE__, rc, priv->sglId);
    }
    else {
        PORTAL_PRINTF("[%s:%d] sem_wait on first id request\n", __FUNCTION__, __LINE__);
        sem_wait(&priv->sglIdSem);
    }
    id = priv->sglId;
    PORTAL_PRINTF("[%s:%d] id=%d, fd=%d\n", __FUNCTION__, __LINE__, id, fd);
    rc = snd_fd_to_portal(priv->sglDevice, fd, id, sz);
    if (rc <= 0) {
        PORTAL_PRINTF("%s:%d sem_wait\n", __FUNCTION__, __LINE__);
        if (priv->poll) {
            uint32_t ret;
            int rc = priv->poll(priv->shared_mmu_indication, &ret);
            printf("[%s:%d] return after sendfd %d %d\n", __FUNCTION__, __LINE__, rc, ret);
        }
        else
            sem_wait(&priv->confSem);
    }
    return rc;
}

extern "C" {

/**
 * @brief create handle to access connectal device
 *
 * This function instantiates a DMA Manager* to access Connectal DMA engine. It
 * returns
 *
 */
PortalPoller *sonicPoller = new PortalPoller();

void dma_init (uint32_t fd) {
    if (!dma) {
        PORTAL_PRINTF("[%s:%d] platformInit\n", __FUNCTION__, __LINE__);
        dma = sonicPlatformInit(sonicPoller);
        PORTAL_PRINTF("[%s:%d] platformInit finished\n", __FUNCTION__, __LINE__);
        device = new SonicUserRequestProxy(IfcNames_SonicUserRequestS2H);
        //SonicUserIndication memReadIndication(IfcNames_SonicUserIndicationH2S);
        indication = new SonicUserIndication(IfcNames_SonicUserIndicationH2S, sonicPoller);
        printf("[%s:%d]: dma %p device %p\n", __func__, __LINE__, dma, device);

        //write_shared_data(fd, offset);
        DmaManagerPrivate *priv = &dma->priv;
        dma_reference(priv, fd, LENGTH);
        PORTAL_PRINTF("[%s:%d] dma_init finished\n", __FUNCTION__, __LINE__);
    }
}

/**
 * @brief Used by Tx to send PA(physical address) of a tx_buff to hardware
 */
void tx_send_pa(uint64_t base, uint32_t len) {
    printf("[%s:%d], do dma read.\n", __func__, __LINE__);
    // start read
}

/**
 * @brief Used by Rx to send PA(physical address) of a free rx_buff to hardware
 */
void rx_send_pa(uint64_t base, uint32_t len) {

}

/**
 * @brief sonic_read_version
 */
void read_version(void) {
    fprintf(stderr, "[%s:%d] read version.\n", __func__, __LINE__);
    assert(device != NULL);
    device->sonic_read_version();
}

} //extern "C"

/*
 * @brief main() unused
 */
int main(int argc, char **argv) { return 0; }
<commit_msg>refactored dpdk.cpp<commit_after>/**
 * @file dpdk.cpp
 * @author Han Wang
 * @brief Connectal API for Intel DPDK
 */
#include <sys/mman.h>
#include <assert.h>

#include "dmaManager.h"
#include "GeneratedTypes.h" //ChannelType!!
#include "SonicUserRequest.h"
#include "SonicUserIndication.h"

static int trace_memory = 1;
static sem_t test_sem;
static int mismatchCount = 0;

class SonicUserIndication : public SonicUserIndicationWrapper
{
	public:
		virtual void sonic_read_version_resp(uint32_t a) {
			fprintf(stderr, "read version %d\n", a);
		}
		virtual void readDone(uint32_t a) {
			fprintf(stderr, "SonicUser::readDone(%x)\n", a);
			mismatchCount += a;
			sem_post(&test_sem);
		}
		void started(uint32_t words) {
			fprintf(stderr, "Memwrite::started: words=%x\n", words);
		}
		void writeDone ( uint32_t srcGen ) {
			fprintf(stderr, "Memwrite::writeDone (%08x)\n", srcGen);
			sem_post(&test_sem);
		}
		void reportStateDbg(uint32_t streamWrCnt, uint32_t srcGen) {
			fprintf(stderr, "Memwrite::reportStateDbg: streamWrCnt=%08x srcGen=%d\n", streamWrCnt, srcGen);
		}
		SonicUserIndication(unsigned int id) : SonicUserIndicationWrapper(id){}
		SonicUserIndication(unsigned int id, PortalPoller *poller) : SonicUserIndicationWrapper(id, poller){}
};

#define PLATFORM_TILE 0
#define PAGE_SHIFT0 12
#define PAGE_SHIFT4 16
#define PAGE_SHIFT8 20
#define PAGE_SHIFT12 24
#define LENGTH (1024UL * 1024 * 1024)
static int shifts[] = {PAGE_SHIFT12, PAGE_SHIFT8, PAGE_SHIFT4, PAGE_SHIFT0, 0};

class SonicDpdkManager {
    DmaManager *dma;
    SonicUserRequestProxy *device;
    SonicUserIndication *indication;
    int mmu_sglId;
    public:
        SonicDpdkManager() : dma(0), device(0), indication(0), mmu_sglId(0) {}

        void init(int fd) {
            if (!dma) {
                dma = platformInit();
                device = new SonicUserRequestProxy(IfcNames_SonicUserRequestS2H);
                indication = new SonicUserIndication(IfcNames_SonicUserIndicationH2S);
                DmaManagerPrivate *priv = &dma->priv;
                mmu_sglId = dma_reference(priv, fd, LENGTH);
                PORTAL_PRINTF("[%s:%d] mmu sglId=%d\n", __FUNCTION__, __LINE__, mmu_sglId);
            }
        }
        void read_version() {
            assert(device != NULL);
            device->sonic_read_version();
        }
        void tx_send_pa(uint64_t base, uint32_t len) {
            device->sonicXmitFrame(mmu_sglId, base, len*4, 32*4); //DMA Burst Len is 128 bytes
        }
        void rx_send_pa(uint64_t base, uint32_t len) {
        }

    private:
        int dma_reference (DmaManagerPrivate* priv, int fd, size_t sz) {
            int id = 0;
            int rc = 0;
            MMURequest_idRequest(priv->sglDevice, (SpecialTypeForSendingFd)fd);
            sem_wait(&priv->sglIdSem);
            id = priv->sglId;
            rc = send_fd_to_portal(priv->sglDevice, fd, id, sz);
            if (rc <= 0) {
                sem_wait(&priv->confSem);
            }
            PORTAL_PRINTF("[%s:%d] rc=%d\n", __FUNCTION__, __LINE__, rc);
            return rc;
        }
        int send_fd_to_portal(PortalInternal *device, int fd, int id, size_t sz)
        {
            int rc = 0;
            int i, j;
            uint32_t regions[4] = {0,0,0,0};
            uint64_t border = 0;
            unsigned char entryCount = 0;
            uint64_t borderVal[4];
            uint32_t indexVal[4];
            unsigned char idxOffset;
            int size_accum = 0;
            rc = id;
            long len = 1 << PAGE_SHIFT12; // 16MB pages
            unsigned entries = sz >> PAGE_SHIFT12;

            for(i = 0; 1; i++){
                long addr;
                if (!entries)
                    break;
                if (!len)
                    break;
                addr = size_accum;
                size_accum += len;
                addr |= ((long)id) << 32; //[39:32] = truncate(pref);

                for(j = 0; j < 4; j++)
                    if (len == 1<<shifts[j]) {
                        regions[j]++;
                        if (addr & ((1L<<shifts[j]) - 1))
                            PORTAL_PRINTF("%s: addr %lx shift %x *********\n", __FUNCTION__, addr, shifts[j]);
                        addr >>= shifts[j];
                        break;
                    }
                if (j >= 4)
                    PORTAL_PRINTF("DmaManager:unsupported sglist size %lx\n", len);
                if (trace_memory)
                    PORTAL_PRINTF("DmaManager:sglist(id=%08x, i=%d dma_addr=%08lx, len=%08lx)\n", id, i, (long)addr, len);
                MMURequest_sglist(device, id, i, addr, len);
                entries--;
            } // balance }

            if (trace_memory)
                PORTAL_PRINTF("DmaManager:sglist(id=%08x, i=%d end of list)\n", id, i);
            MMURequest_sglist(device, id, i, 0, 0); // end list

            for(i = 0; i < 4; i++){
                idxOffset = entryCount - border;
                entryCount += regions[i];
                border += regions[i];
                borderVal[i] = border;
                indexVal[i] = idxOffset;
                border <<= (shifts[i] - shifts[i+1]);
            }

            if (trace_memory) {
                PORTAL_PRINTF("regions %d (%x %x %x %x)\n", id, regions[0], regions[1], regions[2], regions[3]);
                PORTAL_PRINTF("borders %d (%"PRIx64" %"PRIx64" %"PRIx64" %"PRIx64")\n", id, borderVal[0], borderVal[1], borderVal[2], borderVal[3]);
            }
            MMURequest_region(device, id, borderVal[0], indexVal[0], borderVal[1], indexVal[1], borderVal[2], indexVal[2], borderVal[3], indexVal[3]);
            /* ifdefs here to supress warning during kernel build */
            return rc;
        } // send_fd_to_portal
};

extern "C" {

SonicDpdkManager dpdk;

void dma_init (uint32_t fd) {
    printf("[%s:%d], dma init.\n", __func__, __LINE__);
    dpdk.init(fd);
}

void start_default_poller() {
    defaultPoller->start();
}

void stop_default_poller() {
    defaultPoller->stop();
}

void poll(void) {
    defaultPoller->event();
}

void tx_send_pa(uint64_t base, uint32_t len) {
    printf("[%s:%d], do dma read.\n", __func__, __LINE__);
    dpdk.tx_send_pa(0, len);
    sem_wait(&test_sem);
}

void rx_send_pa(uint32_t id, uint64_t base, uint32_t len) {
    printf("[%s:%d], do dma write.\n", __func__, __LINE__);
    dpdk.rx_send_pa(0, len);
}

void read_version(void) {
    fprintf(stderr, "[%s:%d] read version.\n", __func__, __LINE__);
    dpdk.read_version();
}

} //extern "C"

/*
 * @brief main() unused
 */
int main(int argc, char **argv) { return 0; }
<|endoftext|>


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

#include "katesessionapplet.h"
#include <QStyleOptionGraphicsItem>
#include <QTreeView>
#include <QVBoxLayout>
#include <QGraphicsGridLayout>
#include <KStandardDirs>
#include <KIconLoader>
#include <KInputDialog>
#include <KMessageBox>
#include <KStandardGuiItem>
#include <plasma/widgets/icon.h>
#include <QGraphicsProxyWidget>
#include <QListWidgetItem>
#include <QStandardItemModel>
#include <KIcon>
#include <KToolInvocation>
#include <KDirWatch>
#include <QGraphicsLinearLayout>
#include <KGlobalSettings>

KateSessionApplet::KateSessionApplet(QObject *parent, const QVariantList &args)
    : Plasma::PopupApplet(parent, args), m_listView( 0 )
{
    KDirWatch *dirwatch = new KDirWatch( this );
    QStringList lst = KGlobal::dirs()->findDirs( "data", "kate/sessions/" );
    for ( int i = 0; i < lst.count(); i++ )
    {
        dirwatch->addDir( lst[i] );
    }
    connect( dirwatch, SIGNAL(dirty (const QString &) ), this, SLOT( slotUpdateSessionMenu() ) );
    setIcon( "kate" );
}

KateSessionApplet::~KateSessionApplet()
{
    delete m_listView;
}

QWidget *KateSessionApplet::widget()
{
    if ( !m_listView )
    {
        m_listView= new QTreeView();
        m_listView->setEditTriggers( QAbstractItemView::NoEditTriggers );
        m_listView->setRootIsDecorated(false);
        m_listView->setHeaderHidden(true);
        m_listView->setMouseTracking(true);

        m_kateModel = new QStandardItemModel(this);
        m_listView->setModel(m_kateModel);
        m_listView->setMouseTracking(true);

        initSessionFiles();

        if (KGlobalSettings::singleClick()) {
            connect(m_listView, SIGNAL(clicked(const QModelIndex &)),
                    this, SLOT(slotOnItemClicked(const QModelIndex &)));
        } else {
            connect(m_listView, SIGNAL(doubleClicked(const QModelIndex &)),
                    this, SLOT(slotOnItemClicked(const QModelIndex &)));
        }
    }
    return m_listView;
}

void KateSessionApplet::slotUpdateSessionMenu()
{
    m_kateModel->clear();
    initSessionFiles();
}

void KateSessionApplet::initSessionFiles()
{
    int index = 0;

    QStandardItem *item = new QStandardItem();
    item->setData(i18n("Start Kate (no arguments)"), Qt::DisplayRole);
    item->setData( KIcon( "kate" ), Qt::DecorationRole );
    item->setData( index++, Index );
    m_kateModel->appendRow(item);

    item = new QStandardItem();
    item->setData( i18n("New Kate Session"), Qt::DisplayRole);
    item->setData( KIcon( "document-new" ), Qt::DecorationRole );
    item->setData( index++, Index );
    m_kateModel->appendRow(item);

    item = new QStandardItem();
    item->setData( i18n("New Anonymous Session"), Qt::DisplayRole);
    item->setData( index++, Index );
    item->setData( KIcon( "document-new" ), Qt::DecorationRole );
    m_kateModel->appendRow(item);

    QStringList list = KGlobal::dirs()->findAllResources( "data", "kate/sessions/*.katesession", KStandardDirs::NoDuplicates );
    for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
    {
        KConfig _config( *it, KConfig::SimpleConfig );
        KConfigGroup config(&_config, "General" );
        QString name =  config.readEntry( "Name" );
        m_sessions.append( name );
        item = new QStandardItem();
        item->setData(name, Qt::DisplayRole);
        item->setData( index++, Index );
        m_kateModel->appendRow( item);
    }
}

void KateSessionApplet::slotOnItemClicked(const QModelIndex &index)
{
    hidePopup();
    int id = index.data(Index).toInt();
    QStringList args;
    if ( id > 0 )
        args << "--start";

    // If a new session is requested we try to ask for a name.
    if ( id == 1 )
    {
        bool ok = false;
        QString name = KInputDialog::getText( i18n("Session Name"),
                                              i18n("Please enter a name for the new session"),
                                              QString(),
                                              &ok );
        if ( ! ok )
            return;

        if ( name.isEmpty() && KMessageBox::questionYesNo( 0,
                                                           i18n("An unnamed session will not be saved automatically. "
                                                                "Do you want to create such a session?"),
                                                           i18n("Create anonymous session?"),
                                                           KStandardGuiItem::yes(), KStandardGuiItem::cancel(),
                                                           "kate_session_button_create_anonymous" ) == KMessageBox::No )
            return;

        if ( m_sessions.contains( name ) &&
             KMessageBox::warningYesNo( 0,
                                        i18n("You already have a session named %1. Do you want to open that session?", name ),
                                        i18n("Session exists") ) == KMessageBox::No )
            return;
        args << name;
    }

    else if ( id == 2 )
        args << "";

    else if ( id > 2 )
        args << m_sessions[ id-3 ];

    KToolInvocation::kdeinitExec("kate", args);
}

#include "katesessionapplet.moc"
<commit_msg>build<commit_after>/***************************************************************************
 *   Copyright (C) 2008 by Montel Laurent <montel@kde.org>                 *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA          *
 ***************************************************************************/

#include "katesessionapplet.h"
#include <QStyleOptionGraphicsItem>
#include <QTreeView>
#include <QVBoxLayout>
#include <QGraphicsGridLayout>
#include <KStandardDirs>
#include <KIconLoader>
#include <KInputDialog>
#include <KMessageBox>
#include <KStandardGuiItem>
#include <plasma/widgets/icon.h>
#include <QGraphicsProxyWidget>
#include <QListWidgetItem>
#include <QStandardItemModel>
#include <KIcon>
#include <KToolInvocation>
#include <KDirWatch>
#include <QGraphicsLinearLayout>
#include <KGlobalSettings>

KateSessionApplet::KateSessionApplet(QObject *parent, const QVariantList &args)
    : Plasma::PopupApplet(parent, args), m_listView( 0 )
{
    KDirWatch *dirwatch = new KDirWatch( this );
    QStringList lst = KGlobal::dirs()->findDirs( "data", "kate/sessions/" );
    for ( int i = 0; i < lst.count(); i++ )
    {
        dirwatch->addDir( lst[i] );
    }
    connect( dirwatch, SIGNAL(dirty (const QString &) ), this, SLOT( slotUpdateSessionMenu() ) );
    setPopupIcon( "kate" );
}

KateSessionApplet::~KateSessionApplet()
{
    delete m_listView;
}

QWidget *KateSessionApplet::widget()
{
    if ( !m_listView )
    {
        m_listView= new QTreeView();
        m_listView->setEditTriggers( QAbstractItemView::NoEditTriggers );
        m_listView->setRootIsDecorated(false);
        m_listView->setHeaderHidden(true);
        m_listView->setMouseTracking(true);

        m_kateModel = new QStandardItemModel(this);
        m_listView->setModel(m_kateModel);
        m_listView->setMouseTracking(true);

        initSessionFiles();

        if (KGlobalSettings::singleClick()) {
            connect(m_listView, SIGNAL(clicked(const QModelIndex &)),
                    this, SLOT(slotOnItemClicked(const QModelIndex &)));
        } else {
            connect(m_listView, SIGNAL(doubleClicked(const QModelIndex &)),
                    this, SLOT(slotOnItemClicked(const QModelIndex &)));
        }
    }
    return m_listView;
}

void KateSessionApplet::slotUpdateSessionMenu()
{
    m_kateModel->clear();
    initSessionFiles();
}

void KateSessionApplet::initSessionFiles()
{
    int index = 0;

    QStandardItem *item = new QStandardItem();
    item->setData(i18n("Start Kate (no arguments)"), Qt::DisplayRole);
    item->setData( KIcon( "kate" ), Qt::DecorationRole );
    item->setData( index++, Index );
    m_kateModel->appendRow(item);

    item = new QStandardItem();
    item->setData( i18n("New Kate Session"), Qt::DisplayRole);
    item->setData( KIcon( "document-new" ), Qt::DecorationRole );
    item->setData( index++, Index );
    m_kateModel->appendRow(item);

    item = new QStandardItem();
    item->setData( i18n("New Anonymous Session"), Qt::DisplayRole);
    item->setData( index++, Index );
    item->setData( KIcon( "document-new" ), Qt::DecorationRole );
    m_kateModel->appendRow(item);

    QStringList list = KGlobal::dirs()->findAllResources( "data", "kate/sessions/*.katesession", KStandardDirs::NoDuplicates );
    for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
    {
        KConfig _config( *it, KConfig::SimpleConfig );
        KConfigGroup config(&_config, "General" );
        QString name =  config.readEntry( "Name" );
        m_sessions.append( name );
        item = new QStandardItem();
        item->setData(name, Qt::DisplayRole);
        item->setData( index++, Index );
        m_kateModel->appendRow( item);
    }
}

void KateSessionApplet::slotOnItemClicked(const QModelIndex &index)
{
    hidePopup();
    int id = index.data(Index).toInt();
    QStringList args;
    if ( id > 0 )
        args << "--start";

    // If a new session is requested we try to ask for a name.
    if ( id == 1 )
    {
        bool ok = false;
        QString name = KInputDialog::getText( i18n("Session Name"),
                                              i18n("Please enter a name for the new session"),
                                              QString(),
                                              &ok );
        if ( ! ok )
            return;

        if ( name.isEmpty() && KMessageBox::questionYesNo( 0,
                                                           i18n("An unnamed session will not be saved automatically. "
                                                                "Do you want to create such a session?"),
                                                           i18n("Create anonymous session?"),
                                                           KStandardGuiItem::yes(), KStandardGuiItem::cancel(),
                                                           "kate_session_button_create_anonymous" ) == KMessageBox::No )
            return;

        if ( m_sessions.contains( name ) &&
             KMessageBox::warningYesNo( 0,
                                        i18n("You already have a session named %1. Do you want to open that session?", name ),
                                        i18n("Session exists") ) == KMessageBox::No )
            return;
        args << name;
    }

    else if ( id == 2 )
        args << "";

    else if ( id > 2 )
        args << m_sessions[ id-3 ];

    KToolInvocation::kdeinitExec("kate", args);
}

#include "katesessionapplet.moc"
<|endoftext|>


<commit_before>/**
 *  @file
 *  @author     2012 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
 *  @copyright  Simplified BSD
 *
 *  @cond
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the FreeBSD license as published by the FreeBSD
 *  project.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 *  You should have received a copy of the FreeBSD license along with this
 *  program. If not, see <http://www.opensource.org/licenses/bsd-license>.
 *  @endcond
 */

#include "umundo/protoc-rpc/ServiceGeneratorCPP.h"

#include <set>
#include <iostream>

#include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/compiler/cpp/cpp_file.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>

namespace umundo {

using namespace google::protobuf::compiler::cpp;

bool ServiceGeneratorCPP::Generate(const FileDescriptor* file,
                                   const string& parameter,
                                   GeneratorContext* generator_context,
                                   string* error) const {
	vector<pair<string, string> > options;
	ParseGeneratorParameter(parameter, &options);

	string dllexport_decl;
	for (size_t i = 0; i < options.size(); i++) {
		if (options[i].first == "dllexport_decl") {
			dllexport_decl = options[i].second;
		} else {
			*error = "Unknown generator option: " + options[i].first;
			return false;
		}
	}

	string basename = StripProto(file->name());
	string filenameID = FilenameIdentifier(file->name());

	// Generate header.
	{
		scoped_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(basename + ".rpc.pb.h"));
		io::Printer printer(output.get(), '$');

		// header prolog
		printer.Print(
		    "// Generated by the umundo protocol buffer compiler. DO NOT EDIT!\n"
		    "// source: $filename$\n\n"
		    "#ifndef __PROTOBUF_$filename_identifier$\n"
		    "#define __PROTOBUF_$filename_identifier$\n\n"
		    "#include <umundo/rpc.h>\n"
		    "#include \"$basename$.pb.h\" // generated by protoc\n"
		    "#include \"$basename$.rpc.pb.h\" // generated by protoc\n",

		    "basename", basename,
		    "filename", file->name(),
		    "filename_identifier", filenameID);

		if (file->dependency_count() > 0) {
			for (int i = 0; i < file->dependency_count(); i++) {
				const FileDescriptor* fileDesc = file->dependency(i);
				printer.Print("#include \"$dependency$.pb.h\" // generated by protoc\n", "dependency", StripProto(fileDesc->name()));
			}
		}

		printer.Print("\n\nnamespace umundo {\n\n");

		if (file->service_count() > 0) {
			for (int i = 0; i < file->service_count(); i++) {
				const ServiceDescriptor* svcDesc = file->service(i);
				writeServiceStubHeader(printer, svcDesc);
				printer.Print("\n");
				writeServiceHeader(printer, svcDesc);
				printer.Print("\n\n");
			}
		}

		// header epilog
		printer.Print(
		    "\n}\n"
		    "#endif\n");
	}

	// Generate cc file.
	{
		scoped_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(basename + ".rpc.pb.cc"));
		io::Printer printer(output.get(), '$');

		if (file->service_count() > 0) {
			// implementation prolog
			printer.Print(
			    "#include \"umundo/rpc/Service.h\"\n"
			    "#include \"umundo/rpc/ServiceManager.h\"\n"
			    "#include \"$basename$.rpc.pb.h\"\n\n"
			    "namespace umundo {\n\n",
			    "basename", basename
			);

			for (int i = 0; i < file->service_count(); i++) {
				const ServiceDescriptor* svcDesc = file->service(i);
				writeServiceImplConstructor(printer, svcDesc);
				printer.Print("\n");
				writeServiceImplDispatcher(printer, svcDesc);
				printer.Print("\n");
				writeServiceImplCleanUp(printer, svcDesc);
				printer.Print("\n");
				writeServiceStubImpl(printer, svcDesc);
				printer.Print("\n\n");
			}
		}

		if (file->service_count() > 0) {
			// implementation epilog
			printer.Print("\n}\n");
		}
	}

	return true;

}

void ServiceGeneratorCPP::writeServiceStubHeader(io::Printer& printer, const ServiceDescriptor* svcDesc) const {
	printer.Print(
	    "class $svcName$Stub : public ServiceStub {\n"
	    "public:\n"
	    "\t$svcName$Stub(ServiceDescription*);\n",
	    "svcName", svcDesc->name()
	);

	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {
			const MethodDescriptor* methodDesc = svcDesc->method(i);
			printer.Print("\t$outType$* $methodName$($inType$*);\n",
			              "inType", container(methodDesc->input_type())->name(),
			              "methodName", methodDesc->name(),
			              "outType", container(methodDesc->output_type())->name()
			             );
		}
	}
	printer.Print("};\n");
}

void ServiceGeneratorCPP::writeServiceHeader(io::Printer &printer, const ServiceDescriptor* svcDesc) const {
	printer.Print(
	    "class $svcName$Base : public Service {\n"
	    "public:\n"
	    "\t$svcName$Base();\n",
	    "svcName", svcDesc->name()
	);

	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {
			const MethodDescriptor* methodDesc = svcDesc->method(i);
			printer.Print("\tvirtual $outType$* $methodName$($inType$*) = 0;\n",
			              "inType", container(methodDesc->input_type())->name(),
			              "methodName", methodDesc->name(),
			              "outType", container(methodDesc->output_type())->name()
			             );
		}

		printer.Print(
		    "protected:\n"
		    "\tvoid callMethod(string&, void*, const string&, void*&, const string&);\n"
		    "\tvoid cleanUpObjects(string&, void*, void*);\n"
		);
	}
	printer.Print("};\n");
}

const Descriptor* ServiceGeneratorCPP::container(const Descriptor* desc) {
//	fprintf(stderr, "checking %s\n", desc->name().c_str());
	while(desc->containing_type() != NULL) {
		desc = desc->containing_type();
//		fprintf(stderr, "\t-> %s\n", desc->name().c_str());
	}
	return desc;
}

void ServiceGeneratorCPP::writeServiceImplConstructor(io::Printer& printer, const ServiceDescriptor* svcDesc) const {

	std::set<string> inTypes;
	std::set<string> outTypes;
	std::set<string>::iterator inTypeIter;
	std::set<string>::iterator outTypeIter;

	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {
			const MethodDescriptor* methodDesc = svcDesc->method(i);
			inTypes.insert(methodDesc->input_type()->name());
			outTypes.insert(methodDesc->output_type()->name());
		}
	}

	printer.Print(
	    "$className$Stub::$className$Stub(ServiceDescription* svcDesc) : ServiceStub(svcDesc)  {\n"
	    "\t_serviceName = \"$className$\";\n",
	    "className", svcDesc->name()
	);

	// register intypes at publisher for stub, outtypes at subscriber
	for (inTypeIter = inTypes.begin(); inTypeIter != inTypes.end(); inTypeIter++) {
		printer.Print(
		    "\t_rpcPub->registerType(\"$inType$\", new $inType$());\n",
		    "inType", (*inTypeIter)
		);
	}
	for (outTypeIter = outTypes.begin(); outTypeIter != outTypes.end(); outTypeIter++) {
		printer.Print(
		    "\t_rpcSub->registerType(\"$outType$\", new $outType$());\n",
		    "outType", (*outTypeIter)
		);
	}

	printer.Print("}\n\n");

	printer.Print(
	    "$className$Base::$className$Base() {\n"
	    "\t_serviceName = \"$className$\";\n",
	    "className", svcDesc->name()
	);

	// register intypes at sublisher for impl, outtypes at publisher
	for (inTypeIter = inTypes.begin(); inTypeIter != inTypes.end(); inTypeIter++) {
		printer.Print(
		    "\t_rpcSub->registerType(\"$inType$\", new $inType$());\n",
		    "inType", (*inTypeIter)
		);
	}
	for (outTypeIter = outTypes.begin(); outTypeIter != outTypes.end(); outTypeIter++) {
		printer.Print(
		    "\t_rpcPub->registerType(\"$outType$\", new $outType$());\n",
		    "outType", (*outTypeIter)
		);
	}

	printer.Print("}\n");

}

void ServiceGeneratorCPP::writeServiceImplDispatcher(io::Printer& printer, const ServiceDescriptor* svcDesc) const {

	printer.Print(
	    "void $className$Base::callMethod(string& methodName, void* in, const string& inType, void* &out, const string& outType) {\n"
	    "\tif (false) {\n",
	    "className", svcDesc->name()
	);

	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {
			const MethodDescriptor* methodDesc = svcDesc->method(i);
			printer.Print(
			    "\t} else if (methodName.compare(\"$methodName$\") == 0) {\n"
			    "\t\tout = (void*)$methodName$(($inType$*)in);\n",
			    "inType", methodDesc->input_type()->name(),
			    "methodName", methodDesc->name()
			);
		}
	}
	printer.Print("\t}\n}\n");
}

void ServiceGeneratorCPP::writeServiceImplCleanUp(io::Printer& printer, const ServiceDescriptor* svcDesc) const {
	printer.Print(
	    "void $className$Base::cleanUpObjects(string& methodName, void* in, void* out) {\n"
	    "\tif (false) {\n",
	    "className", svcDesc->name()
	);

	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {
			const MethodDescriptor* methodDesc = svcDesc->method(i);
			printer.Print(
			    "\t} else if (methodName.compare(\"$methodName$\") == 0) {\n"
			    "\t\tif (in != NULL) delete(($inType$*)in);\n"
			    "\t\tif (out != NULL) delete(($outType$*)out);\n",
			    "inType", methodDesc->input_type()->name(),
			    "outType", methodDesc->output_type()->name(),
			    "methodName", methodDesc->name()
			);
		}
	}
	printer.Print("\t}\n}\n");
}

void ServiceGeneratorCPP::writeServiceStubImpl(io::Printer& printer, const ServiceDescriptor* svcDesc) const {
	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {

			const MethodDescriptor* methodDesc = svcDesc->method(i);
			printer.Print(
			    "$outType$* $className$Stub",
			    "className", svcDesc->name(),
			    "outType", methodDesc->output_type()->name());

			printer.Print(
			    "::$methodName$($inType$* in) {\n"
			    "\tvoid* out = NULL;\n"
			    "\tcallStubMethod(\"$methodName$\", in, \"$inType$\", out, \"$outType$\");\n"
			    "\treturn ($outType$*)out;\n"
			    "}\n",
			    "inType", methodDesc->input_type()->name(),
			    "methodName", methodDesc->name(),
			    "outType", methodDesc->output_type()->name()
			);
		}
	}
}

}

int main(int argc, char* argv[]) {
	umundo::ServiceGeneratorCPP generator;
	return google::protobuf::compiler::PluginMain(argc, argv, &generator);
}
<commit_msg>Support for light-weight reflection with services<commit_after>/**
 *  @file
 *  @author     2012 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
 *  @copyright  Simplified BSD
 *
 *  @cond
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the FreeBSD license as published by the FreeBSD
 *  project.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 *  You should have received a copy of the FreeBSD license along with this
 *  program. If not, see <http://www.opensource.org/licenses/bsd-license>.
 *  @endcond
 */

#include "umundo/protoc-rpc/ServiceGeneratorCPP.h"

#include <set>
#include <iostream>

#include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/compiler/cpp/cpp_file.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>

namespace umundo {

using namespace google::protobuf::compiler::cpp;

bool ServiceGeneratorCPP::Generate(const FileDescriptor* file,
                                   const string& parameter,
                                   GeneratorContext* generator_context,
                                   string* error) const {
	vector<pair<string, string> > options;
	ParseGeneratorParameter(parameter, &options);

	string dllexport_decl;
	for (size_t i = 0; i < options.size(); i++) {
		if (options[i].first == "dllexport_decl") {
			dllexport_decl = options[i].second;
		} else {
			*error = "Unknown generator option: " + options[i].first;
			return false;
		}
	}

	string basename = StripProto(file->name());
	string filenameID = FilenameIdentifier(file->name());

	// Generate header.
	{
		scoped_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(basename + ".rpc.pb.h"));
		io::Printer printer(output.get(), '$');

		// header prolog
		printer.Print(
		    "// Generated by the umundo protocol buffer compiler. DO NOT EDIT!\n"
		    "// source: $filename$\n\n"
		    "#ifndef __PROTOBUF_$filename_identifier$\n"
		    "#define __PROTOBUF_$filename_identifier$\n\n"
		    "#include <umundo/rpc.h>\n"
		    "#include \"$basename$.pb.h\" // generated by protoc\n"
		    "#include \"$basename$.rpc.pb.h\" // generated by protoc\n",

		    "basename", basename,
		    "filename", file->name(),
		    "filename_identifier", filenameID);

		if (file->dependency_count() > 0) {
			for (int i = 0; i < file->dependency_count(); i++) {
				const FileDescriptor* fileDesc = file->dependency(i);
				printer.Print("#include \"$dependency$.pb.h\" // generated by protoc\n", "dependency", StripProto(fileDesc->name()));
			}
		}

		printer.Print("\n\nnamespace umundo {\n\n");

		if (file->service_count() > 0) {
			for (int i = 0; i < file->service_count(); i++) {
				const ServiceDescriptor* svcDesc = file->service(i);
				writeServiceStubHeader(printer, svcDesc);
				printer.Print("\n");
				writeServiceHeader(printer, svcDesc);
				printer.Print("\n\n");
			}
		}

		// header epilog
		printer.Print(
		    "\n}\n"
		    "#endif\n");
	}

	// Generate cc file.
	{
		scoped_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(basename + ".rpc.pb.cc"));
		io::Printer printer(output.get(), '$');

		if (file->service_count() > 0) {
			// implementation prolog
			printer.Print(
			    "#include \"umundo/rpc/Service.h\"\n"
			    "#include \"umundo/rpc/ServiceManager.h\"\n"
			    "#include \"$basename$.rpc.pb.h\"\n\n"
			    "namespace umundo {\n\n",
			    "basename", basename
			);

			for (int i = 0; i < file->service_count(); i++) {
				const ServiceDescriptor* svcDesc = file->service(i);
				writeServiceImplConstructor(printer, svcDesc);
				printer.Print("\n");
				writeServiceImplDispatcher(printer, svcDesc);
				printer.Print("\n");
				writeServiceImplCleanUp(printer, svcDesc);
				printer.Print("\n");
				writeServiceStubImpl(printer, svcDesc);
				printer.Print("\n\n");
			}
		}

		if (file->service_count() > 0) {
			// implementation epilog
			printer.Print("\n}\n");
		}
	}

	return true;

}

void ServiceGeneratorCPP::writeServiceStubHeader(io::Printer& printer, const ServiceDescriptor* svcDesc) const {
	printer.Print(
	    "class $svcName$Stub : public ServiceStub {\n"
	    "public:\n"
	    "\t$svcName$Stub(ServiceDescription*);\n",
	    "svcName", svcDesc->name()
	);

	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {
			const MethodDescriptor* methodDesc = svcDesc->method(i);
			printer.Print("\t$outType$* $methodName$($inType$*);\n",
			              "inType", container(methodDesc->input_type())->name(),
			              "methodName", methodDesc->name(),
			              "outType", container(methodDesc->output_type())->name()
			             );
		}
	}
	printer.Print("};\n");
}

void ServiceGeneratorCPP::writeServiceHeader(io::Printer &printer, const ServiceDescriptor* svcDesc) const {
	printer.Print(
	    "class $svcName$Base : public Service {\n"
	    "public:\n"
	    "\t$svcName$Base();\n",
	    "svcName", svcDesc->name()
	);

	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {
			const MethodDescriptor* methodDesc = svcDesc->method(i);
			printer.Print("\tvirtual $outType$* $methodName$($inType$*) = 0;\n",
			              "inType", container(methodDesc->input_type())->name(),
			              "methodName", methodDesc->name(),
			              "outType", container(methodDesc->output_type())->name()
			             );
		}

		printer.Print(
		    "protected:\n"
		    "\tvoid callMethod(string&, void*, string&, void*&, string&);\n"
		    "\tvoid cleanUpObjects(string&, void*, void*);\n"
		);
	}
	printer.Print("};\n");
}

const Descriptor* ServiceGeneratorCPP::container(const Descriptor* desc) {
//	fprintf(stderr, "checking %s\n", desc->name().c_str());
	while(desc->containing_type() != NULL) {
		desc = desc->containing_type();
//		fprintf(stderr, "\t-> %s\n", desc->name().c_str());
	}
	return desc;
}

void ServiceGeneratorCPP::writeServiceImplConstructor(io::Printer& printer, const ServiceDescriptor* svcDesc) const {

	std::set<string> inTypes;
	std::set<string> outTypes;
	std::set<string>::iterator inTypeIter;
	std::set<string>::iterator outTypeIter;

	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {
			const MethodDescriptor* methodDesc = svcDesc->method(i);
			inTypes.insert(methodDesc->input_type()->name());
			outTypes.insert(methodDesc->output_type()->name());
		}
	}

	printer.Print(
	    "$className$Stub::$className$Stub(ServiceDescription* svcDesc) : ServiceStub(svcDesc)  {\n"
	    "\t_serviceName = \"$className$\";\n",
	    "className", svcDesc->name()
	);

	// register intypes at publisher for stub, outtypes at subscriber
	for (inTypeIter = inTypes.begin(); inTypeIter != inTypes.end(); inTypeIter++) {
		printer.Print(
		    "\t_rpcPub->registerType(\"$inType$\", new $inType$());\n",
		    "inType", (*inTypeIter)
		);
	}
	for (outTypeIter = outTypes.begin(); outTypeIter != outTypes.end(); outTypeIter++) {
		printer.Print(
		    "\t_rpcSub->registerType(\"$outType$\", new $outType$());\n",
		    "outType", (*outTypeIter)
		);
	}

	printer.Print("}\n\n");

	printer.Print(
	    "$className$Base::$className$Base() {\n"
	    "\t_serviceName = \"$className$\";\n",
	    "className", svcDesc->name()
	);

	// register intypes at sublisher for impl, outtypes at publisher
	for (inTypeIter = inTypes.begin(); inTypeIter != inTypes.end(); inTypeIter++) {
		printer.Print(
		    "\t_rpcSub->registerType(\"$inType$\", new $inType$());\n",
		    "inType", (*inTypeIter)
		);
	}
	for (outTypeIter = outTypes.begin(); outTypeIter != outTypes.end(); outTypeIter++) {
		printer.Print(
		    "\t_rpcPub->registerType(\"$outType$\", new $outType$());\n",
		    "outType", (*outTypeIter)
		);
	}

	printer.Print("}\n");

}

void ServiceGeneratorCPP::writeServiceImplDispatcher(io::Printer& printer, const ServiceDescriptor* svcDesc) const {

	printer.Print(
	    "void $className$Base::callMethod(string& methodName, void* in, string& inType, void* &out, string& outType) {\n"
	    "\tif (false) {\n",
	    "className", svcDesc->name()
	);

	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {
			const MethodDescriptor* methodDesc = svcDesc->method(i);
			printer.Print(
			    "\t} else if (methodName.compare(\"$methodName$\") == 0) {\n"
			    "\t\tif (outType.length() == 0) { outType = \"$outType$\"; }\n"
			    "\t\tif (inType.length() == 0) { inType = \"$inType$\"; }\n"
			    "\t\tout = (void*)$methodName$(($inType$*)in);\n",
			    "outType", methodDesc->output_type()->name(),
			    "inType", methodDesc->input_type()->name(),
			    "methodName", methodDesc->name()
			);
		}
	}
	printer.Print("\t}\n}\n");
}

void ServiceGeneratorCPP::writeServiceImplCleanUp(io::Printer& printer, const ServiceDescriptor* svcDesc) const {
	printer.Print(
	    "void $className$Base::cleanUpObjects(string& methodName, void* in, void* out) {\n"
	    "\tif (false) {\n",
	    "className", svcDesc->name()
	);

	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {
			const MethodDescriptor* methodDesc = svcDesc->method(i);
			printer.Print(
			    "\t} else if (methodName.compare(\"$methodName$\") == 0) {\n"
			    "\t\tif (in != NULL) delete(($inType$*)in);\n"
			    "\t\tif (out != NULL) delete(($outType$*)out);\n",
			    "inType", methodDesc->input_type()->name(),
			    "outType", methodDesc->output_type()->name(),
			    "methodName", methodDesc->name()
			);
		}
	}
	printer.Print("\t}\n}\n");
}

void ServiceGeneratorCPP::writeServiceStubImpl(io::Printer& printer, const ServiceDescriptor* svcDesc) const {
	if (svcDesc->method_count() > 0) {
		for (int i = 0; i < svcDesc->method_count(); i++) {

			const MethodDescriptor* methodDesc = svcDesc->method(i);
			printer.Print(
			    "$outType$* $className$Stub",
			    "className", svcDesc->name(),
			    "outType", methodDesc->output_type()->name());

			printer.Print(
			    "::$methodName$($inType$* in) {\n"
			    "\tvoid* out = NULL;\n"
			    "\tcallStubMethod(\"$methodName$\", in, \"$inType$\", out, \"$outType$\");\n"
			    "\treturn ($outType$*)out;\n"
			    "}\n",
			    "inType", methodDesc->input_type()->name(),
			    "methodName", methodDesc->name(),
			    "outType", methodDesc->output_type()->name()
			);
		}
	}
}

}

int main(int argc, char* argv[]) {
	umundo::ServiceGeneratorCPP generator;
	return google::protobuf::compiler::PluginMain(argc, argv, &generator);
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <gtest/gtest.h>

namespace grpc {
namespace {

class CodegenTestMinimal : public ::testing::Test {};

TEST_F(CodegenTestMinimal, Build) {}

}  // namespace
}  // namespace grpc

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Implement newly virtualized "Next"<commit_after>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <gtest/gtest.h>
#include <grpcpp/impl/codegen/completion_queue.h>

namespace grpc {

// Unused implementation for the virtual "Next" method.
bool CompletionQueue::Next(void** tag, bool* ok) {
  return false;
}

namespace {

class CodegenTestMinimal : public ::testing::Test {};

TEST_F(CodegenTestMinimal, Build) {}

}  // namespace
}  // namespace grpc

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>