<commit_before>//
//  TiledVectorLayerTileImageProvider.cpp
//  G3MiOSSDK
//
//  Created by Diego Gomez Deck on 4/30/14.
//
//

#include "TiledVectorLayerTileImageProvider.hpp"
#include "TiledVectorLayer.hpp"
#include "Tile.hpp"
#include "IDownloader.hpp"
#include "TileImageListener.hpp"
#include "TileImageContribution.hpp"
#include "GEOJSONParser.hpp"
#include "GEOObject.hpp"
#include "GEORasterSymbolizer.hpp"
#include "IFactory.hpp"
#include "ICanvas.hpp"
#include "GEORasterProjection.hpp"

TiledVectorLayerTileImageProvider::GEOJSONBufferParser::~GEOJSONBufferParser() {
  _imageAssembler->deletedParser();

  if (_buffer) printf("    ****** (2) Deleting buffer=%p\n", _buffer);
  delete _buffer;
  if (_geoObject) printf("    ****** (2) Deleting geoObject=%p\n", _geoObject);
  delete _geoObject;
#ifdef JAVA_CODE
  super.dispose();
#endif
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::cancel() {
  _imageAssembler = NULL;

//  printf("    ****** (1) Deleting buffer=%p\n", _buffer);
//  delete _buffer;
//  _buffer = NULL;
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::runInBackground(const G3MContext* context) {
  if ((_imageAssembler != NULL) && (_buffer != NULL)) {
    printf("    ****** Parsing buffer=%p\n", _buffer);
    _geoObject = GEOJSONParser::parseJSON(_buffer);
    printf("    ****** Parsed geoObject=%p\n", _geoObject);
  }
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::onPostExecute(const G3MContext* context) {
  if (_imageAssembler != NULL) {
    GEOObject* geoObject = _geoObject;
    _geoObject = NULL; // moves ownership of _geoObject to _imageAssembler
    _imageAssembler->parsedGEOObject(geoObject);
  }
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onDownload(const URL& url,
                                                                                IByteBuffer* buffer,
                                                                                bool expired) {
  _imageAssembler->bufferDownloaded(buffer);
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onError(const URL& url) {
  _imageAssembler->bufferDownloadError(url);
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onCancel(const URL& url) {
  _imageAssembler->bufferDownloadCanceled();
}

TiledVectorLayerTileImageProvider::ImageAssembler::ImageAssembler(TiledVectorLayerTileImageProvider* tileImageProvider,
                                                                  const Tile*                        tile,
                                                                  const TileImageContribution*       contribution,
                                                                  TileImageListener*                 listener,
                                                                  bool                               deleteListener,
                                                                  const Vector2I&                    imageResolution,
                                                                  IDownloader*                       downloader,
                                                                  const IThreadUtils*                threadUtils) :
_tileImageProvider(tileImageProvider),
_tileId(tile->_id),
_tileSector(tile->_sector),
_tileIsMercator(tile->_mercator),
_tileLevel(tile->_level),
_contribution(contribution),
_listener(listener),
_deleteListener(deleteListener),
_imageWidth(imageResolution._x),
_imageHeight(imageResolution._y),
_downloader(downloader),
_threadUtils(threadUtils),
_canceled(false),
_downloadListener(NULL),
_downloadRequestId(-1),
_parser(NULL),
_symbolizer(NULL)
{

}

void TiledVectorLayerTileImageProvider::ImageAssembler::start(const TiledVectorLayer* layer,
                                                              const Tile*             tile,
                                                              long long               tileDownloadPriority,
                                                              bool                    logDownloadActivity) {
  _downloadListener = new GEOJSONBufferDownloadListener(this);

  _symbolizer = layer->symbolizerCopy();

  _downloadRequestId = layer->requestGEOJSONBuffer(tile,
                                                   _downloader,
                                                   tileDownloadPriority,
                                                   logDownloadActivity,
                                                   _downloadListener,
                                                   true /* deleteListener */);

}

TiledVectorLayerTileImageProvider::ImageAssembler::~ImageAssembler() {
  if (_deleteListener) {
    delete _listener;
  }
  TileImageContribution::deleteContribution(_contribution);
  delete _symbolizer;
}

void TiledVectorLayerTileImageProvider::ImageAssembler::cancel() {
  _canceled = true;
  if (_downloadRequestId >= 0) {
    _downloader->cancelRequest(_downloadRequestId);
    _downloadRequestId = -1;
  }
  if (_parser != NULL) {
    _parser->cancel();
  }

#warning TODO call listener cancel
  _listener->imageCreationCanceled(_tileId);
  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloaded(IByteBuffer* buffer) {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  if (!_canceled) {
    _parser = new GEOJSONBufferParser(this, buffer);
    _threadUtils->invokeAsyncTask(_parser,
                                  true);
  }

#warning Diego at work!
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloadError(const URL& url) {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  _listener->imageCreationError(_tileId,
                                "Download error - " + url.getPath());
  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloadCanceled() {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  // do nothing here, the cancel() method already notified the listener
//  _listener->imageCreationCanceled(_tileId);
//  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::parsedGEOObject(GEOObject* geoObject) {
  if (geoObject == NULL) {
    _listener->imageCreationError(_tileId, "GEOJSON parser error");
    if (_deleteListener) {
      delete _listener;
    }
  }
  else {
#warning Diego at work!
    //ILogger::instance()->logInfo("Parsed geojson");

    if (_canceled) {
      printf("    ****** <<CANCELED>> Rasterizing geoObject=%p\n", geoObject);
    }
    else {
      printf("    ****** Rasterizing geoObject=%p\n", geoObject);
    }

    ICanvas* canvas = IFactory::instance()->createCanvas();

    canvas->initialize(_imageWidth, _imageHeight);

    const GEORasterProjection* projection = new GEORasterProjection(_tileSector,
                                                                    _tileIsMercator,
                                                                    _imageWidth,
                                                                    _imageHeight);;
    geoObject->rasterize(_symbolizer,
                         canvas,
                         projection,
                         _tileLevel);

    delete projection;
    delete canvas;

    printf("    ****** (1) Deleting geoObject=%p\n", geoObject);
    delete geoObject;

#warning remove this
    _listener->imageCreationError(_tileId,
                                  "NOT YET IMPLEMENTED");

    TileImageContribution::deleteContribution(_contribution);
    _contribution = NULL;

    _tileImageProvider->requestFinish(_tileId);
  }
}

void TiledVectorLayerTileImageProvider::ImageAssembler::deletedParser() {
  _parser = NULL;
}

const TileImageContribution* TiledVectorLayerTileImageProvider::contribution(const Tile* tile) {
  return _layer->contribution(tile);
}

void TiledVectorLayerTileImageProvider::create(const Tile* tile,
                                               const TileImageContribution* contribution,
                                               const Vector2I& resolution,
                                               long long tileDownloadPriority,
                                               bool logDownloadActivity,
                                               TileImageListener* listener,
                                               bool deleteListener,
                                               FrameTasksExecutor* frameTasksExecutor) {

  ImageAssembler* assembler = new ImageAssembler(this,
                                                 tile,
                                                 contribution,
                                                 listener,
                                                 deleteListener,
                                                 resolution,
                                                 _downloader,
                                                 _threadUtils);

  _assemblers[tile->_id] = assembler;

  assembler->start(_layer,
                   tile,
                   tileDownloadPriority,
                   logDownloadActivity);
}

void TiledVectorLayerTileImageProvider::cancel(const std::string& tileId) {
#ifdef C_CODE
  if (_assemblers.find(tileId) != _assemblers.end()) {
    ImageAssembler* assembler = _assemblers[tileId];

    assembler->cancel();
  }
#endif
#ifdef JAVA_CODE
  final ImageAssembler assembler = _assemblers.get(tileId);
  if (assembler != null) {
    assembler.cancel();
  }
#endif
}

void TiledVectorLayerTileImageProvider::requestFinish(const std::string& tileId) {
#ifdef C_CODE
  if (_assemblers.find(tileId) != _assemblers.end()) {
    ImageAssembler* assembler = _assemblers[tileId];

    delete assembler;

    _assemblers.erase(tileId);
  }
#endif
#ifdef JAVA_CODE
  final ImageAssembler assembler = _assemblers.remove(tileId);
  if (assembler != null) {
    assembler.dispose();
  }
#endif
}
<commit_msg>Tile's image creation refactoring - NOT YET USABLE<commit_after>//
//  TiledVectorLayerTileImageProvider.cpp
//  G3MiOSSDK
//
//  Created by Diego Gomez Deck on 4/30/14.
//
//

#include "TiledVectorLayerTileImageProvider.hpp"
#include "TiledVectorLayer.hpp"
#include "Tile.hpp"
#include "IDownloader.hpp"
#include "TileImageListener.hpp"
#include "TileImageContribution.hpp"
#include "GEOJSONParser.hpp"
#include "GEOObject.hpp"
#include "GEORasterSymbolizer.hpp"
#include "IFactory.hpp"
#include "ICanvas.hpp"
#include "GEORasterProjection.hpp"

TiledVectorLayerTileImageProvider::GEOJSONBufferParser::~GEOJSONBufferParser() {
  _imageAssembler->deletedParser();

  delete _buffer;
  delete _geoObject;
#ifdef JAVA_CODE
  super.dispose();
#endif
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::cancel() {
  _imageAssembler = NULL;

//  delete _buffer;
//  _buffer = NULL;
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::runInBackground(const G3MContext* context) {
  if ((_imageAssembler != NULL) && (_buffer != NULL)) {
    _geoObject = GEOJSONParser::parseJSON(_buffer);
  }
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::onPostExecute(const G3MContext* context) {
  if (_imageAssembler != NULL) {
    GEOObject* geoObject = _geoObject;
    _geoObject = NULL; // moves ownership of _geoObject to _imageAssembler
    _imageAssembler->parsedGEOObject(geoObject);
  }
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onDownload(const URL& url,
                                                                                IByteBuffer* buffer,
                                                                                bool expired) {
  _imageAssembler->bufferDownloaded(buffer);
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onError(const URL& url) {
  _imageAssembler->bufferDownloadError(url);
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onCancel(const URL& url) {
  _imageAssembler->bufferDownloadCanceled();
}

TiledVectorLayerTileImageProvider::ImageAssembler::ImageAssembler(TiledVectorLayerTileImageProvider* tileImageProvider,
                                                                  const Tile*                        tile,
                                                                  const TileImageContribution*       contribution,
                                                                  TileImageListener*                 listener,
                                                                  bool                               deleteListener,
                                                                  const Vector2I&                    imageResolution,
                                                                  IDownloader*                       downloader,
                                                                  const IThreadUtils*                threadUtils) :
_tileImageProvider(tileImageProvider),
_tileId(tile->_id),
_tileSector(tile->_sector),
_tileIsMercator(tile->_mercator),
_tileLevel(tile->_level),
_contribution(contribution),
_listener(listener),
_deleteListener(deleteListener),
_imageWidth(imageResolution._x),
_imageHeight(imageResolution._y),
_downloader(downloader),
_threadUtils(threadUtils),
_canceled(false),
_downloadListener(NULL),
_downloadRequestId(-1),
_parser(NULL),
_symbolizer(NULL)
{

}

void TiledVectorLayerTileImageProvider::ImageAssembler::start(const TiledVectorLayer* layer,
                                                              const Tile*             tile,
                                                              long long               tileDownloadPriority,
                                                              bool                    logDownloadActivity) {
  _downloadListener = new GEOJSONBufferDownloadListener(this);

  _symbolizer = layer->symbolizerCopy();

  _downloadRequestId = layer->requestGEOJSONBuffer(tile,
                                                   _downloader,
                                                   tileDownloadPriority,
                                                   logDownloadActivity,
                                                   _downloadListener,
                                                   true /* deleteListener */);

}

TiledVectorLayerTileImageProvider::ImageAssembler::~ImageAssembler() {
  if (_deleteListener) {
    delete _listener;
  }
  TileImageContribution::deleteContribution(_contribution);
  delete _symbolizer;
}

void TiledVectorLayerTileImageProvider::ImageAssembler::cancel() {
  _canceled = true;
  if (_downloadRequestId >= 0) {
    _downloader->cancelRequest(_downloadRequestId);
    _downloadRequestId = -1;
  }
  if (_parser != NULL) {
    _parser->cancel();
  }

#warning TODO call listener cancel
  _listener->imageCreationCanceled(_tileId);
  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloaded(IByteBuffer* buffer) {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  if (!_canceled) {
    _parser = new GEOJSONBufferParser(this, buffer);
    _threadUtils->invokeAsyncTask(_parser,
                                  true);
  }

#warning Diego at work!
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloadError(const URL& url) {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  _listener->imageCreationError(_tileId,
                                "Download error - " + url.getPath());
  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloadCanceled() {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  // do nothing here, the cancel() method already notified the listener
//  _listener->imageCreationCanceled(_tileId);
//  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::parsedGEOObject(GEOObject* geoObject) {
  if (geoObject == NULL) {
    _listener->imageCreationError(_tileId, "GEOJSON parser error");
    if (_deleteListener) {
      delete _listener;
    }
  }
  else {
#warning Diego at work!
    //ILogger::instance()->logInfo("Parsed geojson");

    ICanvas* canvas = IFactory::instance()->createCanvas();

    canvas->initialize(_imageWidth, _imageHeight);

    const GEORasterProjection* projection = new GEORasterProjection(_tileSector,
                                                                    _tileIsMercator,
                                                                    _imageWidth,
                                                                    _imageHeight);;
    geoObject->rasterize(_symbolizer,
                         canvas,
                         projection,
                         _tileLevel);

    delete projection;
    delete canvas;

    delete geoObject;

#warning remove this
    _listener->imageCreationError(_tileId,
                                  "NOT YET IMPLEMENTED");

    TileImageContribution::deleteContribution(_contribution);
    _contribution = NULL;

    _tileImageProvider->requestFinish(_tileId);
  }
}

void TiledVectorLayerTileImageProvider::ImageAssembler::deletedParser() {
  _parser = NULL;
}

const TileImageContribution* TiledVectorLayerTileImageProvider::contribution(const Tile* tile) {
  return _layer->contribution(tile);
}

void TiledVectorLayerTileImageProvider::create(const Tile* tile,
                                               const TileImageContribution* contribution,
                                               const Vector2I& resolution,
                                               long long tileDownloadPriority,
                                               bool logDownloadActivity,
                                               TileImageListener* listener,
                                               bool deleteListener,
                                               FrameTasksExecutor* frameTasksExecutor) {

  ImageAssembler* assembler = new ImageAssembler(this,
                                                 tile,
                                                 contribution,
                                                 listener,
                                                 deleteListener,
                                                 resolution,
                                                 _downloader,
                                                 _threadUtils);

  _assemblers[tile->_id] = assembler;

  assembler->start(_layer,
                   tile,
                   tileDownloadPriority,
                   logDownloadActivity);
}

void TiledVectorLayerTileImageProvider::cancel(const std::string& tileId) {
#ifdef C_CODE
  if (_assemblers.find(tileId) != _assemblers.end()) {
    ImageAssembler* assembler = _assemblers[tileId];

    assembler->cancel();
  }
#endif
#ifdef JAVA_CODE
  final ImageAssembler assembler = _assemblers.get(tileId);
  if (assembler != null) {
    assembler.cancel();
  }
#endif
}

void TiledVectorLayerTileImageProvider::requestFinish(const std::string& tileId) {
#ifdef C_CODE
  if (_assemblers.find(tileId) != _assemblers.end()) {
    ImageAssembler* assembler = _assemblers[tileId];

    delete assembler;

    _assemblers.erase(tileId);
  }
#endif
#ifdef JAVA_CODE
  final ImageAssembler assembler = _assemblers.remove(tileId);
  if (assembler != null) {
    assembler.dispose();
  }
#endif
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <stdexcept>

const uint32_t MOD = 1000000007;

const size_t MAX_LENGTH = 200;

typedef std::vector<std::vector<uint32_t>> matrix;

/**
 * The class substring presents an efficient substring view of a string by
 * using an offset and source string reference to avoid copy substrings.
 */
class substring {
 private:
  const std::string& source;

  size_t start;

  size_t end;

 public:
  substring(const std::string& source, size_t start, size_t end) :
    source(source), start(start), end(end) {
  }

  const char& operator[](size_t i) const {
    if (i >= this->length()) {
      throw std::invalid_argument("Out of bounds!");
    }
    return this->source[this->start + i];
  }

  size_t length() const {
    return this->end - this->start + 1;
  }
};

uint32_t add(const uint32_t& a, const uint32_t& b) {
  return ((uint64_t) a + b) % MOD;
}

uint32_t sub(const uint32_t& a, const uint32_t& b) {
  return ((uint64_t) a - b + MOD) % MOD;
}

template<class S, class C>
uint32_t common(const S& a, const S& b, C& cache) { // NOLINT
  cache[0][0] = 1;

  for (size_t j = 0; j <= a.length(); j++) {
    for (size_t k = 0; k <= b.length(); k++) {
      if (j > 0 || k > 0) {
        cache[j][k] = 0;
      }
      if (j > 0) {
        cache[j][k] = add(cache[j][k], cache[j - 1][k]);
      }
      if (k > 0) {
        cache[j][k] = add(cache[j][k], cache[j][k - 1]);
      }
      if (j > 0 && k > 0 && a[j - 1] != b[k - 1]) {
        cache[j][k] = sub(cache[j][k], cache[j - 1][k - 1]);
      }
    }
  }

  uint32_t count = 0;
  for (size_t k = 0; k < b.length(); k++) {
    if (a[a.length() - 1] == b[k]) {
      count = add(count, cache[a.length() - 1][k]);
    }
  }
  return count;
}

uint32_t countss(const std::string& str, matrix& cache) { // NOLINT
  uint32_t count = 0;
  for (size_t i = 0; i < str.length() - 1; i++) {
    substring a(str, 0, i);
    substring b(str, i + 1, str.length() - 1);
    count = add(count, common<substring, matrix>(a, b, cache));
  }
  return count;
}

uint32_t countss(const std::string& str) {
  matrix cache(MAX_LENGTH + 1, std::vector<uint32_t>(MAX_LENGTH + 1, 0));
  return countss(str, cache);
}

int main() {
  uint16_t T;
  std::string S;
  std::cin >> T;
  while (T--) {
    std::cin >> S;
    std::cout << countss(S) << std::endl;
  }
  return 0;
}
<commit_msg>Cleanup Square Subsequences problem<commit_after>#include <iostream>
#include <array>

const uint32_t MOD = 1000000007;

const size_t MAX_LENGTH = 200;

//
// Safely calculates (a + b) % MOD
//
int add(int a, int b) {
  return ((int64_t) a + b) % MOD;
}

//
// Safely calculates (a - b) % MOD
//
int sub(int a, int b) {
  return ((int64_t) a - b + MOD) % MOD;
}

//
// Calculates the number of subsequences in common between L = s[0...p] and
// R = s[p + 1...n] where each subsequence ends with s[p]. Takes
// O(length(L) * length(R)) time.
//
int common(const std::string& s, int p) {
  // Each dp[i][j] is the number of common subsequences in the first i
  // characters of L and the first j characters of R.
  int dp[MAX_LENGTH][MAX_LENGTH] = {{0}};

  // Length of L = s[0...p].
  int n = p + 1;

  // Length of R = s[p + 1...n].
  int m = s.size() - n;

  // Base case - Length of longest common subsequences between "" and x where
  // |x| > 0 is 1. (The empty subsequence)
  for (int i = 0; i <= n; i++) {
    dp[i][0] = 1;
  }

  for (int j = 0; j <= m; j++) {
    dp[0][j] = 1;
  }

  //
  // Consider function f(i, j) = The number of common subsequences between
  // L[0...i - 1] and R[0...j - 1]. We have already described the base case
  // H(*, 0) = H(0, *) = 1 above. The two recursive cases are as follows.
  //
  // 1. H(i, j) = H(i, j - 1) + H(i - 1, j) - H(i - 1, j - 1) if
  //    L[i - 1] != R[j - 1]. We must subtract H(i - 1, j - 1) to avoid double
  //    counting subsequences. (Inclusion Exclusion Principle)
  //
  // 2. H(i, j) = H(i, j - 1) + H(i - 1, j) - H(i - 1, j - 1) + H(i - 1, j - 1)
  //    = H(i - 1, j) + H(i, j - 1) if L[i - 1] == R[j - 1]. We must consider
  //    common subsequences counted by H(i - 1, j - 1) as a prefix to the
  //    common subsequences ending with L[i - 1] == R[j - 1].
  //
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      dp[i][j] = add(dp[i][j], dp[i - 1][j]);

      dp[i][j] = add(dp[i][j], dp[i][j - 1]);

      if (s[i - 1] != s[p + j]) {
        dp[i][j] = sub(dp[i][j], dp[i - 1][j - 1]);
      }
    }
  }

  //
  // Count only the common subsequences ending with s[p] - the last character
  // of L.
  //
  int count = 0;

  for (int j = 0; j < m; j++) {
    if (s[p] == s[p + j + 1]) {
      count = add(count, dp[p][j]);
    }
  }

  return count;
}

//
// Counts the square subsequences in s. The idea behind the algorithm is to...
//
// 1. Consider all partitions s = LR of s where |L| > 0 and |R| > 0
//
// 2. Count the number of subsequences shared between each L and R ending with
//    the last character of L. This is important because it forms a partition
//    boundary so that we do not double count any subsequences across different
//    partitions.
//
int countss(const std::string& s) {
  int count = 0;
  for (size_t p = 0; p < s.length() - 1; p++) {
    count = add(count, common(s, p));
  }
  return count;
}

int main() {
  int T;
  std::string S;
  std::cin >> T;
  while (T--) {
    std::cin >> S;
    std::cout << countss(S) << std::endl;
  }
  return 0;
}
<|endoftext|>


<commit_before>/*
  RCSwitch - Arduino libary for remote control outlet switches
  Copyright (c) 2011 Suat Özgür.  All right reserved.

  Contributors:
  - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com

  Project home: http://code.google.com/p/rc-switch/

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

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "RCSwitch.h"

RCSwitchCallback RCSwitch::mCallback;

RCSwitch::RCSwitch() {
  this->nReceiverInterrupt = -1;
  this->nTransmitterPin = -1;
  this->setPulseLength(350);
  this->setRepeatTransmit(10);
}

/**
 * deprecated
 */
RCSwitch::RCSwitch(int nTransmitterPin) {
  this->enableTransmit(nTransmitterPin);
  this->setPulseLength(350);
  this->setRepeatTransmit(10);
}

/**
 * deprecated
 */
RCSwitch::RCSwitch(int nTransmitterPin, int nDelay) {
  this->enableTransmit(nTransmitterPin);
  this->setPulseLength(nDelay);
  this->setRepeatTransmit(10);
}

/**
  * Sets pulse length in microseconds
  */
void RCSwitch::setPulseLength(int nPulseLength) {
  this->nPulseLength = nPulseLength;
}

/**
  * Sets Repeat Transmits
  */
void RCSwitch::setRepeatTransmit(int RepeatTransmit) {
  this->RepeatTransmit = RepeatTransmit;
}

/**
 * Enable transmissions
 *
 * @param nTransmitterPin    Arduino Pin to which the sender is connected to
 */
void RCSwitch::enableTransmit(int nTransmitterPin) {
  this->nTransmitterPin = nTransmitterPin;
  pinMode(this->nTransmitterPin, OUTPUT);
}

/**
  * Disable transmissions
  */
void RCSwitch::disableTransmit() {
  this->nTransmitterPin = -1;
}

/**
 * Switch a remote switch on (Type C Intertechno)
 *
 * @param sFamily  Familycode (a..f)
 * @param nGroup   Number of group (1..4)
 * @param nDevice  Number of device (1..4)
  */
void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) {
  this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) );
}

/**
 * Switch a remote switch off (Type C Intertechno)
 *
 * @param sFamily  Familycode (a..f)
 * @param nGroup   Number of group (1..4)
 * @param nDevice  Number of device (1..4)
 */
void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) {
  this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) );
}

/**
 * Switch a remote switch on (Type B with two rotary/sliding switches)
 *
 * @param nAddressCode  Number of the switch group (1..4)
 * @param nChannelCode  Number of the switch itself (1..4)
 */
void RCSwitch::switchOn(int nAddressCode, int nChannelCode) {
  this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) );
}

/**
 * Switch a remote switch off (Type B with two rotary/sliding switches)
 *
 * @param nAddressCode  Number of the switch group (1..4)
 * @param nChannelCode  Number of the switch itself (1..4)
 */
void RCSwitch::switchOff(int nAddressCode, int nChannelCode) {
  this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) );
}

/**
 * Switch a remote switch on (Type A with 10 pole DIP switches)
 *
 * @param sGroup        Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
 * @param nChannelCode  Number of the switch itself (1..4)
 */
void RCSwitch::switchOn(String sGroup, int nChannel) {
  this->sendTriState( this->getCodeWordA(sGroup, nChannel, true) );
}

/**
 * Switch a remote switch off (Type A with 10 pole DIP switches)
 *
 * @param sGroup        Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
 * @param nChannelCode  Number of the switch itself (1..4)
 */
void RCSwitch::switchOff(String sGroup, int nChannel) {
  this->sendTriState( this->getCodeWordA(sGroup, nChannel, false) );
}

/**
 * Returns a String[13], representing the Code Word to be send.
 * A Code Word consists of 9 address bits, 3 data bits and one sync bit but in our case only the first 8 address bits and the last 2 data bits were used.
 * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit)
 *
 * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
 * | 4 bits address (switch group) | 4 bits address (switch number) | 1 bit address (not used, so never mind) | 1 bit address (not used, so never mind) | 2 data bits (on|off) | 1 sync bit |
 * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0   | 1=0FFF 2=F0FF 3=FF0F 4=FFF0    | F                                       | F                                       | on=FF off=F0         | S          |
 * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
 *
 * @param nAddressCode  Number of the switch group (1..4)
 * @param nChannelCode  Number of the switch itself (1..4)
 * @param bStatus       Wether to switch on (true) or off (false)
 *
 * @return String[13]
 */
String RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, boolean bStatus) {
   String code[5] = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };

   if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
    return "";
   }

   return code[nAddressCode] + code[nChannelCode] + "FF" + (bStatus==true?"FF":"F0");
}

/**
 * Like getCodeWord  (Type A)
 */
String RCSwitch::getCodeWordA(String sGroup, int nChannelCode, boolean bStatus) {
  String code[6] = { "FFFFF", "0FFFF", "F0FFF", "FF0FF", "FFF0F", "FFFF0" };

  if (sGroup.length() != 5 || nChannelCode < 1 || nChannelCode > 5) {
    return "";
  }

  String sAddressCode = "";
  for (int i = 0; i<5; i++) {
    if (sGroup[i] == '0') {
      sAddressCode += "F";
    } else {
      sAddressCode += "0";
    }
  }

  return sAddressCode + code[nChannelCode] + (bStatus==true?"0F":"F0");
}

/**
 * Like getCodeWord (Type C = Intertechno)
 */
String RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, boolean bStatus) {
  if ( (byte)sFamily < 97 || (byte)sFamily > 112) {
    return "";
  }
  if (nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
    return "";
  }
  char* sDeviceGroupCode =  dec2binWzerofill(  (nDevice-1) + (nGroup-1)*4, 4  );
  String familycode[16] = { "0000", "1000", "0100", "1100", "0010", "1010", "0110", "1110", "0001", "1001", "0101", "1101", "0011", "1011", "0111", "1111" };
  String sReturn = familycode[ (int)sFamily - 97 ];
  for (int i = 0; i<4; i++) {
    sReturn = sReturn + sDeviceGroupCode[3-i];
  }
  sReturn = sReturn + "01";
  sReturn = sReturn + (bStatus==true?"11":"10");
  return sReturn;
}

/**
 * Sends a Code Word
 * @param sCodeWord   /^[10FS]*$/  -> see getCodeWord
 */
void RCSwitch::sendTriState(String sCodeWord) {
  for (int nRepeat=0; nRepeat<RepeatTransmit; nRepeat++) {
    for(int i=0; i<sCodeWord.length(); i++) {
      switch(sCodeWord[i]) {
        case '0':
          this->sendT0();
        break;
        case 'F':
          this->sendTF();
        break;
        case '1':
          this->sendT1();
        break;
      }
    }
    this->sendSync();
  }
}

void RCSwitch::send(unsigned long Code, unsigned int length) {
  this->send( this->dec2binWzerofill(Code, length) );
}

void RCSwitch::send(char* sCodeWord) {
  for (int nRepeat=0; nRepeat<RepeatTransmit; nRepeat++) {
    int i = 0;
    while (sCodeWord[i] != '\0') {
      switch(sCodeWord[i]) {
        case '0':
          this->send0();
        break;
        case '1':
          this->send1();
        break;
      }
      i++;
    }
    this->sendSync();
  }
}

void RCSwitch::transmit(int nHighPulses, int nLowPulses) {

  if (this->nTransmitterPin != -1) {
    int nRec = this->nReceiverInterrupt;
    if (this->nReceiverInterrupt != -1) {
      this->disableReceive();
    }
    digitalWrite(this->nTransmitterPin, HIGH);
    delayMicroseconds( this->nPulseLength * nHighPulses);
    digitalWrite(this->nTransmitterPin, LOW);
    delayMicroseconds( this->nPulseLength * nLowPulses);
    if (nRec != -1) {
      this->enableReceive(nRec, this->mCallback);
    }
  }
}

/**
 * Sends a "0" Bit
 *            _
 * Waveform: | |___
 */
void RCSwitch::send0() {
  this->transmit(1,3);
}

/**
 * Sends a "1" Bit
 *            ___
 * Waveform: |   |_
 */
void RCSwitch::send1() {
  this->transmit(3,1);
}

/**
 * Sends a Tri-State "0" Bit
 *            _     _
 * Waveform: | |___| |___
 */
void RCSwitch::sendT0() {
  this->transmit(1,3);
  this->transmit(1,3);
}

/**
 * Sends a Tri-State "1" Bit
 *            ___   ___
 * Waveform: |   |_|   |_
 */
void RCSwitch::sendT1() {
  this->transmit(3,1);
  this->transmit(3,1);
}

/**
 * Sends a Tri-State "F" Bit
 *            _     ___
 * Waveform: | |___|   |_
 */
void RCSwitch::sendTF() {
  this->transmit(1,3);
  this->transmit(3,1);
}

/**
 * Sends a "Sync" Bit
 *            _
 * Waveform: | |_______________________________
 */
void RCSwitch::sendSync() {
  this->transmit(1,31);
}

/**
 * Enable receiving data
 */
void RCSwitch::enableReceive(int interrupt, RCSwitchCallback callback) {
  this->nReceiverInterrupt = interrupt;
  attachInterrupt(this->nReceiverInterrupt, receiveInterrupt, CHANGE);
  this->mCallback = callback;
}

/**
 * Disable receiving data
 */
void RCSwitch::disableReceive() {
  detachInterrupt(this->nReceiverInterrupt);
  this->nReceiverInterrupt = -1;
}

/**
 *
 */
void RCSwitch::receiveInterrupt() {

  static unsigned int duration;
  static unsigned int changeCount;
  static unsigned int timings[RCSWITCH_MAX_CHANGES];
  static unsigned long lastTime;
  static unsigned int repeatCount;

  long time = micros();
  duration = time - lastTime;

  if (duration > 5000 && duration > timings[0] - 200 && duration < timings[0] + 200) {
    repeatCount++;
    changeCount--;
    if (repeatCount == 2) {

      unsigned long code = 0;
      unsigned long delay = timings[0] / 31;
      unsigned long delayTolerance = delay*0.3;
      for (int i = 1; i<changeCount ; i=i+2) {

          if (timings[i] > delay-delayTolerance && timings[i] < delay+delayTolerance && timings[i+1] > delay*3-delayTolerance && timings[i+1] < delay*3+delayTolerance) {
            code = code << 1;
          } else if (timings[i] > delay*3-delayTolerance && timings[i] < delay*+delayTolerance && timings[i+1] > delay-delayTolerance && timings[i+1] < delay+delayTolerance) {
            code+=1;
            code = code << 1;
          } else {
            // Failed
            i = changeCount;
            code = 0;
            repeatCount = 0;
          }
      }
      code = code >> 1;
      (mCallback)(code, changeCount/2, delay, timings);
      repeatCount = 0;
    }
    changeCount = 0;
  } else if (duration > 5000) {
    changeCount = 0;
  }

  if (changeCount >= RCSWITCH_MAX_CHANGES) {
    changeCount = 0;
    repeatCount = 0;
  }
  timings[changeCount++] = duration;
  lastTime = time;
}

/**
  * Turns a decimal value to its binary representation
  */
char* RCSwitch::dec2binWzerofill(unsigned long Dec, unsigned int bitLength){
  static char bin[64];
  unsigned int i=0;

  while (Dec > 0) {
    bin[32+i++] = (Dec & 1 > 0) ? '1' : '0';
    Dec = Dec >> 1;
  }

  for (unsigned int j = 0; j< bitLength; j++) {
    if (j >= bitLength - i) {
      bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
    }else {
      bin[j] = '0';
    }
  }
  bin[bitLength] = '\0';

  return bin;
}

<commit_msg>bugfix Intertechno encoding<commit_after>/*
  RCSwitch - Arduino libary for remote control outlet switches
  Copyright (c) 2011 Suat Özgür.  All right reserved.

  Contributors:
  - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com

  Project home: http://code.google.com/p/rc-switch/

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

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "RCSwitch.h"

RCSwitchCallback RCSwitch::mCallback;

RCSwitch::RCSwitch() {
  this->nReceiverInterrupt = -1;
  this->nTransmitterPin = -1;
  this->setPulseLength(350);
  this->setRepeatTransmit(10);
}

/**
 * deprecated
 */
RCSwitch::RCSwitch(int nTransmitterPin) {
  this->enableTransmit(nTransmitterPin);
  this->setPulseLength(350);
  this->setRepeatTransmit(10);
}

/**
 * deprecated
 */
RCSwitch::RCSwitch(int nTransmitterPin, int nDelay) {
  this->enableTransmit(nTransmitterPin);
  this->setPulseLength(nDelay);
  this->setRepeatTransmit(10);
}

/**
  * Sets pulse length in microseconds
  */
void RCSwitch::setPulseLength(int nPulseLength) {
  this->nPulseLength = nPulseLength;
}

/**
  * Sets Repeat Transmits
  */
void RCSwitch::setRepeatTransmit(int RepeatTransmit) {
  this->RepeatTransmit = RepeatTransmit;
}

/**
 * Enable transmissions
 *
 * @param nTransmitterPin    Arduino Pin to which the sender is connected to
 */
void RCSwitch::enableTransmit(int nTransmitterPin) {
  this->nTransmitterPin = nTransmitterPin;
  pinMode(this->nTransmitterPin, OUTPUT);
}

/**
  * Disable transmissions
  */
void RCSwitch::disableTransmit() {
  this->nTransmitterPin = -1;
}

/**
 * Switch a remote switch on (Type C Intertechno)
 *
 * @param sFamily  Familycode (a..f)
 * @param nGroup   Number of group (1..4)
 * @param nDevice  Number of device (1..4)
  */
void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) {
  this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) );
}

/**
 * Switch a remote switch off (Type C Intertechno)
 *
 * @param sFamily  Familycode (a..f)
 * @param nGroup   Number of group (1..4)
 * @param nDevice  Number of device (1..4)
 */
void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) {
  this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) );
}

/**
 * Switch a remote switch on (Type B with two rotary/sliding switches)
 *
 * @param nAddressCode  Number of the switch group (1..4)
 * @param nChannelCode  Number of the switch itself (1..4)
 */
void RCSwitch::switchOn(int nAddressCode, int nChannelCode) {
  this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) );
}

/**
 * Switch a remote switch off (Type B with two rotary/sliding switches)
 *
 * @param nAddressCode  Number of the switch group (1..4)
 * @param nChannelCode  Number of the switch itself (1..4)
 */
void RCSwitch::switchOff(int nAddressCode, int nChannelCode) {
  this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) );
}

/**
 * Switch a remote switch on (Type A with 10 pole DIP switches)
 *
 * @param sGroup        Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
 * @param nChannelCode  Number of the switch itself (1..4)
 */
void RCSwitch::switchOn(String sGroup, int nChannel) {
  this->sendTriState( this->getCodeWordA(sGroup, nChannel, true) );
}

/**
 * Switch a remote switch off (Type A with 10 pole DIP switches)
 *
 * @param sGroup        Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
 * @param nChannelCode  Number of the switch itself (1..4)
 */
void RCSwitch::switchOff(String sGroup, int nChannel) {
  this->sendTriState( this->getCodeWordA(sGroup, nChannel, false) );
}

/**
 * Returns a String[13], representing the Code Word to be send.
 * A Code Word consists of 9 address bits, 3 data bits and one sync bit but in our case only the first 8 address bits and the last 2 data bits were used.
 * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit)
 *
 * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
 * | 4 bits address (switch group) | 4 bits address (switch number) | 1 bit address (not used, so never mind) | 1 bit address (not used, so never mind) | 2 data bits (on|off) | 1 sync bit |
 * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0   | 1=0FFF 2=F0FF 3=FF0F 4=FFF0    | F                                       | F                                       | on=FF off=F0         | S          |
 * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
 *
 * @param nAddressCode  Number of the switch group (1..4)
 * @param nChannelCode  Number of the switch itself (1..4)
 * @param bStatus       Wether to switch on (true) or off (false)
 *
 * @return String[13]
 */
String RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, boolean bStatus) {
   String code[5] = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };

   if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
    return "";
   }

   return code[nAddressCode] + code[nChannelCode] + "FF" + (bStatus==true?"FF":"F0");
}

/**
 * Like getCodeWord  (Type A)
 */
String RCSwitch::getCodeWordA(String sGroup, int nChannelCode, boolean bStatus) {
  String code[6] = { "FFFFF", "0FFFF", "F0FFF", "FF0FF", "FFF0F", "FFFF0" };

  if (sGroup.length() != 5 || nChannelCode < 1 || nChannelCode > 5) {
    return "";
  }

  String sAddressCode = "";
  for (int i = 0; i<5; i++) {
    if (sGroup[i] == '0') {
      sAddressCode += "F";
    } else {
      sAddressCode += "0";
    }
  }

  return sAddressCode + code[nChannelCode] + (bStatus==true?"0F":"F0");
}

/**
 * Like getCodeWord (Type C = Intertechno)
 */
String RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, boolean bStatus) {
  if ( (byte)sFamily < 97 || (byte)sFamily > 112) {
    return "";
  }
  if (nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
    return "";
  }
  char* sDeviceGroupCode =  dec2binWzerofill(  (nDevice-1) + (nGroup-1)*4, 4  );
  String familycode[16] = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0", "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" };
  String sReturn = familycode[ (int)sFamily - 97 ];
  for (int i = 0; i<4; i++) {
    sReturn = sReturn + (sDeviceGroupCode[3-i] == '1' ? "F" : "0");
  }
  sReturn = sReturn + "0F";
  sReturn = sReturn + (bStatus==true?"FF":"F0");
  return sReturn;
}

/**
 * Sends a Code Word
 * @param sCodeWord   /^[10FS]*$/  -> see getCodeWord
 */
void RCSwitch::sendTriState(String sCodeWord) {
  for (int nRepeat=0; nRepeat<RepeatTransmit; nRepeat++) {
    for(int i=0; i<sCodeWord.length(); i++) {
      switch(sCodeWord[i]) {
        case '0':
          this->sendT0();
        break;
        case 'F':
          this->sendTF();
        break;
        case '1':
          this->sendT1();
        break;
      }
    }
    this->sendSync();
  }
}

void RCSwitch::send(unsigned long Code, unsigned int length) {
  this->send( this->dec2binWzerofill(Code, length) );
}

void RCSwitch::send(char* sCodeWord) {
  for (int nRepeat=0; nRepeat<RepeatTransmit; nRepeat++) {
    int i = 0;
    while (sCodeWord[i] != '\0') {
      switch(sCodeWord[i]) {
        case '0':
          this->send0();
        break;
        case '1':
          this->send1();
        break;
      }
      i++;
    }
    this->sendSync();
  }
}

void RCSwitch::transmit(int nHighPulses, int nLowPulses) {

  if (this->nTransmitterPin != -1) {
    int nRec = this->nReceiverInterrupt;
    if (this->nReceiverInterrupt != -1) {
      this->disableReceive();
    }
    digitalWrite(this->nTransmitterPin, HIGH);
    delayMicroseconds( this->nPulseLength * nHighPulses);
    digitalWrite(this->nTransmitterPin, LOW);
    delayMicroseconds( this->nPulseLength * nLowPulses);
    if (nRec != -1) {
      this->enableReceive(nRec, this->mCallback);
    }
  }
}

/**
 * Sends a "0" Bit
 *            _
 * Waveform: | |___
 */
void RCSwitch::send0() {
  this->transmit(1,3);
}

/**
 * Sends a "1" Bit
 *            ___
 * Waveform: |   |_
 */
void RCSwitch::send1() {
  this->transmit(3,1);
}

/**
 * Sends a Tri-State "0" Bit
 *            _     _
 * Waveform: | |___| |___
 */
void RCSwitch::sendT0() {
  this->transmit(1,3);
  this->transmit(1,3);
}

/**
 * Sends a Tri-State "1" Bit
 *            ___   ___
 * Waveform: |   |_|   |_
 */
void RCSwitch::sendT1() {
  this->transmit(3,1);
  this->transmit(3,1);
}

/**
 * Sends a Tri-State "F" Bit
 *            _     ___
 * Waveform: | |___|   |_
 */
void RCSwitch::sendTF() {
  this->transmit(1,3);
  this->transmit(3,1);
}

/**
 * Sends a "Sync" Bit
 *            _
 * Waveform: | |_______________________________
 */
void RCSwitch::sendSync() {
  this->transmit(1,31);
}

/**
 * Enable receiving data
 */
void RCSwitch::enableReceive(int interrupt, RCSwitchCallback callback) {
  this->nReceiverInterrupt = interrupt;
  attachInterrupt(this->nReceiverInterrupt, receiveInterrupt, CHANGE);
  this->mCallback = callback;
}

/**
 * Disable receiving data
 */
void RCSwitch::disableReceive() {
  detachInterrupt(this->nReceiverInterrupt);
  this->nReceiverInterrupt = -1;
}

/**
 *
 */
void RCSwitch::receiveInterrupt() {

  static unsigned int duration;
  static unsigned int changeCount;
  static unsigned int timings[RCSWITCH_MAX_CHANGES];
  static unsigned long lastTime;
  static unsigned int repeatCount;

  long time = micros();
  duration = time - lastTime;

  if (duration > 5000 && duration > timings[0] - 200 && duration < timings[0] + 200) {
    repeatCount++;
    changeCount--;
    if (repeatCount == 2) {

      unsigned long code = 0;
      unsigned long delay = timings[0] / 31;
      unsigned long delayTolerance = delay*0.3;
      for (int i = 1; i<changeCount ; i=i+2) {

          if (timings[i] > delay-delayTolerance && timings[i] < delay+delayTolerance && timings[i+1] > delay*3-delayTolerance && timings[i+1] < delay*3+delayTolerance) {
            code = code << 1;
          } else if (timings[i] > delay*3-delayTolerance && timings[i] < delay*+delayTolerance && timings[i+1] > delay-delayTolerance && timings[i+1] < delay+delayTolerance) {
            code+=1;
            code = code << 1;
          } else {
            // Failed
            i = changeCount;
            code = 0;
            repeatCount = 0;
          }
      }
      code = code >> 1;
      (mCallback)(code, changeCount/2, delay, timings);
      repeatCount = 0;
    }
    changeCount = 0;
  } else if (duration > 5000) {
    changeCount = 0;
  }

  if (changeCount >= RCSWITCH_MAX_CHANGES) {
    changeCount = 0;
    repeatCount = 0;
  }
  timings[changeCount++] = duration;
  lastTime = time;
}

/**
  * Turns a decimal value to its binary representation
  */
char* RCSwitch::dec2binWzerofill(unsigned long Dec, unsigned int bitLength){
  static char bin[64];
  unsigned int i=0;

  while (Dec > 0) {
    bin[32+i++] = (Dec & 1 > 0) ? '1' : '0';
    Dec = Dec >> 1;
  }

  for (unsigned int j = 0; j< bitLength; j++) {
    if (j >= bitLength - i) {
      bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
    }else {
      bin[j] = '0';
    }
  }
  bin[bitLength] = '\0';

  return bin;
}

<|endoftext|>


<commit_before>#include <iostream>

#include "distances/detail/Matrix.hh"
#include "distances/detail/Munkres.hh"

using namespace aleph::distances::detail;

int main()
{
  Matrix<unsigned short> m( 3 );

  m(0,0) = 1; m(0,1) = 2; m(0,2) = 3;
  m(1,0) = 2; m(1,1) = 4; m(1,2) = 6;
  m(2,0) = 3; m(2,1) = 6; m(2,2) = 9;

  auto separator = std::string( 80, '-' );

  std::cerr << separator << "\n"
            << "Original costs\n"
            << separator << "\n"
            << m
            << separator << "\n";

  Munkres<unsigned short> solver( m );
  solver();
}
<commit_msg>Extended test for Hungarian method<commit_after>#include <iostream>
#include <string>

#include "distances/detail/Matrix.hh"
#include "distances/detail/Munkres.hh"

using namespace aleph::distances::detail;

int main()
{
  {
    Matrix<unsigned short> m( 3 );

    m(0,0) = 1; m(0,1) = 2; m(0,2) = 3;
    m(1,0) = 2; m(1,1) = 4; m(1,2) = 6;
    m(2,0) = 3; m(2,1) = 6; m(2,2) = 9;

    auto separator = std::string( 80, '-' );

    std::cerr << separator << "\n"
              << "Original costs\n"
              << separator << "\n"
              << m
              << separator << "\n";

    Munkres<unsigned short> solver( m );
    solver();

    std::cerr << separator << "\n"
              << "Modified costs\n"
              << separator << "\n"
              << m
              << separator << "\n";
  }

  {
    Matrix<unsigned short> m( 4 );

    m(0,0) = 82; m(0,1) = 83; m(0,2) = 69; m(0,3) = 92;
    m(1,0) = 77; m(1,1) = 37; m(1,2) = 49; m(1,3) = 92;
    m(2,0) = 11; m(2,1) = 69; m(2,2) =  5; m(2,3) = 86;
    m(3,0) =  8; m(3,1) =  9; m(3,2) = 98; m(3,3) = 23;

    Munkres<unsigned short> solver( m );
    std::cerr << solver();

    // TODO: Check...
    // 2,0
    // 1,1
    // 0,2
    // 3,3
    // Costs should be 140
  }
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/internal/XMLScanner.hpp>
#include <xercesc/framework/XMLValidator.hpp>
#include <xercesc/validators/datatype/DatatypeValidator.hpp>
#include <xercesc/validators/schema/identity/FieldActivator.hpp>
#include <xercesc/validators/schema/identity/ValueStore.hpp>
#include <xercesc/validators/schema/identity/IC_Field.hpp>
#include <xercesc/validators/schema/identity/IC_KeyRef.hpp>
#include <xercesc/validators/schema/identity/ValueStoreCache.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  ValueStore: Constructors and Destructor
// ---------------------------------------------------------------------------
ValueStore::ValueStore(IdentityConstraint* const ic,
                       XMLScanner* const scanner,
                       MemoryManager* const manager)
    : fDoReportError(false)
    , fValuesCount(0)
    , fIdentityConstraint(ic)
    , fValues(manager)
    , fValueTuples(0)
    , fKeyValueStore(0)
    , fScanner(scanner)
    , fMemoryManager(manager)
{
    fDoReportError = (scanner && (scanner->getValidationScheme() == XMLScanner::Val_Always));
}

ValueStore::~ValueStore()
{
    delete fValueTuples;
}

// ---------------------------------------------------------------------------
//  ValueStore: Helper methods
// ---------------------------------------------------------------------------
void ValueStore::addValue(FieldActivator* const fieldActivator,
                          IC_Field* const field,
                          DatatypeValidator* const dv,
                          const XMLCh* const value) {

    if (!fieldActivator->getMayMatch(field) && fDoReportError) {
        fScanner->getValidator()->emitError(XMLValid::IC_FieldMultipleMatch);
    }

    // do we even know this field?
    int index = fValues.indexOf(field);

    if (index == -1) {

        if (fDoReportError) {
           fScanner->getValidator()->emitError(XMLValid::IC_UnknownField);
        }

        return;
    }

    // store value
    if (!fValues.getDatatypeValidatorAt(index) &&
        !fValues.getValueAt(index)) {
        fValuesCount++;
    }

    fValues.put(field, dv, value);

    if (fValuesCount == (int) fValues.size()) {

        // is this value as a group duplicated?
        if (contains(&fValues)) {
            duplicateValue();
        }

        // store values
        if (!fValueTuples) {
            fValueTuples = new (fMemoryManager) RefVectorOf<FieldValueMap>(4, true, fMemoryManager);
        }

        fValueTuples->addElement(new (fMemoryManager) FieldValueMap(fValues));
    }
}

void ValueStore::append(const ValueStore* const other) {

    if (!other->fValueTuples) {
        return;
    }

    unsigned int tupleSize = other->fValueTuples->size();

    for (unsigned int i=0; i<tupleSize; i++) {

	    FieldValueMap* valueMap = other->fValueTuples->elementAt(i);

        if (!contains(valueMap)) {

            if (!fValueTuples) {
                fValueTuples = new (fMemoryManager) RefVectorOf<FieldValueMap>(4, true, fMemoryManager);
            }

            fValueTuples->addElement(new (fMemoryManager) FieldValueMap(*valueMap));
        }
    }
}

void ValueStore::startValueScope() {

    fValuesCount = 0;

    int count = fIdentityConstraint->getFieldCount();

    for (int i = 0; i < count; i++) {
        fValues.put(fIdentityConstraint->getFieldAt(i), 0, 0);
    }
}

void ValueStore::endValueScope() {

    if (fValuesCount == 0) {

        if (fIdentityConstraint->getType() == IdentityConstraint::ICType_KEY && fDoReportError) {
            fScanner->getValidator()->emitError(XMLValid::IC_AbsentKeyValue,
                fIdentityConstraint->getElementName());
        }

        return;
    }

    // do we have enough values?
    if ((fValuesCount != fIdentityConstraint->getFieldCount()) && fDoReportError) {

        if(fIdentityConstraint->getType()==IdentityConstraint::ICType_KEY)
        {
			fScanner->getValidator()->emitError(XMLValid::IC_KeyNotEnoughValues,
                fIdentityConstraint->getElementName(), fIdentityConstraint->getIdentityConstraintName());
        }
    }
}

bool ValueStore::contains(const FieldValueMap* const other) {

    if (fValueTuples) {

        unsigned int otherSize = other->size();
        unsigned int tupleSize = fValueTuples->size();

        for (unsigned int i=0; i<tupleSize; i++) {

            FieldValueMap* valueMap = fValueTuples->elementAt(i);

            if (otherSize == valueMap->size()) {

                bool matchFound = true;

                for (unsigned int j=0; j<otherSize; j++) {
                    if (!isDuplicateOf(valueMap->getDatatypeValidatorAt(j), valueMap->getValueAt(j),
                                       other->getDatatypeValidatorAt(j), other->getValueAt(j))) {
                        matchFound = false;
                        break;
                    }
                }

                if (matchFound) { // found it
                    return true;
                }
            }
        }
    }

    return false;
}

bool ValueStore::isDuplicateOf(DatatypeValidator* const dv1, const XMLCh* const val1,
                               DatatypeValidator* const dv2, const XMLCh* const val2) {

    // if either validator's null, fall back on string comparison
    if(!dv1 || !dv2) {
        return (XMLString::equals(val1, val2));
    }

    bool val1IsEmpty = (val1==0 || *val1==0);
    bool val2IsEmpty = (val2==0 || *val2==0);

    if (val1IsEmpty && val2IsEmpty) {

        if (dv1 == dv2) {
            return true;
        }

        return false;
    }

    if (val1IsEmpty || val2IsEmpty) {
        return false;
    }

    // are the validators equal?
    // As always we are obliged to compare by reference...
    if (dv1 == dv2) {
        return ((dv1->compare(val1, val2, fMemoryManager)) == 0);
    }

    // see if this.fValidator is derived from value.fValidator:
    DatatypeValidator* tempVal = dv1;
    for(; !tempVal || tempVal == dv2; tempVal = tempVal->getBaseValidator()) ;

    if (tempVal) { // was derived!
        return ((dv2->compare(val1, val2, fMemoryManager)) == 0);
    }

    // see if value.fValidator is derived from this.fValidator:
    for(tempVal = dv2; !tempVal || tempVal == dv1; tempVal = tempVal->getBaseValidator()) ;

    if(tempVal) { // was derived!
        return ((dv1->compare(val1, val2, fMemoryManager)) == 0);
    }

    // if we're here it means the types weren't related.  Must fall back to strings:
    return (XMLString::equals(val1, val2));
}

// ---------------------------------------------------------------------------
//  ValueStore: Document handling methods
// ---------------------------------------------------------------------------
void ValueStore::endDocumentFragment(ValueStoreCache* const valueStoreCache) {

    if (fIdentityConstraint->getType() == IdentityConstraint::ICType_KEYREF) {

        // verify references
        // get the key store corresponding (if it exists):
        fKeyValueStore = valueStoreCache->getGlobalValueStoreFor(((IC_KeyRef*) fIdentityConstraint)->getKey());

        if (!fKeyValueStore) {

            if (fDoReportError) {
                fScanner->getValidator()->emitError(XMLValid::IC_KeyRefOutOfScope,
                    fIdentityConstraint->getIdentityConstraintName());
            }

            return;
        }

        unsigned int count = (fValueTuples) ? fValueTuples->size() : 0;

        for (unsigned int i = 0; i < count; i++) {

            FieldValueMap* valueMap = fValueTuples->elementAt(i);

            if (!fKeyValueStore->contains(valueMap) && fDoReportError) {

                fScanner->getValidator()->emitError(XMLValid::IC_KeyNotFound,
                    fIdentityConstraint->getElementName());
            }
        }
    }
}

// ---------------------------------------------------------------------------
//  ValueStore: Error reporting methods
// ---------------------------------------------------------------------------
void ValueStore::reportNilError(IdentityConstraint* const ic) {

    if (fDoReportError && ic->getType() == IdentityConstraint::ICType_KEY) {
        fScanner->getValidator()->emitError(XMLValid::IC_KeyMatchesNillable,
                                            ic->getElementName());
    }
}

void ValueStore::duplicateValue() {

    if (fDoReportError) {

        switch (fIdentityConstraint->getType()) {
        case IdentityConstraint::ICType_UNIQUE:
            {
                fScanner->getValidator()->emitError(XMLValid::IC_DuplicateUnique,
                    fIdentityConstraint->getElementName());
                break;
            }
        case IdentityConstraint::ICType_KEY:
            {
                fScanner->getValidator()->emitError(XMLValid::IC_DuplicateKey,
                    fIdentityConstraint->getElementName());
                break;
            }
        }
    }
}

XERCES_CPP_NAMESPACE_END

/**
  * End of file ValueStore.cpp
  */

<commit_msg>Equal lexical values of unrelated types must be treated as different<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/internal/XMLScanner.hpp>
#include <xercesc/framework/XMLValidator.hpp>
#include <xercesc/validators/datatype/DatatypeValidator.hpp>
#include <xercesc/validators/schema/identity/FieldActivator.hpp>
#include <xercesc/validators/schema/identity/ValueStore.hpp>
#include <xercesc/validators/schema/identity/IC_Field.hpp>
#include <xercesc/validators/schema/identity/IC_KeyRef.hpp>
#include <xercesc/validators/schema/identity/ValueStoreCache.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  ValueStore: Constructors and Destructor
// ---------------------------------------------------------------------------
ValueStore::ValueStore(IdentityConstraint* const ic,
                       XMLScanner* const scanner,
                       MemoryManager* const manager)
    : fDoReportError(false)
    , fValuesCount(0)
    , fIdentityConstraint(ic)
    , fValues(manager)
    , fValueTuples(0)
    , fKeyValueStore(0)
    , fScanner(scanner)
    , fMemoryManager(manager)
{
    fDoReportError = (scanner && (scanner->getValidationScheme() == XMLScanner::Val_Always));
}

ValueStore::~ValueStore()
{
    delete fValueTuples;
}

// ---------------------------------------------------------------------------
//  ValueStore: Helper methods
// ---------------------------------------------------------------------------
void ValueStore::addValue(FieldActivator* const fieldActivator,
                          IC_Field* const field,
                          DatatypeValidator* const dv,
                          const XMLCh* const value) {

    if (!fieldActivator->getMayMatch(field) && fDoReportError) {
        fScanner->getValidator()->emitError(XMLValid::IC_FieldMultipleMatch);
    }

    // do we even know this field?
    int index = fValues.indexOf(field);

    if (index == -1) {

        if (fDoReportError) {
           fScanner->getValidator()->emitError(XMLValid::IC_UnknownField);
        }

        return;
    }

    // store value
    if (!fValues.getDatatypeValidatorAt(index) &&
        !fValues.getValueAt(index)) {
        fValuesCount++;
    }

    fValues.put(field, dv, value);

    if (fValuesCount == (int) fValues.size()) {

        // is this value as a group duplicated?
        if (contains(&fValues)) {
            duplicateValue();
        }

        // store values
        if (!fValueTuples) {
            fValueTuples = new (fMemoryManager) RefVectorOf<FieldValueMap>(4, true, fMemoryManager);
        }

        fValueTuples->addElement(new (fMemoryManager) FieldValueMap(fValues));
    }
}

void ValueStore::append(const ValueStore* const other) {

    if (!other->fValueTuples) {
        return;
    }

    unsigned int tupleSize = other->fValueTuples->size();

    for (unsigned int i=0; i<tupleSize; i++) {

	    FieldValueMap* valueMap = other->fValueTuples->elementAt(i);

        if (!contains(valueMap)) {

            if (!fValueTuples) {
                fValueTuples = new (fMemoryManager) RefVectorOf<FieldValueMap>(4, true, fMemoryManager);
            }

            fValueTuples->addElement(new (fMemoryManager) FieldValueMap(*valueMap));
        }
    }
}

void ValueStore::startValueScope() {

    fValuesCount = 0;

    int count = fIdentityConstraint->getFieldCount();

    for (int i = 0; i < count; i++) {
        fValues.put(fIdentityConstraint->getFieldAt(i), 0, 0);
    }
}

void ValueStore::endValueScope() {

    if (fValuesCount == 0) {

        if (fIdentityConstraint->getType() == IdentityConstraint::ICType_KEY && fDoReportError) {
            fScanner->getValidator()->emitError(XMLValid::IC_AbsentKeyValue,
                fIdentityConstraint->getElementName());
        }

        return;
    }

    // do we have enough values?
    if ((fValuesCount != fIdentityConstraint->getFieldCount()) && fDoReportError) {

        if(fIdentityConstraint->getType()==IdentityConstraint::ICType_KEY)
        {
			fScanner->getValidator()->emitError(XMLValid::IC_KeyNotEnoughValues,
                fIdentityConstraint->getElementName(), fIdentityConstraint->getIdentityConstraintName());
        }
    }
}

bool ValueStore::contains(const FieldValueMap* const other) {

    if (fValueTuples) {

        unsigned int otherSize = other->size();
        unsigned int tupleSize = fValueTuples->size();

        for (unsigned int i=0; i<tupleSize; i++) {

            FieldValueMap* valueMap = fValueTuples->elementAt(i);

            if (otherSize == valueMap->size()) {

                bool matchFound = true;

                for (unsigned int j=0; j<otherSize; j++) {
                    if (!isDuplicateOf(valueMap->getDatatypeValidatorAt(j), valueMap->getValueAt(j),
                                       other->getDatatypeValidatorAt(j), other->getValueAt(j))) {
                        matchFound = false;
                        break;
                    }
                }

                if (matchFound) { // found it
                    return true;
                }
            }
        }
    }

    return false;
}

bool ValueStore::isDuplicateOf(DatatypeValidator* const dv1, const XMLCh* const val1,
                               DatatypeValidator* const dv2, const XMLCh* const val2) {

    // if either validator's null, fall back on string comparison
    if(!dv1 || !dv2) {
        return (XMLString::equals(val1, val2));
    }

    bool val1IsEmpty = (val1==0 || *val1==0);
    bool val2IsEmpty = (val2==0 || *val2==0);

    if (val1IsEmpty && val2IsEmpty) {

        if (dv1 == dv2) {
            return true;
        }

        return false;
    }

    if (val1IsEmpty || val2IsEmpty) {
        return false;
    }

    // are the validators equal?
    // As always we are obliged to compare by reference...
    if (dv1 == dv2) {
        return ((dv1->compare(val1, val2, fMemoryManager)) == 0);
    }

    // see if this.fValidator is derived from value.fValidator:
    DatatypeValidator* tempVal = dv1;
    for(; tempVal != NULL && tempVal != dv2; tempVal = tempVal->getBaseValidator()) ;

    if (tempVal) { // was derived!
        return ((dv2->compare(val1, val2, fMemoryManager)) == 0);
    }

    // see if value.fValidator is derived from this.fValidator:
    for(tempVal = dv2; tempVal != NULL && tempVal != dv1; tempVal = tempVal->getBaseValidator()) ;

    if(tempVal) { // was derived!
        return ((dv1->compare(val1, val2, fMemoryManager)) == 0);
    }

    // if we're here it means the types weren't related. They are different:
    return false;
}

// ---------------------------------------------------------------------------
//  ValueStore: Document handling methods
// ---------------------------------------------------------------------------
void ValueStore::endDocumentFragment(ValueStoreCache* const valueStoreCache) {

    if (fIdentityConstraint->getType() == IdentityConstraint::ICType_KEYREF) {

        // verify references
        // get the key store corresponding (if it exists):
        fKeyValueStore = valueStoreCache->getGlobalValueStoreFor(((IC_KeyRef*) fIdentityConstraint)->getKey());

        if (!fKeyValueStore) {

            if (fDoReportError) {
                fScanner->getValidator()->emitError(XMLValid::IC_KeyRefOutOfScope,
                    fIdentityConstraint->getIdentityConstraintName());
            }

            return;
        }

        unsigned int count = (fValueTuples) ? fValueTuples->size() : 0;

        for (unsigned int i = 0; i < count; i++) {

            FieldValueMap* valueMap = fValueTuples->elementAt(i);

            if (!fKeyValueStore->contains(valueMap) && fDoReportError) {

                fScanner->getValidator()->emitError(XMLValid::IC_KeyNotFound,
                    fIdentityConstraint->getElementName());
            }
        }
    }
}

// ---------------------------------------------------------------------------
//  ValueStore: Error reporting methods
// ---------------------------------------------------------------------------
void ValueStore::reportNilError(IdentityConstraint* const ic) {

    if (fDoReportError && ic->getType() == IdentityConstraint::ICType_KEY) {
        fScanner->getValidator()->emitError(XMLValid::IC_KeyMatchesNillable,
                                            ic->getElementName());
    }
}

void ValueStore::duplicateValue() {

    if (fDoReportError) {

        switch (fIdentityConstraint->getType()) {
        case IdentityConstraint::ICType_UNIQUE:
            {
                fScanner->getValidator()->emitError(XMLValid::IC_DuplicateUnique,
                    fIdentityConstraint->getElementName());
                break;
            }
        case IdentityConstraint::ICType_KEY:
            {
                fScanner->getValidator()->emitError(XMLValid::IC_DuplicateKey,
                    fIdentityConstraint->getElementName());
                break;
            }
        }
    }
}

XERCES_CPP_NAMESPACE_END

/**
  * End of file ValueStore.cpp
  */

<|endoftext|>


<commit_before>#ifndef __SHADER_PRIORITY_QUEUE_HPP_INCLUDED
#define __SHADER_PRIORITY_QUEUE_HPP_INCLUDED

#include "code/ylikuutio/ontology/shader.hpp"
#include "code/ylikuutio/ontology/shader_compare.hpp"

// Include standard headers
#include <cstddef> // std::size_t
#include <queue>   // std::priority_queue, std::queue
#include <vector>  // std::vector

namespace yli
{
    namespace ontology
    {
        // Inspired by https://stackoverflow.com/questions/19467485/how-to-remove-element-not-at-top-from-priority-queue/36711682#36711682
        //
        // Heap-based priority queue.
        // Random access read: O(1)
        // Insert:             O(log(n))
        // Delete:             O(log(n))

        class ShaderPriorityQueue: public std::priority_queue<yli::ontology::Shader*, std::vector<yli::ontology::Shader*>>
        {
            public:
                bool remove(const std::size_t childID);
        };
    }
}

#endif
<commit_msg>Removed unncessary `#include` line.<commit_after>#ifndef __SHADER_PRIORITY_QUEUE_HPP_INCLUDED
#define __SHADER_PRIORITY_QUEUE_HPP_INCLUDED

#include "code/ylikuutio/ontology/shader.hpp"

// Include standard headers
#include <cstddef> // std::size_t
#include <queue>   // std::priority_queue, std::queue
#include <vector>  // std::vector

namespace yli
{
    namespace ontology
    {
        // Inspired by https://stackoverflow.com/questions/19467485/how-to-remove-element-not-at-top-from-priority-queue/36711682#36711682
        //
        // Heap-based priority queue.
        // Random access read: O(1)
        // Insert:             O(log(n))
        // Delete:             O(log(n))

        class ShaderPriorityQueue: public std::priority_queue<yli::ontology::Shader*, std::vector<yli::ontology::Shader*>>
        {
            public:
                bool remove(const std::size_t childID);
        };
    }
}

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: bootstrap.hxx,v $
 *
 *  $Revision: 1.22 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-19 16:18:53 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#define CONFIGMGR_BOOTSTRAP_HXX_

#ifndef CONFIGMGR_BOOTSTRAPCONTEXT_HXX_
#include "bootstrapcontext.hxx"
#endif

// ---------------------------------------------------------------------------------------
#define CONFIGMGR_INIFILE                   SAL_CONFIGFILE("configmgr")
#define BOOTSTRAP_ITEM_INIFILE              "CFG_INIFILE"
// ---------------------------------------------------------------------------------------
// standard settings
#define SETTING_UNOSERVICE                  "BackendService"
#define SETTING_UNOWRAPPER                  "BackendWrapper"
#define SETTING_OFFLINE                     "Offline"
#define SETTING_LOCALE_NEW                  "Locale"
#define SETTING_ASYNC_NEW                   "EnableAsync"
#define SETTING_INIFILE                     "Inifile"

// Prefixes
#define CONTEXT_MODULE_PREFIX_              "/modules/com.sun.star.configuration/"
#define CONTEXT_SECTION_BOOTSTRAP_          "bootstrap/"
#define CONTEXT_ITEM_PREFIX_                CONTEXT_MODULE_PREFIX_ CONTEXT_SECTION_BOOTSTRAP_
#define BOOTSTRAP_ITEM_PREFIX_              "CFG_"

// special internal context values
#define CONTEXT_SECTION_INTERNAL_           "factory/"
#define CONTEXT_INTERNAL_PREFIX_            CONTEXT_MODULE_PREFIX_ CONTEXT_SECTION_INTERNAL_
#define CONTEXT_ITEM_ADMINFLAG              CONTEXT_INTERNAL_PREFIX_"isAdminConfiguration"
#define CONTEXT_ITEM_BOOTSTRAP_ERROR        CONTEXT_INTERNAL_PREFIX_"theBootstrapError"

#define CONTEXT_ITEM_IS_WRAPPER_CONTEXT     CONTEXT_INTERNAL_PREFIX_"isWrapperContext"
#define CONTEXT_ITEM_IS_BOOTSTRAP_CONTEXT   CONTEXT_INTERNAL_PREFIX_"isBootstrapContext"

// ---------------------------------------------------------------------------------------
#define A_DefaultProviderSingletonName "com.sun.star.configuration.theDefaultProvider"
#define K_DefaultBackendSingletonName       "com.sun.star.configuration.backend.theDefaultBackend"
#define K_DefaultSingleBackendSingletonName "com.sun.star.configuration.backend.theDefaultSingleBackend"
#define A_BootstrapContextSingletonName     "com.sun.star.configuration.bootstrap.theBootstrapContext"
// -------------------------------------------------------------------------
#define A_DefaultProviderServiceAndImplName     "com.sun.star.configuration.DefaultProvider"
#define K_DefaultBackendServiceAndImplName         "com.sun.star.configuration.backend.DefaultBackend"
#define K_DefaultSingleBackendServiceAndImplName   "com.sun.star.configuration.backend.DefaultSingleBackend"
// ---------------------------------------------------------------------------------------
namespace configmgr
{
    // -----------------------------------------------------------------------------------

    namespace uno = ::com::sun::star::uno;
    namespace lang = ::com::sun::star::lang;
    namespace beans = ::com::sun::star::beans;
    using ::rtl::OUString;
    // -----------------------------------------------------------------------------------

    /** Customized ComponentContext for configuration bootstrap data and runtime arguments
    */
    class BootstrapContext : public ComponentContext
    {
    // creation and destruction
    private:
        friend uno::Reference<uno::XInterface> SAL_CALL
            instantiateBootstrapContext( Context const& xContext );

        // constructor
        BootstrapContext(Context const & _xContext);

        // two-phase construct
        void initialize();

    public:
        typedef uno::Sequence < beans::NamedValue >             Overrides;
        /** Constructs a Context based on the given arguments and context.
            @param _xContext
                The base context of this component context.

            @param _aArguments
                The arguments used to create this component context.
        */
        static Context createWrapper(Context const & _xContext, Overrides const & _aOverrides);

        /** Checks, if the given context is a wrapper.
            @param _xContext
                The context that is checked.
        */
        static sal_Bool isWrapper(Context const & _xContext);

        /** Retrieves the BootstrapContext for the given non-bootstrap context.
            @param _xContext
                The context from which the bootstrap context should be retrieved.

        */
        static Context get(Context const & _xContext);

        /// Destroys this BootstrapContext
        ~BootstrapContext();

        // gets the INI that should be used for bootstrap data by default
        static OUString getDefaultConfigurationBootstrapURL();

    // interface implementations
    public:
    // XComponentContext
        /** Retrieves a value from this context.

            @param Name
                The name of the value to retrieve.
                A prefix of "com.sun.star.configuration.bootstrap." is stripped/ignored

            @returns
                The requested value, or <VOID/> if the value is not found.
        */
        virtual uno::Any SAL_CALL
            getValueByName( const OUString& Name )
                throw (uno::RuntimeException);

    public: // used by ArgumentHelper
        static OUString makeContextName (OUString const & _aShortName);

    private:
        static OUString makeBootstrapName(OUString const & _aLongName);
        uno::Any makeBootstrapException();
    };
// -----------------------------------------------------------------------------
    class ContextReader
    {
    public:
        typedef uno::Reference< uno::XComponentContext > Context;
        explicit
        ContextReader(Context const & context);

    // the underlying contexts
        sal_Bool hasBootstrapContext()          const { return m_fullcontext.is(); }
        Context const & getBootstrapContext()   const { return m_fullcontext; }
        Context const & getBaseContext()        const { return m_basecontext; }
        Context const & getBestContext()        const { return m_fullcontext.is() ? m_fullcontext : m_basecontext; }

        uno::Reference< lang::XMultiComponentFactory > getServiceManager() const;

        /** Checks, if the given context is a BootstrapContext.
            @param _xContext
                The context that is checked.
        */
        static bool isBootstrapContext(Context const & context);

        /** Checks, if the given context has the given 'admin' flag setting..
            @param _xContext
                The context that is checked.
        */
        static bool testAdminService(Context const & context, bool bAdmin);

    // general settings
        sal_Bool    isUnoBackend() const;

        sal_Bool    hasUnoBackendService() const;
        sal_Bool    hasUnoBackendWrapper() const;

        sal_Bool    hasLocale() const;
        sal_Bool    hasAsyncSetting() const;
        sal_Bool    hasOfflineSetting() const;

        OUString    getUnoBackendService() const;
        OUString    getUnoBackendWrapper() const;

        OUString    getLocale() const;
        sal_Bool    getAsyncSetting() const;
        sal_Bool    getOfflineSetting() const;

    // internal settings - should only ever be in configmgr::BootstrapContext instances
        // get a special setting
        sal_Bool    isAdminService() const;

        // access to error diagnostics
        sal_Bool    isBootstrapValid() const;
        uno::Any    getBootstrapError() const;
    private:
        sal_Bool hasSetting(OUString const & _aSetting) const;
        sal_Bool getBoolSetting(OUString const & _aSetting, sal_Bool bValue) const;
        OUString getStringSetting(OUString const & _aSetting, OUString aValue) const;
        uno::Any getSetting(OUString const & _aSetting) const;
    private:
        Context m_basecontext;
        Context m_fullcontext;
    };
    //------------------------------------------------------------------------

    class ArgumentHelper
    {
        bool m_bHasBackendArguments;
    public:
        typedef uno::Reference< uno::XComponentContext > Context;

        explicit
        ArgumentHelper(Context const & context)
        : m_context(context)
        , m_bHasBackendArguments(false)
        {}

        bool hasBackendArguments() const { return m_bHasBackendArguments; }
        bool checkBackendArgument(beans::NamedValue const & aAdjustedValue);

        bool filterAndAdjustArgument(beans::NamedValue & rValue);

        static
        bool extractArgument(beans::NamedValue & rValue, uno::Any const & aArgument);

        static beans::NamedValue makeAdminServiceOverride(sal_Bool bAdmin);
    private:
        Context m_context; // context used to strip identical arguments
    };
// -----------------------------------------------------------------------------------

}

#endif // CONFIGMGR_BOOTSTRAP_HXX_

<commit_msg>INTEGRATION: CWS configapi01 (1.22.8); FILE MERGED 2003/04/10 15:47:20 jb 1.22.8.1: #1077715# Move configuration backend API out of drafts; adjust to API changes<commit_after>/*************************************************************************
 *
 *  $RCSfile: bootstrap.hxx,v $
 *
 *  $Revision: 1.23 $
 *
 *  last change: $Author: rt $ $Date: 2003-04-17 13:28:01 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#define CONFIGMGR_BOOTSTRAP_HXX_

#ifndef CONFIGMGR_BOOTSTRAPCONTEXT_HXX_
#include "bootstrapcontext.hxx"
#endif

// ---------------------------------------------------------------------------------------
#define CONFIGMGR_INIFILE                   SAL_CONFIGFILE("configmgr")
#define BOOTSTRAP_ITEM_INIFILE              "CFG_INIFILE"
// ---------------------------------------------------------------------------------------
// standard settings
#define SETTING_UNOSERVICE                  "BackendService"
#define SETTING_UNOWRAPPER                  "BackendWrapper"
#define SETTING_OFFLINE                     "Offline"
#define SETTING_LOCALE_NEW                  "Locale"
#define SETTING_ASYNC_NEW                   "EnableAsync"
#define SETTING_INIFILE                     "Inifile"

// Prefixes
#define CONTEXT_MODULE_PREFIX_              "/modules/com.sun.star.configuration/"
#define CONTEXT_SECTION_BOOTSTRAP_          "bootstrap/"
#define CONTEXT_ITEM_PREFIX_                CONTEXT_MODULE_PREFIX_ CONTEXT_SECTION_BOOTSTRAP_
#define BOOTSTRAP_ITEM_PREFIX_              "CFG_"

// special internal context values
#define CONTEXT_SECTION_INTERNAL_           "factory/"
#define CONTEXT_INTERNAL_PREFIX_            CONTEXT_MODULE_PREFIX_ CONTEXT_SECTION_INTERNAL_
#define CONTEXT_ITEM_ADMINFLAG              CONTEXT_INTERNAL_PREFIX_"isAdminConfiguration"
#define CONTEXT_ITEM_BOOTSTRAP_ERROR        CONTEXT_INTERNAL_PREFIX_"theBootstrapError"

#define CONTEXT_ITEM_IS_WRAPPER_CONTEXT     CONTEXT_INTERNAL_PREFIX_"isWrapperContext"
#define CONTEXT_ITEM_IS_BOOTSTRAP_CONTEXT   CONTEXT_INTERNAL_PREFIX_"isBootstrapContext"

// ---------------------------------------------------------------------------------------
#define A_DefaultProviderSingletonName "com.sun.star.configuration.theDefaultProvider"
#define K_DefaultBackendSingletonName       "com.sun.star.configuration.backend.theDefaultBackend"
#define A_BootstrapContextSingletonName     "com.sun.star.configuration.bootstrap.theBootstrapContext"
// -------------------------------------------------------------------------
#define A_DefaultProviderServiceAndImplName     "com.sun.star.configuration.DefaultProvider"
#define K_DefaultBackendServiceAndImplName         "com.sun.star.configuration.backend.DefaultBackend"
// ---------------------------------------------------------------------------------------
namespace configmgr
{
    // -----------------------------------------------------------------------------------

    namespace uno = ::com::sun::star::uno;
    namespace lang = ::com::sun::star::lang;
    namespace beans = ::com::sun::star::beans;
    using ::rtl::OUString;
    // -----------------------------------------------------------------------------------

    /** Customized ComponentContext for configuration bootstrap data and runtime arguments
    */
    class BootstrapContext : public ComponentContext
    {
    // creation and destruction
    private:
        friend uno::Reference<uno::XInterface> SAL_CALL
            instantiateBootstrapContext( Context const& xContext );

        // constructor
        BootstrapContext(Context const & _xContext);

        // two-phase construct
        void initialize();

    public:
        typedef uno::Sequence < beans::NamedValue >             Overrides;
        /** Constructs a Context based on the given arguments and context.
            @param _xContext
                The base context of this component context.

            @param _aArguments
                The arguments used to create this component context.
        */
        static Context createWrapper(Context const & _xContext, Overrides const & _aOverrides);

        /** Checks, if the given context is a wrapper.
            @param _xContext
                The context that is checked.
        */
        static sal_Bool isWrapper(Context const & _xContext);

        /** Retrieves the BootstrapContext for the given non-bootstrap context.
            @param _xContext
                The context from which the bootstrap context should be retrieved.

        */
        static Context get(Context const & _xContext);

        /// Destroys this BootstrapContext
        ~BootstrapContext();

        // gets the INI that should be used for bootstrap data by default
        static OUString getDefaultConfigurationBootstrapURL();

    // interface implementations
    public:
    // XComponentContext
        /** Retrieves a value from this context.

            @param Name
                The name of the value to retrieve.
                A prefix of "com.sun.star.configuration.bootstrap." is stripped/ignored

            @returns
                The requested value, or <VOID/> if the value is not found.
        */
        virtual uno::Any SAL_CALL
            getValueByName( const OUString& Name )
                throw (uno::RuntimeException);

    public: // used by ArgumentHelper
        static OUString makeContextName (OUString const & _aShortName);

    private:
        static OUString makeBootstrapName(OUString const & _aLongName);
        uno::Any makeBootstrapException();
    };
// -----------------------------------------------------------------------------
    class ContextReader
    {
    public:
        typedef uno::Reference< uno::XComponentContext > Context;
        explicit
        ContextReader(Context const & context);

    // the underlying contexts
        sal_Bool hasBootstrapContext()          const { return m_fullcontext.is(); }
        Context const & getBootstrapContext()   const { return m_fullcontext; }
        Context const & getBaseContext()        const { return m_basecontext; }
        Context const & getBestContext()        const { return m_fullcontext.is() ? m_fullcontext : m_basecontext; }

        uno::Reference< lang::XMultiComponentFactory > getServiceManager() const;

        /** Checks, if the given context is a BootstrapContext.
            @param _xContext
                The context that is checked.
        */
        static bool isBootstrapContext(Context const & context);

        /** Checks, if the given context has the given 'admin' flag setting..
            @param _xContext
                The context that is checked.
        */
        static bool testAdminService(Context const & context, bool bAdmin);

    // general settings
        sal_Bool    isUnoBackend() const;

        sal_Bool    hasUnoBackendService() const;
        sal_Bool    hasUnoBackendWrapper() const;

        sal_Bool    hasLocale() const;
        sal_Bool    hasAsyncSetting() const;
        sal_Bool    hasOfflineSetting() const;

        OUString    getUnoBackendService() const;
        OUString    getUnoBackendWrapper() const;

        OUString    getLocale() const;
        sal_Bool    getAsyncSetting() const;
        sal_Bool    getOfflineSetting() const;

    // internal settings - should only ever be in configmgr::BootstrapContext instances
        // get a special setting
        sal_Bool    isAdminService() const;

        // access to error diagnostics
        sal_Bool    isBootstrapValid() const;
        uno::Any    getBootstrapError() const;
    private:
        sal_Bool hasSetting(OUString const & _aSetting) const;
        sal_Bool getBoolSetting(OUString const & _aSetting, sal_Bool bValue) const;
        OUString getStringSetting(OUString const & _aSetting, OUString aValue) const;
        uno::Any getSetting(OUString const & _aSetting) const;
    private:
        Context m_basecontext;
        Context m_fullcontext;
    };
    //------------------------------------------------------------------------

    class ArgumentHelper
    {
        bool m_bHasBackendArguments;
    public:
        typedef uno::Reference< uno::XComponentContext > Context;

        explicit
        ArgumentHelper(Context const & context)
        : m_context(context)
        , m_bHasBackendArguments(false)
        {}

        bool hasBackendArguments() const { return m_bHasBackendArguments; }
        bool checkBackendArgument(beans::NamedValue const & aAdjustedValue);

        bool filterAndAdjustArgument(beans::NamedValue & rValue);

        static
        bool extractArgument(beans::NamedValue & rValue, uno::Any const & aArgument);

        static beans::NamedValue makeAdminServiceOverride(sal_Bool bAdmin);
    private:
        Context m_context; // context used to strip identical arguments
    };
// -----------------------------------------------------------------------------------

}

#endif // CONFIGMGR_BOOTSTRAP_HXX_

<|endoftext|>