<commit_before>/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkCanvas.h"
#include "SkDocument.h"
#include "SkFontMgr.h"
#include "SkGradientShader.h"
#include "SkPaint.h"
#include "SkStream.h"
#include "SkString.h"
#include "SkTextBlob.h"
#include "SkTypeface.h"

#include <hb.h>
#include <hb-ot.h>

#include <cassert>
#include <iostream>
#include <map>
#include <string>

struct BaseOption {
  std::string selector;
  std::string description;
  virtual void set(std::string _value) = 0;
  virtual std::string valueToString() = 0;

  BaseOption(std::string _selector, std::string _description) :
    selector(_selector),
    description(_description) {}

  virtual ~BaseOption() {}
};

template <class T> struct Option : BaseOption {
  T value;
  Option(std::string selector, std::string description, T defaultValue) :
    BaseOption(selector, description),
    value(defaultValue) {}
};

struct DoubleOption : Option<double> {
  virtual void set(std::string _value) {
    value = atof(_value.c_str());
  }
  virtual std::string valueToString() {
    return std::to_string(value);
  }
  DoubleOption(std::string selector, std::string description, double defaultValue) :
    Option<double>(selector, description, defaultValue) {}
};

struct SkStringOption : Option<SkString> {
  virtual void set(std::string _value) {
    value = _value.c_str();
  }
  virtual std::string valueToString() {
    return value.c_str();
  }
  SkStringOption(std::string selector, std::string description, SkString defaultValue) :
    Option<SkString>(selector, description, defaultValue) {}
};

struct StdStringOption : Option<std::string> {
  virtual void set(std::string _value) {
    value = _value;
  }
  virtual std::string valueToString() {
    return value;
  }
  StdStringOption(std::string selector, std::string description, std::string defaultValue) :
    Option<std::string>(selector, description, defaultValue) {}
};

struct Config {
  DoubleOption *page_width = new DoubleOption("-w", "Page width", 600.0f);
  DoubleOption *page_height = new DoubleOption("-h", "Page height", 800.0f);
  SkStringOption *title = new SkStringOption("-t", "PDF title", SkString("---"));
  SkStringOption *author = new SkStringOption("-a", "PDF author", SkString("---"));
  SkStringOption *subject = new SkStringOption("-k", "PDF subject", SkString("---"));
  SkStringOption *keywords = new SkStringOption("-c", "PDF keywords", SkString("---"));
  SkStringOption *creator = new SkStringOption("-t", "PDF creator", SkString("---"));
  StdStringOption *font_file = new StdStringOption("-f", ".ttf font file", "fonts/DejaVuSans.ttf");
  DoubleOption *font_size = new DoubleOption("-z", "Font size", 8.0f);
  DoubleOption *left_margin = new DoubleOption("-m", "Left margin", 20.0f);
  DoubleOption *line_spacing_ratio = new DoubleOption("-h", "Line spacing ratio", 1.5f);
  StdStringOption *output_file_name = new StdStringOption("-o", ".pdf output file name", "out-skiahf.pdf");

  std::map<std::string, BaseOption*> options = {
    { page_width->selector, page_width },
    { page_height->selector, page_height },
    { title->selector, title },
    { author->selector, author },
    { subject->selector, subject },
    { keywords->selector, keywords },
    { creator->selector, creator },
    { font_file->selector, font_file },
    { font_size->selector, font_size },
    { left_margin->selector, left_margin },
    { line_spacing_ratio->selector, line_spacing_ratio },
    { output_file_name->selector, output_file_name },
  };

  Config(int argc, char **argv) {
    for (int i = 1; i < argc; i++) {
      std::string option_selector(argv[i]);
      auto it = options.find(option_selector);
      if (it != options.end()) {
        if (i >= argc) {
          break;
        }
        const char *option_value = argv[i + 1];
        it->second->set(option_value);
        i++;
      } else {
        printf("Ignoring unrecognized option: %s.\n", argv[i]);
        printf("Usage: %s {option value}\n", argv[0]);
        printf("\tTakes text from stdin and produces pdf file.\n");
        printf("Supported options:\n");
        for (auto it = options.begin(); it != options.end(); ++it) {
          printf("\t%s\t%s (%s)\n", it->first.c_str(),
            it->second->description.c_str(),
            it->second->valueToString().c_str());
        }
        exit(-1);
      }
    }
  } // end of Config::Config
};

const double FONT_SIZE_SCALE = 64.0f;

struct Face {
  struct HBFDel { void operator()(hb_face_t* f) { hb_face_destroy(f); } };
  std::unique_ptr<hb_face_t, HBFDel> fHarfBuzzFace;
  sk_sp<SkTypeface> fSkiaTypeface;

  Face(const char* path, int index) {
    // fairly portable mmap impl
    auto data = SkData::MakeFromFileName(path);
    assert(data);
    if (!data) { return; }
    fSkiaTypeface.reset(
      SkTypeface::CreateFromStream(
        new SkMemoryStream(data), index));
    assert(fSkiaTypeface);
    if (!fSkiaTypeface) { return; }
    auto destroy = [](void *d) { static_cast<SkData*>(d)->unref(); };
    const char* bytes = (const char*)data->data();
    unsigned int size = (unsigned int)data->size();
    hb_blob_t* blob = hb_blob_create(bytes,
                                     size,
                                     HB_MEMORY_MODE_READONLY,
                                     data.release(),
                                     destroy);
    assert(blob);
    hb_blob_make_immutable(blob);
    hb_face_t* face = hb_face_create(blob, (unsigned)index);
    hb_blob_destroy(blob);
    assert(face);
    if (!face) {
        fSkiaTypeface.reset();
        return;
    }
    hb_face_set_index(face, (unsigned)index);
    hb_face_set_upem(face, fSkiaTypeface->getUnitsPerEm());
    fHarfBuzzFace.reset(face);
  }
};

class Placement {
 public:
  Placement(Config &_config, SkWStream* outputStream) : config(_config) {
    face = new Face(config.font_file->value.c_str(), 0 /* index */);
    hb_font = hb_font_create(face->fHarfBuzzFace.get());

    hb_font_set_scale(hb_font,
        FONT_SIZE_SCALE * config.font_size->value,
        FONT_SIZE_SCALE * config.font_size->value);
    hb_ot_font_set_funcs(hb_font);

    SkDocument::PDFMetadata pdf_info;
    pdf_info.fTitle = config.title->value;
    pdf_info.fAuthor = config.author->value;
    pdf_info.fSubject = config.subject->value;
    pdf_info.fKeywords = config.keywords->value;
    pdf_info.fCreator = config.creator->value;
    SkTime::DateTime now;
    SkTime::GetDateTime(&now);
    pdf_info.fCreation.fEnabled = true;
    pdf_info.fCreation.fDateTime = now;
    pdf_info.fModified.fEnabled = true;
    pdf_info.fModified.fDateTime = now;
    pdfDocument = SkDocument::MakePDF(outputStream, SK_ScalarDefaultRasterDPI,
                                      pdf_info, nullptr, true);
    assert(pdfDocument);

    white_paint.setColor(SK_ColorWHITE);

    glyph_paint.setFlags(
        SkPaint::kAntiAlias_Flag |
        SkPaint::kSubpixelText_Flag);  // ... avoid waggly text when rotating.
    glyph_paint.setColor(SK_ColorBLACK);
    glyph_paint.setTextSize(config.font_size->value);
    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
    glyph_paint.setTypeface(face->fSkiaTypeface);
    glyph_paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);

    NewPage();
  } // end of Placement

  ~Placement() {
    delete face;
    hb_font_destroy (hb_font);
  }

  void WriteLine(const char *text) {
    /* Create hb-buffer and populate. */
    hb_buffer_t *hb_buffer = hb_buffer_create ();
    hb_buffer_add_utf8 (hb_buffer, text, -1, 0, -1);
    hb_buffer_guess_segment_properties (hb_buffer);

    /* Shape it! */
    hb_shape (hb_font, hb_buffer, NULL, 0);

    DrawGlyphs(hb_buffer);

    hb_buffer_destroy (hb_buffer);

    // Advance to the next line.
    current_y += config.line_spacing_ratio->value * config.font_size->value;
    if (current_y > config.page_height->value) {
      pdfDocument->endPage();
      NewPage();
    }
  }

  bool Close() {
    return pdfDocument->close();
  }

private:
  Config config;

  Face *face;

  hb_font_t *hb_font;

  sk_sp<SkDocument> pdfDocument;

  SkCanvas* pageCanvas;

  SkPaint white_paint;
  SkPaint glyph_paint;

  double current_x;
  double current_y;

  void NewPage() {
    pageCanvas = pdfDocument->beginPage(config.page_width->value, config.page_height->value);

    pageCanvas->drawPaint(white_paint);

    current_x = config.left_margin->value;
    current_y = config.line_spacing_ratio->value * config.font_size->value;
  }

  bool DrawGlyphs(hb_buffer_t *hb_buffer) {
    SkTextBlobBuilder textBlobBuilder;
    unsigned len = hb_buffer_get_length (hb_buffer);
    if (len == 0) {
      return true;
    }
    hb_glyph_info_t *info = hb_buffer_get_glyph_infos (hb_buffer, NULL);
    hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (hb_buffer, NULL);
    auto runBuffer = textBlobBuilder.allocRunPos(glyph_paint, len);

    double x = 0;
    double y = 0;
    for (unsigned int i = 0; i < len; i++)
    {
      runBuffer.glyphs[i] = info[i].codepoint;
      reinterpret_cast<SkPoint*>(runBuffer.pos)[i] = SkPoint::Make(
        x + pos[i].x_offset / FONT_SIZE_SCALE,
        y - pos[i].y_offset / FONT_SIZE_SCALE);
      x += pos[i].x_advance / FONT_SIZE_SCALE;
      y += pos[i].y_advance / FONT_SIZE_SCALE;
    }

    pageCanvas->drawTextBlob(textBlobBuilder.build(), current_x, current_y, glyph_paint);
    return true;
  } // end of DrawGlyphs
}; // end of Placement class

int main(int argc, char** argv) {
    Config config(argc, argv);

    Placement placement(config, new SkFILEWStream(config.output_file_name->value.c_str()));
    for (std::string line; std::getline(std::cin, line);) {
      placement.WriteLine(line.c_str());
    }
    placement.Close();

    return 0;
}
<commit_msg>tools/using_skia_and_harfbuzz: minor cleanup<commit_after>/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This sample progam demonstrates how to use Skia and HarfBuzz to
// produce a PDF file from UTF-8 text in stdin.

#include <cassert>
#include <iostream>
#include <map>
#include <string>

#include <hb-ot.h>

#include "SkCanvas.h"
#include "SkDocument.h"
#include "SkStream.h"
#include "SkTextBlob.h"
#include "SkTypeface.h"

struct BaseOption {
  std::string selector;
  std::string description;
  virtual void set(std::string _value) = 0;
  virtual std::string valueToString() = 0;

  BaseOption(std::string _selector, std::string _description) :
    selector(_selector),
    description(_description) {}

  virtual ~BaseOption() {}
};

template <class T> struct Option : BaseOption {
  T value;
  Option(std::string selector, std::string description, T defaultValue) :
    BaseOption(selector, description),
    value(defaultValue) {}
};

struct DoubleOption : Option<double> {
  virtual void set(std::string _value) {
    value = atof(_value.c_str());
  }
  virtual std::string valueToString() {
    return std::to_string(value);
  }
  DoubleOption(std::string selector, std::string description, double defaultValue) :
    Option<double>(selector, description, defaultValue) {}
};

struct SkStringOption : Option<SkString> {
  virtual void set(std::string _value) {
    value = _value.c_str();
  }
  virtual std::string valueToString() {
    return value.c_str();
  }
  SkStringOption(std::string selector, std::string description, SkString defaultValue) :
    Option<SkString>(selector, description, defaultValue) {}
};

struct StdStringOption : Option<std::string> {
  virtual void set(std::string _value) {
    value = _value;
  }
  virtual std::string valueToString() {
    return value;
  }
  StdStringOption(std::string selector, std::string description, std::string defaultValue) :
    Option<std::string>(selector, description, defaultValue) {}
};

struct Config {
  DoubleOption *page_width = new DoubleOption("-w", "Page width", 600.0f);
  DoubleOption *page_height = new DoubleOption("-h", "Page height", 800.0f);
  SkStringOption *title = new SkStringOption("-t", "PDF title", SkString("---"));
  SkStringOption *author = new SkStringOption("-a", "PDF author", SkString("---"));
  SkStringOption *subject = new SkStringOption("-k", "PDF subject", SkString("---"));
  SkStringOption *keywords = new SkStringOption("-c", "PDF keywords", SkString("---"));
  SkStringOption *creator = new SkStringOption("-t", "PDF creator", SkString("---"));
  StdStringOption *font_file = new StdStringOption("-f", ".ttf font file", "fonts/DejaVuSans.ttf");
  DoubleOption *font_size = new DoubleOption("-z", "Font size", 8.0f);
  DoubleOption *left_margin = new DoubleOption("-m", "Left margin", 20.0f);
  DoubleOption *line_spacing_ratio = new DoubleOption("-h", "Line spacing ratio", 1.5f);
  StdStringOption *output_file_name = new StdStringOption("-o", ".pdf output file name", "out-skiahf.pdf");

  std::map<std::string, BaseOption*> options = {
    { page_width->selector, page_width },
    { page_height->selector, page_height },
    { title->selector, title },
    { author->selector, author },
    { subject->selector, subject },
    { keywords->selector, keywords },
    { creator->selector, creator },
    { font_file->selector, font_file },
    { font_size->selector, font_size },
    { left_margin->selector, left_margin },
    { line_spacing_ratio->selector, line_spacing_ratio },
    { output_file_name->selector, output_file_name },
  };

  Config(int argc, char **argv) {
    for (int i = 1; i < argc; i++) {
      std::string option_selector(argv[i]);
      auto it = options.find(option_selector);
      if (it != options.end()) {
        if (i >= argc) {
          break;
        }
        const char *option_value = argv[i + 1];
        it->second->set(option_value);
        i++;
      } else {
        printf("Ignoring unrecognized option: %s.\n", argv[i]);
        printf("Usage: %s {option value}\n", argv[0]);
        printf("\tTakes text from stdin and produces pdf file.\n");
        printf("Supported options:\n");
        for (auto it = options.begin(); it != options.end(); ++it) {
          printf("\t%s\t%s (%s)\n", it->first.c_str(),
            it->second->description.c_str(),
            it->second->valueToString().c_str());
        }
        exit(-1);
      }
    }
  } // end of Config::Config
};

const double FONT_SIZE_SCALE = 64.0f;

struct Face {
  struct HBFDel { void operator()(hb_face_t* f) { hb_face_destroy(f); } };
  std::unique_ptr<hb_face_t, HBFDel> fHarfBuzzFace;
  sk_sp<SkTypeface> fSkiaTypeface;

  Face(const char* path, int index) {
    // fairly portable mmap impl
    auto data = SkData::MakeFromFileName(path);
    assert(data);
    if (!data) { return; }
    fSkiaTypeface.reset(
      SkTypeface::CreateFromStream(
        new SkMemoryStream(data), index));
    assert(fSkiaTypeface);
    if (!fSkiaTypeface) { return; }
    auto destroy = [](void *d) { static_cast<SkData*>(d)->unref(); };
    const char* bytes = (const char*)data->data();
    unsigned int size = (unsigned int)data->size();
    hb_blob_t* blob = hb_blob_create(bytes,
                                     size,
                                     HB_MEMORY_MODE_READONLY,
                                     data.release(),
                                     destroy);
    assert(blob);
    hb_blob_make_immutable(blob);
    hb_face_t* face = hb_face_create(blob, (unsigned)index);
    hb_blob_destroy(blob);
    assert(face);
    if (!face) {
        fSkiaTypeface.reset();
        return;
    }
    hb_face_set_index(face, (unsigned)index);
    hb_face_set_upem(face, fSkiaTypeface->getUnitsPerEm());
    fHarfBuzzFace.reset(face);
  }
};

class Placement {
 public:
  Placement(Config &_config, SkWStream* outputStream) : config(_config) {
    face = new Face(config.font_file->value.c_str(), 0 /* index */);
    hb_font = hb_font_create(face->fHarfBuzzFace.get());

    hb_font_set_scale(hb_font,
        FONT_SIZE_SCALE * config.font_size->value,
        FONT_SIZE_SCALE * config.font_size->value);
    hb_ot_font_set_funcs(hb_font);

    SkDocument::PDFMetadata pdf_info;
    pdf_info.fTitle = config.title->value;
    pdf_info.fAuthor = config.author->value;
    pdf_info.fSubject = config.subject->value;
    pdf_info.fKeywords = config.keywords->value;
    pdf_info.fCreator = config.creator->value;
    SkTime::DateTime now;
    SkTime::GetDateTime(&now);
    pdf_info.fCreation.fEnabled = true;
    pdf_info.fCreation.fDateTime = now;
    pdf_info.fModified.fEnabled = true;
    pdf_info.fModified.fDateTime = now;
    pdfDocument = SkDocument::MakePDF(outputStream, SK_ScalarDefaultRasterDPI,
                                      pdf_info, nullptr, true);
    assert(pdfDocument);

    white_paint.setColor(SK_ColorWHITE);

    glyph_paint.setFlags(
        SkPaint::kAntiAlias_Flag |
        SkPaint::kSubpixelText_Flag);  // ... avoid waggly text when rotating.
    glyph_paint.setColor(SK_ColorBLACK);
    glyph_paint.setTextSize(config.font_size->value);
    glyph_paint.setTypeface(face->fSkiaTypeface);
    glyph_paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);

    NewPage();
  } // end of Placement

  ~Placement() {
    delete face;
    hb_font_destroy (hb_font);
  }

  void WriteLine(const char *text) {
    /* Create hb-buffer and populate. */
    hb_buffer_t *hb_buffer = hb_buffer_create ();
    hb_buffer_add_utf8 (hb_buffer, text, -1, 0, -1);
    hb_buffer_guess_segment_properties (hb_buffer);

    /* Shape it! */
    hb_shape (hb_font, hb_buffer, NULL, 0);

    DrawGlyphs(hb_buffer);

    hb_buffer_destroy (hb_buffer);

    // Advance to the next line.
    current_y += config.line_spacing_ratio->value * config.font_size->value;
    if (current_y > config.page_height->value) {
      pdfDocument->endPage();
      NewPage();
    }
  }

  bool Close() {
    return pdfDocument->close();
  }

private:
  Config config;

  Face *face;

  hb_font_t *hb_font;

  sk_sp<SkDocument> pdfDocument;

  SkCanvas* pageCanvas;

  SkPaint white_paint;
  SkPaint glyph_paint;

  double current_x;
  double current_y;

  void NewPage() {
    pageCanvas = pdfDocument->beginPage(config.page_width->value, config.page_height->value);

    pageCanvas->drawPaint(white_paint);

    current_x = config.left_margin->value;
    current_y = config.line_spacing_ratio->value * config.font_size->value;
  }

  bool DrawGlyphs(hb_buffer_t *hb_buffer) {
    SkTextBlobBuilder textBlobBuilder;
    unsigned len = hb_buffer_get_length (hb_buffer);
    if (len == 0) {
      return true;
    }
    hb_glyph_info_t *info = hb_buffer_get_glyph_infos (hb_buffer, NULL);
    hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (hb_buffer, NULL);
    auto runBuffer = textBlobBuilder.allocRunPos(glyph_paint, len);

    double x = 0;
    double y = 0;
    for (unsigned int i = 0; i < len; i++)
    {
      runBuffer.glyphs[i] = info[i].codepoint;
      reinterpret_cast<SkPoint*>(runBuffer.pos)[i] = SkPoint::Make(
        x + pos[i].x_offset / FONT_SIZE_SCALE,
        y - pos[i].y_offset / FONT_SIZE_SCALE);
      x += pos[i].x_advance / FONT_SIZE_SCALE;
      y += pos[i].y_advance / FONT_SIZE_SCALE;
    }

    pageCanvas->drawTextBlob(textBlobBuilder.build(), current_x, current_y, glyph_paint);
    return true;
  } // end of DrawGlyphs
}; // end of Placement class

int main(int argc, char** argv) {
    Config config(argc, argv);

    Placement placement(config, new SkFILEWStream(config.output_file_name->value.c_str()));
    for (std::string line; std::getline(std::cin, line);) {
      placement.WriteLine(line.c_str());
    }
    placement.Close();

    return 0;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	モトローラーＳフォーマット入出力
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <vector>
#include <string>
#include "file_io.hpp"
#include <iomanip>

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	Motolora Sx I/O クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class motsx_io {

		uint32_t	amin_;
		uint32_t	amax_;

		std::vector<uint8_t>	memory_;

		bool write_byte_(uint32_t address, uint8_t val) {
			if(address < memory_.size()) {
				memory_[address] = val;
				return true;
			} else {
				return false;
			}
		}

		bool load_(utils::file_io& fio) {
			amin_ = 0xffffffff;
			amax_ = 0x00000000;

			uint32_t value = 0;
			uint32_t type = 0;
			uint32_t length = 0;
			uint32_t address = 0;
			uint32_t sum = 0;
			int vcnt = 0;

			bool toend = false;
			int mode = 0;

			while(1) {
				char ch;
				if(!fio.get_char(ch)) {
					break;
				}

			   	if(ch == ' ') {
			   	} else if(ch == 0x0d || ch == 0x0a) {
				   	if(toend) break;
			   	} else if(mode == 0 && ch == 'S') {
			   		mode = 1;
			   		value = vcnt = 0;
			   	} else if(ch >= '0' && ch <= '9') {
			   		value <<= 4;
			   		value |= ch - '0';
			   		++vcnt;
			   	} else if(ch >= 'A' && ch <= 'F') {
			   		value <<= 4;
			   		value |= ch - 'A' + 10;
			   		++vcnt;
			   	} else {
					std::cerr << "S format illegual character: '";
			   		if(ch >= 0x20 && ch <= 0x7f) {
						std::cerr << ch;
			   		} else {
						std::cerr << std::hex << std::setw(2)
								  << static_cast<int>(ch) << std::dec;
			   		}
					std::cerr << "'" << std::endl;
			   		return false;
			   	}

			   	if(mode == 1) {		// タイプ取得
			   		if(vcnt == 1) {
			   			type = value;
			   			mode = 2;
			   			value = vcnt = 0;
			   		}
			   	} else if(mode == 2) {	// レングス取得
			   		if(vcnt == 2) {
			   			length = value;
			   			sum = value;
			   			mode = 3;
			   			value = vcnt = 0;
			   		}
			   	} else if(mode == 3) {	// アドレス取得
			   		int alen = 0;
			   		if(type == 0) {
			   			alen = 4;
			   		} else if(type == 1) {
			   			alen = 4;
			   		} else if(type == 2) {
			   			alen = 6;
			   		} else if(type == 3) {
			   			alen = 8;
			   		} else if(type == 5) {
			   			alen = 4;
			   		} else if(type == 7) {
			   			alen = 8;
			   		} else if(type == 8) {
			   			alen = 6;
			   		} else if(type == 9) {
			   			alen = 4;
			   		} else {
			   			return false;
			   		}
			   		if(vcnt == alen) {
			   			address = value;
			   			if(type >= 1 && type <= 3) {
			   				if(amin_ > address) amin_ = address;
			   			}
			   			alen >>= 1;
			   			length -= alen;
			   			length -= 1;	// SUM の分サイズを引く
			   			// ('.');
			   			while(alen > 0) {
			   				sum += value;
			   				value >>= 8;
			   				--alen;
			   			}
				   		if(type >= 1 && type <= 3) {
				   			mode = 4;
				   		} else if(type >= 7 && type <= 9) {
				   			mode = 5;
				   		} else {
				   			mode = 4;
				   		}
				   		value = vcnt = 0;
				   	}
			   	} else if(mode == 4) {	// データ・レコード
			   		if(vcnt >= 2) {
			   			if(type >= 1 && type <= 3) {
			   				write_byte_(address, value);
			   				if(amax_ < address) amax_ = address;
			   				++address;
			   			}
			   			sum += value;
			   			value = vcnt = 0;
			   			--length;
			   			if(length == 0) {
			   				mode = 5;
			   			}
			   		}
			   	} else if(mode == 5) {	// SUM
			   		if(vcnt >= 2) {
			   			value &= 0xff;
			   			sum ^= 0xff;
			   			sum &= 0xff;
			   			if(sum != value) {	// SUM エラー
							std::cerr << "S format SUM error: ";
							std::cerr << std::hex << std::setw(2)
									  << static_cast<int>(value)
									  << " -> "
									  << static_cast<int>(sum)
									  << std::dec << std::endl;
			   				return false;
			   			} else {
			   				if(type >= 7 && type <= 9) {
			   					toend = true;
			   				}
			   				mode = 0;
			   				value = vcnt = 0;
			   			}
			   		}
			   	}
		   	}
		   	return true;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		*/
		//-----------------------------------------------------------------//
		motsx_io() : amin_(0xffffffff), amax_(0x00000000) { }

		//-----------------------------------------------------------------//
		/*!
			@brief	ロード
			@param[in]	path	ファイルパス
			@return エラー無しなら「true」
		*/
		//-----------------------------------------------------------------//
		bool load(const std::string& path) {
			utils::file_io fio;
			if(!fio.open(path, "rb")) {
				return false;
			}

			for(int i = 0; i < 65536; ++i) {
				memory_.push_back(0xff);
			}

			if(!load_(fio)) {
				return false;
			}

			fio.close();

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	セーブ
			@param[in]	path	ファイルパス
			@return エラー無しなら「true」
		*/
		//-----------------------------------------------------------------//
		bool save(const std::string& path) {
			return false;
		}

		uint32_t get_min() const { return amin_; }

		uint32_t get_max() const { return amax_; }

		const std::vector<uint8_t>& get_memory() const { return memory_; }

	};
}

<commit_msg>add memory map<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	モトローラーＳフォーマット入出力
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <vector>
#include <map>
#include <string>
#include <array>
#include "file_io.hpp"
#include <iomanip>
#include <boost/foreach.hpp>
#include <boost/format.hpp>

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	Motolora Sx I/O クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class motsx_io {
	public:
		typedef std::array<uint8_t, 256>	array;

	private:
		uint32_t	amin_;
		uint32_t	amax_;

		typedef std::map<uint32_t, array>	memory_map;

		memory_map	memory_map_;

		array		fill_array_;

		void write_byte_(uint32_t address, uint8_t val) {
			uint32_t base = address & 0xffff00;
			memory_map::iterator it = memory_map_.find(base);
			if(it == memory_map_.end()) {
				array ar;
				ar.fill(0xff);
				ar[address & 255] = val;
				memory_map_.emplace(base, ar);
			} else {
				array& ar = it->second;
				ar[address & 255] = val;
			}
		}

		bool load_(utils::file_io& fio) {
			amin_ = 0xffffffff;
			amax_ = 0x00000000;

			uint32_t value = 0;
			uint32_t type = 0;
			uint32_t length = 0;
			uint32_t address = 0;
			uint32_t sum = 0;
			int vcnt = 0;

			bool toend = false;
			int mode = 0;

			while(1) {
				char ch;
				if(!fio.get_char(ch)) {
					break;
				}

			   	if(ch == ' ') {
			   	} else if(ch == 0x0d || ch == 0x0a) {
				   	if(toend) break;
			   	} else if(mode == 0 && ch == 'S') {
			   		mode = 1;
			   		value = vcnt = 0;
			   	} else if(ch >= '0' && ch <= '9') {
			   		value <<= 4;
			   		value |= ch - '0';
			   		++vcnt;
			   	} else if(ch >= 'A' && ch <= 'F') {
			   		value <<= 4;
			   		value |= ch - 'A' + 10;
			   		++vcnt;
			   	} else {
					std::cerr << "S format illegual character: '";
			   		if(ch >= 0x20 && ch <= 0x7f) {
						std::cerr << ch;
			   		} else {
						std::cerr << std::hex << std::setw(2)
								  << static_cast<int>(ch) << std::dec;
			   		}
					std::cerr << "'" << std::endl;
			   		return false;
			   	}

			   	if(mode == 1) {		// タイプ取得
			   		if(vcnt == 1) {
			   			type = value;
			   			mode = 2;
			   			value = vcnt = 0;
			   		}
			   	} else if(mode == 2) {	// レングス取得
			   		if(vcnt == 2) {
			   			length = value;
			   			sum = value;
			   			mode = 3;
			   			value = vcnt = 0;
			   		}
			   	} else if(mode == 3) {	// アドレス取得
			   		int alen = 0;
			   		if(type == 0) {
			   			alen = 4;
			   		} else if(type == 1) {
			   			alen = 4;
			   		} else if(type == 2) {
			   			alen = 6;
			   		} else if(type == 3) {
			   			alen = 8;
			   		} else if(type == 5) {
			   			alen = 4;
			   		} else if(type == 7) {
			   			alen = 8;
			   		} else if(type == 8) {
			   			alen = 6;
			   		} else if(type == 9) {
			   			alen = 4;
			   		} else {
			   			return false;
			   		}
			   		if(vcnt == alen) {
			   			address = value;
			   			if(type >= 1 && type <= 3) {
			   				if(amin_ > address) amin_ = address;
			   			}
			   			alen >>= 1;
			   			length -= alen;
			   			length -= 1;	// SUM の分サイズを引く
			   			// ('.');
			   			while(alen > 0) {
			   				sum += value;
			   				value >>= 8;
			   				--alen;
			   			}
				   		if(type >= 1 && type <= 3) {
				   			mode = 4;
				   		} else if(type >= 7 && type <= 9) {
				   			mode = 5;
				   		} else {
				   			mode = 4;
				   		}
				   		value = vcnt = 0;
				   	}
			   	} else if(mode == 4) {	// データ・レコード
			   		if(vcnt >= 2) {
			   			if(type >= 1 && type <= 3) {
			   				write_byte_(address, value);
			   				if(amax_ < address) amax_ = address;
			   				++address;
			   			}
			   			sum += value;
			   			value = vcnt = 0;
			   			--length;
			   			if(length == 0) {
			   				mode = 5;
			   			}
			   		}
			   	} else if(mode == 5) {	// SUM
			   		if(vcnt >= 2) {
			   			value &= 0xff;
			   			sum ^= 0xff;
			   			sum &= 0xff;
			   			if(sum != value) {	// SUM エラー
							std::cerr << "S format SUM error: ";
							std::cerr << std::hex << std::setw(2)
									  << static_cast<int>(value)
									  << " -> "
									  << static_cast<int>(sum)
									  << std::dec << std::endl;
			   				return false;
			   			} else {
			   				if(type >= 7 && type <= 9) {
			   					toend = true;
			   				}
			   				mode = 0;
			   				value = vcnt = 0;
			   			}
			   		}
			   	}
		   	}
		   	return true;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		*/
		//-----------------------------------------------------------------//
		motsx_io() : amin_(0xffffffff), amax_(0x00000000) {
			fill_array_.fill(0xff);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	ロード
			@param[in]	path	ファイルパス
			@return エラー無しなら「true」
		*/
		//-----------------------------------------------------------------//
		bool load(const std::string& path) {
			utils::file_io fio;
			if(!fio.open(path, "rb")) {
				return false;
			}

			memory_map_.clear();

			if(!load_(fio)) {
				return false;
			}

			fio.close();

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	セーブ
			@param[in]	path	ファイルパス
			@return エラー無しなら「true」
		*/
		//-----------------------------------------------------------------//
		bool save(const std::string& path) {
			return false;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	総ページ数の取得
			@return 総ページ数
		*/
		//-----------------------------------------------------------------//
		uint32_t get_total_page() const {
			return memory_map_.size();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	メモリーマップの表示
		*/
		//-----------------------------------------------------------------//
		void list_memory_map() const {
			uint32_t org = 0;
			uint32_t fin = 0;
			bool first = true;
			BOOST_FOREACH(const memory_map::value_type& m, memory_map_) {
				if(first) {
					std::cout << boost::format("0x%06X to ") % m.first;
					org = fin = m.first;
					first = false;
				}
				if(m.first != fin) {
					std::cout << boost::format("0x%06X (%d bytes)\n") %
						(fin - 1) % (fin - org);
					first = true;
				}
				fin += 256;
			}
			std::cout << boost::format("0x%06X (%d bytes)\n") %
				(fin - 1) % (fin - org);
			std::cout << std::flush;
		}

		uint32_t get_min() const { return amin_; }

		uint32_t get_max() const { return amax_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	利用されているページを探す（有効なページ）
			@param[in]	address	アドレス
			@return 有効なページがあれば「true」
		*/
		//-----------------------------------------------------------------//
		bool find_page(uint32_t address) const {
			return memory_map_.find(address & 0xffff00) != memory_map_.end();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	ページメモリーの取得
			@param[in]	address	ベースとなるアドレス
			@return ページメモリー @n
					無効なページの場合、内部データは全て 0xff となっている。
		*/
		//-----------------------------------------------------------------//
		const array& get_memory(uint32_t address) const {
			memory_map::const_iterator cit = memory_map_.find(address & 0xffff00);
			if(cit == memory_map_.end()) {
				return fill_array_;
			}
			return cit->second;
		}
	};
}
<|endoftext|>


<commit_before>#include <boost/test/unit_test.hpp>
#include <test/data/ethspv_valid.json.h>
#include <test/data/ethspv_invalid.json.h>

#include <uint256.h>
#include <util/strencodings.h>
#include <ethereum/ethereum.h>
#include <ethereum/common.h>
#include <ethereum/rlp.h>
#include <script/interpreter.h>
#include <script/standard.h>
#include <policy/policy.h>
#include <services/asset.h>
#include <univalue.h>
#include <key_io.h>
#include <util/system.h>
extern UniValue read_json(const std::string& jsondata);

BOOST_AUTO_TEST_SUITE(ethereum_tests)
BOOST_AUTO_TEST_CASE(ethereum_parseabidata)
{
    tfm::format(std::cout,"Running ethereum_parseabidata...\n");
    CAmount outputAmount;
    uint32_t nAsset = 0;
    const std::vector<unsigned char> &expectedMethodHash = ParseHex("54c988ff");
    const std::vector<unsigned char> &rlpBytes = ParseHex("54c988ff00000000000000000000000000000000000000000000000000000002540be400000000000000000000000000000000000000000000000000000000009be8894b0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002c62637274317130667265323430737939326d716b386b6b377073616561366b74366d3537323570377964636a0000000000000000000000000000000000000000");
    CTxDestination expectedDestination = DecodeDestination("bcrt1q0fre240sy92mqk8kk7psaea6kt6m5725p7ydcj");
    CTxDestination address;
    BOOST_CHECK(parseEthMethodInputData(expectedMethodHash, 8, 8, rlpBytes, outputAmount, nAsset, address));
    BOOST_CHECK_EQUAL(outputAmount, 100*COIN);
    BOOST_CHECK_EQUAL(nAsset, 2615707979);
    BOOST_CHECK(address == expectedDestination);

}

BOOST_AUTO_TEST_CASE(ethspv_valid)
{
    tfm::format(std::cout,"Running ethspv_valid...\n");
    // Read tests from test/data/ethspv_valid.json
    // Format is an array of arrays
    // Inner arrays are either [ "comment" ]
    // [[spv_root, spv_parent_node, spv_value, spv_path]]

    UniValue tests = read_json(std::string(json_tests::ethspv_valid, json_tests::ethspv_valid + sizeof(json_tests::ethspv_valid)));

    for (unsigned int idx = 0; idx < tests.size(); idx++) {
        UniValue test = tests[idx];
        std::string strTest = test.write();
        if (test.size() != 4) {
				// ignore comments
				continue;
		} else {
        if ( !test[0].isStr() || !test[1].isStr() || !test[2].isStr() || !test[3].isStr()) {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }

      	std::string spv_tx_root = test[0].get_str();
			  std::string spv_parent_nodes = test[1].get_str();
			  std::string spv_value = test[2].get_str();
			  std::string spv_path = test[3].get_str();

        const std::vector<unsigned char> &vchTxRoot = ParseHex(spv_tx_root);
        dev::RLP rlpTxRoot(&vchTxRoot);
        const std::vector<unsigned char> &vchTxParentNodes = ParseHex(spv_parent_nodes);
        dev::RLP rlpTxParentNodes(&vchTxParentNodes);
        const std::vector<unsigned char> &vchTxValue = ParseHex(spv_value);
        dev::RLP rlpTxValue(&vchTxValue);
        const std::vector<unsigned char> &vchTxPath = ParseHex(spv_path);
        BOOST_CHECK(VerifyProof(&vchTxPath, rlpTxValue, rlpTxParentNodes, rlpTxRoot));
        }
    }
}

BOOST_AUTO_TEST_CASE(ethspv_invalid)
{
    tfm::format(std::cout,"Running ethspv_invalid...\n");
    // Read tests from test/data/ethspv_invalid.json
    // Format is an array of arrays
    // Inner arrays are either [ "comment" ]
    // [[spv_root, spv_parent_node, spv_value, spv_path]]

    UniValue tests = read_json(std::string(json_tests::ethspv_invalid, json_tests::ethspv_invalid + sizeof(json_tests::ethspv_invalid)));

    for (unsigned int idx = 0; idx < tests.size(); idx++) {
        UniValue test = tests[idx];
        std::string strTest = test.write();
        if (test.size() != 4) {
				// ignore comments
				continue;
		    } else {
            if ( !test[0].isStr() || !test[1].isStr() || !test[2].isStr() || !test[3].isStr()) {
                BOOST_ERROR("Bad test: " << strTest);
                continue;
            }
			      std::string spv_tx_root = test[0].get_str();
			      std::string spv_parent_nodes = test[1].get_str();
			      std::string spv_value = test[2].get_str();
			      std::string spv_path = test[3].get_str();

            const std::vector<unsigned char> &vchTxRoot = ParseHex(spv_tx_root);
            dev::RLP rlpTxRoot(&vchTxRoot);
            const std::vector<unsigned char> &vchTxParentNodes = ParseHex(spv_parent_nodes);
            dev::RLP rlpTxParentNodes(&vchTxParentNodes);
            const std::vector<unsigned char> &vchTxValue = ParseHex(spv_value);
            dev::RLP rlpTxValue(&vchTxValue);
            const std::vector<unsigned char> &vchTxPath = ParseHex(spv_path);
            BOOST_CHECK(!VerifyProof(&vchTxPath, rlpTxValue, rlpTxParentNodes, rlpTxRoot));
        }
    }
}
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Update ethereum_tests.cpp<commit_after>#include <boost/test/unit_test.hpp>
#include <test/data/ethspv_valid.json.h>
#include <test/data/ethspv_invalid.json.h>

#include <uint256.h>
#include <util/strencodings.h>
#include <ethereum/ethereum.h>
#include <ethereum/common.h>
#include <ethereum/rlp.h>
#include <script/interpreter.h>
#include <script/standard.h>
#include <policy/policy.h>
#include <services/asset.h>
#include <univalue.h>
#include <key_io.h>
#include <util/system.h>
#include <test/util/setup_common.h>
extern UniValue read_json(const std::string& jsondata);

BOOST_FIXTURE_TEST_SUITE(ethereum_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(ethereum_parseabidata)
{
    tfm::format(std::cout,"Running ethereum_parseabidata...\n");
    CAmount outputAmount;
    uint32_t nAsset = 0;
    const std::vector<unsigned char> &expectedMethodHash = ParseHex("54c988ff");
    const std::vector<unsigned char> &rlpBytes = ParseHex("54c988ff00000000000000000000000000000000000000000000000000000002540be400000000000000000000000000000000000000000000000000000000009be8894b0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002c62637274317130667265323430737939326d716b386b6b377073616561366b74366d3537323570377964636a0000000000000000000000000000000000000000");
    CTxDestination expectedDestination = DecodeDestination("bcrt1q0fre240sy92mqk8kk7psaea6kt6m5725p7ydcj");
    CTxDestination address;
    BOOST_CHECK(parseEthMethodInputData(expectedMethodHash, 8, 8, rlpBytes, outputAmount, nAsset, address));
    BOOST_CHECK_EQUAL(outputAmount, 100*COIN);
    BOOST_CHECK_EQUAL(nAsset, 2615707979);
    BOOST_CHECK(address == expectedDestination);

}

BOOST_AUTO_TEST_CASE(ethspv_valid)
{
    tfm::format(std::cout,"Running ethspv_valid...\n");
    // Read tests from test/data/ethspv_valid.json
    // Format is an array of arrays
    // Inner arrays are either [ "comment" ]
    // [[spv_root, spv_parent_node, spv_value, spv_path]]

    UniValue tests = read_json(std::string(json_tests::ethspv_valid, json_tests::ethspv_valid + sizeof(json_tests::ethspv_valid)));

    for (unsigned int idx = 0; idx < tests.size(); idx++) {
        UniValue test = tests[idx];
        std::string strTest = test.write();
        if (test.size() != 4) {
				// ignore comments
				continue;
		} else {
        if ( !test[0].isStr() || !test[1].isStr() || !test[2].isStr() || !test[3].isStr()) {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }

      	std::string spv_tx_root = test[0].get_str();
			  std::string spv_parent_nodes = test[1].get_str();
			  std::string spv_value = test[2].get_str();
			  std::string spv_path = test[3].get_str();

        const std::vector<unsigned char> &vchTxRoot = ParseHex(spv_tx_root);
        dev::RLP rlpTxRoot(&vchTxRoot);
        const std::vector<unsigned char> &vchTxParentNodes = ParseHex(spv_parent_nodes);
        dev::RLP rlpTxParentNodes(&vchTxParentNodes);
        const std::vector<unsigned char> &vchTxValue = ParseHex(spv_value);
        dev::RLP rlpTxValue(&vchTxValue);
        const std::vector<unsigned char> &vchTxPath = ParseHex(spv_path);
        BOOST_CHECK(VerifyProof(&vchTxPath, rlpTxValue, rlpTxParentNodes, rlpTxRoot));
        }
    }
}

BOOST_AUTO_TEST_CASE(ethspv_invalid)
{
    tfm::format(std::cout,"Running ethspv_invalid...\n");
    // Read tests from test/data/ethspv_invalid.json
    // Format is an array of arrays
    // Inner arrays are either [ "comment" ]
    // [[spv_root, spv_parent_node, spv_value, spv_path]]

    UniValue tests = read_json(std::string(json_tests::ethspv_invalid, json_tests::ethspv_invalid + sizeof(json_tests::ethspv_invalid)));

    for (unsigned int idx = 0; idx < tests.size(); idx++) {
        UniValue test = tests[idx];
        std::string strTest = test.write();
        if (test.size() != 4) {
				// ignore comments
				continue;
		    } else {
            if ( !test[0].isStr() || !test[1].isStr() || !test[2].isStr() || !test[3].isStr()) {
                BOOST_ERROR("Bad test: " << strTest);
                continue;
            }
			      std::string spv_tx_root = test[0].get_str();
			      std::string spv_parent_nodes = test[1].get_str();
			      std::string spv_value = test[2].get_str();
			      std::string spv_path = test[3].get_str();

            const std::vector<unsigned char> &vchTxRoot = ParseHex(spv_tx_root);
            dev::RLP rlpTxRoot(&vchTxRoot);
            const std::vector<unsigned char> &vchTxParentNodes = ParseHex(spv_parent_nodes);
            dev::RLP rlpTxParentNodes(&vchTxParentNodes);
            const std::vector<unsigned char> &vchTxValue = ParseHex(spv_value);
            dev::RLP rlpTxValue(&vchTxValue);
            const std::vector<unsigned char> &vchTxPath = ParseHex(spv_path);
            BOOST_CHECK(!VerifyProof(&vchTxPath, rlpTxValue, rlpTxParentNodes, rlpTxRoot));
        }
    }
}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"

#include "webkit/glue/webinputevent.h"

#include "base/logging.h"
#include "base/string_util.h"
#include "webkit/glue/webinputevent_util.h"

static const unsigned long kDefaultScrollLinesPerWheelDelta = 3;
static const unsigned long kDefaultScrollCharsPerWheelDelta = 1;

// WebMouseEvent --------------------------------------------------------------

static LPARAM GetRelativeCursorPos(HWND hwnd) {
  POINT pos = {-1, -1};
  GetCursorPos(&pos);
  ScreenToClient(hwnd, &pos);
  return MAKELPARAM(pos.x, pos.y);
}

WebMouseEvent::WebMouseEvent(HWND hwnd, UINT message, WPARAM wparam,
                             LPARAM lparam) {
  switch (message) {
    case WM_MOUSEMOVE:
      type = MOUSE_MOVE;
      if (wparam & MK_LBUTTON)
        button = BUTTON_LEFT;
      else if (wparam & MK_MBUTTON)
        button = BUTTON_MIDDLE;
      else if (wparam & MK_RBUTTON)
        button = BUTTON_MIDDLE;
      else
        button = BUTTON_NONE;
      break;
    case WM_MOUSELEAVE:
      type = MOUSE_LEAVE;
      button = BUTTON_NONE;
      // set the current mouse position (relative to the client area of the
      // current window) since none is specified for this event
      lparam = GetRelativeCursorPos(hwnd);
      break;
    case WM_LBUTTONDOWN:
      type = MOUSE_DOWN;
      button = BUTTON_LEFT;
      break;
    case WM_MBUTTONDOWN:
      type = MOUSE_DOWN;
      button = BUTTON_MIDDLE;
      break;
    case WM_RBUTTONDOWN:
      type = MOUSE_DOWN;
      button = BUTTON_RIGHT;
      break;
    case WM_LBUTTONUP:
      type = MOUSE_UP;
      button = BUTTON_LEFT;
      break;
    case WM_MBUTTONUP:
      type = MOUSE_UP;
      button = BUTTON_MIDDLE;
      break;
    case WM_RBUTTONUP:
      type = MOUSE_UP;
      button = BUTTON_RIGHT;
      break;
    case WM_LBUTTONDBLCLK:
      type = MOUSE_DOUBLE_CLICK;
      button = BUTTON_LEFT;
      break;
    case WM_MBUTTONDBLCLK:
      type = MOUSE_DOUBLE_CLICK;
      button = BUTTON_MIDDLE;
      break;
    case WM_RBUTTONDBLCLK:
      type = MOUSE_DOUBLE_CLICK;
      button = BUTTON_RIGHT;
      break;
    default:
      NOTREACHED() << "unexpected native message";
  }

  // set position fields:

  x = static_cast<short>(LOWORD(lparam));
  y = static_cast<short>(HIWORD(lparam));

  POINT global_point = { x, y };
  ClientToScreen(hwnd, &global_point);

  global_x = global_point.x;
  global_y = global_point.y;

  // set modifiers:

  if (wparam & MK_CONTROL)
    modifiers |= CTRL_KEY;
  if (wparam & MK_SHIFT)
    modifiers |= SHIFT_KEY;
  if (GetKeyState(VK_MENU) & 0x8000)
    modifiers |= (ALT_KEY | META_KEY);  // TODO(darin): set META properly

  // TODO(pkasting): http://b/1117926 Instead of using GetTickCount() here, we
  // should use GetMessageTime() on the original Windows message in the browser
  // process, and pass that in the WebMouseEvent.
  timestamp_sec = GetTickCount() / 1000.0;

  layout_test_click_count = 0;
}

// WebMouseWheelEvent ---------------------------------------------------------

WebMouseWheelEvent::WebMouseWheelEvent(HWND hwnd,
                                       UINT message,
                                       WPARAM wparam,
                                       LPARAM lparam)
    : scroll_by_page(false) {
  type = MOUSE_WHEEL;
  button = BUTTON_NONE;

  // Get key state, coordinates, and wheel delta from event.
  typedef SHORT (WINAPI *GetKeyStateFunction)(int key);
  GetKeyStateFunction get_key_state;
  UINT key_state;
  float wheel_delta;
  bool horizontal_scroll = false;
  if ((message == WM_VSCROLL) || (message == WM_HSCROLL)) {
    // Synthesize mousewheel event from a scroll event.  This is needed to
    // simulate middle mouse scrolling in some laptops.  Use GetAsyncKeyState
    // for key state since we are synthesizing the input event.
    get_key_state = GetAsyncKeyState;
    key_state = 0;
    if (get_key_state(VK_SHIFT))
      key_state |= MK_SHIFT;
    if (get_key_state(VK_CONTROL))
      key_state |= MK_CONTROL;

    POINT cursor_position = {0};
    GetCursorPos(&cursor_position);
    global_x = cursor_position.x;
    global_y = cursor_position.y;

    switch (LOWORD(wparam)) {
      case SB_LINEUP:    // == SB_LINELEFT
        wheel_delta = WHEEL_DELTA;
        break;
      case SB_LINEDOWN:  // == SB_LINERIGHT
        wheel_delta = -WHEEL_DELTA;
        break;
      case SB_PAGEUP:
        wheel_delta = 1;
        scroll_by_page = true;
        break;
      case SB_PAGEDOWN:
        wheel_delta = -1;
        scroll_by_page = true;
        break;
      default:  // We don't supoprt SB_THUMBPOSITION or SB_THUMBTRACK here.
        wheel_delta = 0;
        break;
    }

    if (message == WM_HSCROLL) {
      horizontal_scroll = true;
      wheel_delta = -wheel_delta;
    }
  } else {
    // Non-synthesized event; we can just read data off the event.
    get_key_state = GetKeyState;
    key_state = GET_KEYSTATE_WPARAM(wparam);

    global_x = static_cast<short>(LOWORD(lparam));
    global_y = static_cast<short>(HIWORD(lparam));

    wheel_delta = static_cast<float>(GET_WHEEL_DELTA_WPARAM(wparam));
    if (((message == WM_MOUSEHWHEEL) || (key_state & MK_SHIFT)) &&
        (wheel_delta != 0))
      horizontal_scroll = true;
  }

  // Set modifiers based on key state.
  if (key_state & MK_SHIFT)
    modifiers |= SHIFT_KEY;
  if (key_state & MK_CONTROL)
    modifiers |= CTRL_KEY;
  if (get_key_state(VK_MENU) & 0x8000)
    modifiers |= (ALT_KEY | META_KEY);

  // Set coordinates by translating event coordinates from screen to client.
  POINT client_point = { global_x, global_y };
  MapWindowPoints(NULL, hwnd, &client_point, 1);
  x = client_point.x;
  y = client_point.y;

  // Convert wheel delta amount to a number of pixels to scroll.
  //
  // How many pixels should we scroll per line?  Gecko uses the height of the
  // current line, which means scroll distance changes as you go through the
  // page or go to different pages.  IE 7 is ~50 px/line, although the value
  // seems to vary slightly by page and zoom level.  Since IE 7 has a smoothing
  // algorithm on scrolling, it can get away with slightly larger scroll values
  // without feeling jerky.  Here we use 100 px per three lines (the default
  // scroll amount is three lines per wheel tick).
  static const float kScrollbarPixelsPerLine = 100.0f / 3.0f;
  float scroll_delta = wheel_delta / WHEEL_DELTA;
  if (horizontal_scroll) {
    unsigned long scroll_chars = kDefaultScrollCharsPerWheelDelta;
    SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scroll_chars, 0);
    // TODO(pkasting): Should probably have a different multiplier
    // kScrollbarPixelsPerChar here.
    scroll_delta *= static_cast<float>(scroll_chars) * kScrollbarPixelsPerLine;
  } else {
    unsigned long scroll_lines = kDefaultScrollLinesPerWheelDelta;
    SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scroll_lines, 0);
    if (scroll_lines == WHEEL_PAGESCROLL)
      scroll_by_page = true;
    if (!scroll_by_page) {
      scroll_delta *=
          static_cast<float>(scroll_lines) * kScrollbarPixelsPerLine;
    }
  }

  // Set scroll amount based on above calculations.
  if (horizontal_scroll) {
    delta_x = scroll_delta;
    delta_y = 0;
  } else {
    delta_x = 0;
    delta_y = scroll_delta;
  }
}

// WebKeyboardEvent -----------------------------------------------------------

bool IsKeyPad(WPARAM wparam, LPARAM lparam) {
  bool keypad = false;
  switch (wparam) {
    case VK_RETURN:
      keypad = (lparam >> 16) & KF_EXTENDED;
      break;
    case VK_INSERT:
    case VK_DELETE:
    case VK_HOME:
    case VK_END:
    case VK_PRIOR:
    case VK_NEXT:
    case VK_UP:
    case VK_DOWN:
    case VK_LEFT:
    case VK_RIGHT:
      keypad = !((lparam >> 16) & KF_EXTENDED);
      break;
    case VK_NUMLOCK:
    case VK_NUMPAD0:
    case VK_NUMPAD1:
    case VK_NUMPAD2:
    case VK_NUMPAD3:
    case VK_NUMPAD4:
    case VK_NUMPAD5:
    case VK_NUMPAD6:
    case VK_NUMPAD7:
    case VK_NUMPAD8:
    case VK_NUMPAD9:
    case VK_DIVIDE:
    case VK_MULTIPLY:
    case VK_SUBTRACT:
    case VK_ADD:
    case VK_DECIMAL:
    case VK_CLEAR:
      keypad = true;
      break;
    default:
      keypad = false;
  }

  return keypad;
}

WebKeyboardEvent::WebKeyboardEvent(HWND hwnd, UINT message, WPARAM wparam,
                                   LPARAM lparam) {
  system_key = false;

  windows_key_code = native_key_code = static_cast<int>(wparam);

  switch (message) {
    case WM_SYSKEYDOWN:
      system_key = true;
    case WM_KEYDOWN:
      type = RAW_KEY_DOWN;
      break;
    case WM_SYSKEYUP:
      system_key = true;
    case WM_KEYUP:
      type = KEY_UP;
      break;
    case WM_IME_CHAR:
      type = CHAR;
      break;
    case WM_SYSCHAR:
      system_key = true;
      type = CHAR;
    case WM_CHAR:
      type = CHAR;
      break;
    default:
      NOTREACHED() << "unexpected native message: " << message;
  }

  memset(&text, 0, sizeof(text));
  memset(&unmodified_text, 0, sizeof(unmodified_text));
  memset(&key_identifier, 0, sizeof(key_identifier));

  if (type == CHAR || type == RAW_KEY_DOWN) {
    text[0] = windows_key_code;
    unmodified_text[0] = windows_key_code;
  }
  if (type != CHAR) {
    std::string key_identifier_str =
        webkit_glue::GetKeyIdentifierForWindowsKeyCode(windows_key_code);
    base::strlcpy(key_identifier, key_identifier_str.c_str(),
                  kIdentifierLengthCap);
  }

  if (GetKeyState(VK_SHIFT) & 0x8000)
    modifiers |= SHIFT_KEY;
  if (GetKeyState(VK_CONTROL) & 0x8000)
    modifiers |= CTRL_KEY;
  if (GetKeyState(VK_MENU) & 0x8000)
    modifiers |= (ALT_KEY | META_KEY);

  if (LOWORD(lparam) > 1)
    modifiers |= IS_AUTO_REPEAT;
  if (IsKeyPad(wparam, lparam))
    modifiers |= IS_KEYPAD;
}

<commit_msg>Fix horizontal scrolling to not be reversed on tilt wheel mice and old Thinkpads.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"

#include "webkit/glue/webinputevent.h"

#include "base/logging.h"
#include "base/string_util.h"
#include "webkit/glue/webinputevent_util.h"

static const unsigned long kDefaultScrollLinesPerWheelDelta = 3;
static const unsigned long kDefaultScrollCharsPerWheelDelta = 1;

// WebMouseEvent --------------------------------------------------------------

static LPARAM GetRelativeCursorPos(HWND hwnd) {
  POINT pos = {-1, -1};
  GetCursorPos(&pos);
  ScreenToClient(hwnd, &pos);
  return MAKELPARAM(pos.x, pos.y);
}

WebMouseEvent::WebMouseEvent(HWND hwnd, UINT message, WPARAM wparam,
                             LPARAM lparam) {
  switch (message) {
    case WM_MOUSEMOVE:
      type = MOUSE_MOVE;
      if (wparam & MK_LBUTTON)
        button = BUTTON_LEFT;
      else if (wparam & MK_MBUTTON)
        button = BUTTON_MIDDLE;
      else if (wparam & MK_RBUTTON)
        button = BUTTON_MIDDLE;
      else
        button = BUTTON_NONE;
      break;
    case WM_MOUSELEAVE:
      type = MOUSE_LEAVE;
      button = BUTTON_NONE;
      // set the current mouse position (relative to the client area of the
      // current window) since none is specified for this event
      lparam = GetRelativeCursorPos(hwnd);
      break;
    case WM_LBUTTONDOWN:
      type = MOUSE_DOWN;
      button = BUTTON_LEFT;
      break;
    case WM_MBUTTONDOWN:
      type = MOUSE_DOWN;
      button = BUTTON_MIDDLE;
      break;
    case WM_RBUTTONDOWN:
      type = MOUSE_DOWN;
      button = BUTTON_RIGHT;
      break;
    case WM_LBUTTONUP:
      type = MOUSE_UP;
      button = BUTTON_LEFT;
      break;
    case WM_MBUTTONUP:
      type = MOUSE_UP;
      button = BUTTON_MIDDLE;
      break;
    case WM_RBUTTONUP:
      type = MOUSE_UP;
      button = BUTTON_RIGHT;
      break;
    case WM_LBUTTONDBLCLK:
      type = MOUSE_DOUBLE_CLICK;
      button = BUTTON_LEFT;
      break;
    case WM_MBUTTONDBLCLK:
      type = MOUSE_DOUBLE_CLICK;
      button = BUTTON_MIDDLE;
      break;
    case WM_RBUTTONDBLCLK:
      type = MOUSE_DOUBLE_CLICK;
      button = BUTTON_RIGHT;
      break;
    default:
      NOTREACHED() << "unexpected native message";
  }

  // set position fields:

  x = static_cast<short>(LOWORD(lparam));
  y = static_cast<short>(HIWORD(lparam));

  POINT global_point = { x, y };
  ClientToScreen(hwnd, &global_point);

  global_x = global_point.x;
  global_y = global_point.y;

  // set modifiers:

  if (wparam & MK_CONTROL)
    modifiers |= CTRL_KEY;
  if (wparam & MK_SHIFT)
    modifiers |= SHIFT_KEY;
  if (GetKeyState(VK_MENU) & 0x8000)
    modifiers |= (ALT_KEY | META_KEY);  // TODO(darin): set META properly

  // TODO(pkasting): http://b/1117926 Instead of using GetTickCount() here, we
  // should use GetMessageTime() on the original Windows message in the browser
  // process, and pass that in the WebMouseEvent.
  timestamp_sec = GetTickCount() / 1000.0;

  layout_test_click_count = 0;
}

// WebMouseWheelEvent ---------------------------------------------------------

WebMouseWheelEvent::WebMouseWheelEvent(HWND hwnd,
                                       UINT message,
                                       WPARAM wparam,
                                       LPARAM lparam)
    : scroll_by_page(false) {
  type = MOUSE_WHEEL;
  button = BUTTON_NONE;

  // Get key state, coordinates, and wheel delta from event.
  typedef SHORT (WINAPI *GetKeyStateFunction)(int key);
  GetKeyStateFunction get_key_state;
  UINT key_state;
  float wheel_delta;
  bool horizontal_scroll = false;
  if ((message == WM_VSCROLL) || (message == WM_HSCROLL)) {
    // Synthesize mousewheel event from a scroll event.  This is needed to
    // simulate middle mouse scrolling in some laptops.  Use GetAsyncKeyState
    // for key state since we are synthesizing the input event.
    get_key_state = GetAsyncKeyState;
    key_state = 0;
    if (get_key_state(VK_SHIFT))
      key_state |= MK_SHIFT;
    if (get_key_state(VK_CONTROL))
      key_state |= MK_CONTROL;

    POINT cursor_position = {0};
    GetCursorPos(&cursor_position);
    global_x = cursor_position.x;
    global_y = cursor_position.y;

    switch (LOWORD(wparam)) {
      case SB_LINEUP:    // == SB_LINELEFT
        wheel_delta = WHEEL_DELTA;
        break;
      case SB_LINEDOWN:  // == SB_LINERIGHT
        wheel_delta = -WHEEL_DELTA;
        break;
      case SB_PAGEUP:
        wheel_delta = 1;
        scroll_by_page = true;
        break;
      case SB_PAGEDOWN:
        wheel_delta = -1;
        scroll_by_page = true;
        break;
      default:  // We don't supoprt SB_THUMBPOSITION or SB_THUMBTRACK here.
        wheel_delta = 0;
        break;
    }

    if (message == WM_HSCROLL)
      horizontal_scroll = true;
  } else {
    // Non-synthesized event; we can just read data off the event.
    get_key_state = GetKeyState;
    key_state = GET_KEYSTATE_WPARAM(wparam);

    global_x = static_cast<short>(LOWORD(lparam));
    global_y = static_cast<short>(HIWORD(lparam));

    wheel_delta = static_cast<float>(GET_WHEEL_DELTA_WPARAM(wparam));
    if (message == WM_MOUSEHWHEEL) {
      horizontal_scroll = true;
      wheel_delta = -wheel_delta;  // Windows is <- -/+ ->, WebKit <- +/- ->.
    }
  }
  if (key_state & MK_SHIFT)
    horizontal_scroll = true;

  // Set modifiers based on key state.
  if (key_state & MK_SHIFT)
    modifiers |= SHIFT_KEY;
  if (key_state & MK_CONTROL)
    modifiers |= CTRL_KEY;
  if (get_key_state(VK_MENU) & 0x8000)
    modifiers |= (ALT_KEY | META_KEY);

  // Set coordinates by translating event coordinates from screen to client.
  POINT client_point = { global_x, global_y };
  MapWindowPoints(NULL, hwnd, &client_point, 1);
  x = client_point.x;
  y = client_point.y;

  // Convert wheel delta amount to a number of pixels to scroll.
  //
  // How many pixels should we scroll per line?  Gecko uses the height of the
  // current line, which means scroll distance changes as you go through the
  // page or go to different pages.  IE 7 is ~50 px/line, although the value
  // seems to vary slightly by page and zoom level.  Since IE 7 has a smoothing
  // algorithm on scrolling, it can get away with slightly larger scroll values
  // without feeling jerky.  Here we use 100 px per three lines (the default
  // scroll amount is three lines per wheel tick).
  static const float kScrollbarPixelsPerLine = 100.0f / 3.0f;
  float scroll_delta = wheel_delta / WHEEL_DELTA;
  if (horizontal_scroll) {
    unsigned long scroll_chars = kDefaultScrollCharsPerWheelDelta;
    SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scroll_chars, 0);
    // TODO(pkasting): Should probably have a different multiplier
    // kScrollbarPixelsPerChar here.
    scroll_delta *= static_cast<float>(scroll_chars) * kScrollbarPixelsPerLine;
  } else {
    unsigned long scroll_lines = kDefaultScrollLinesPerWheelDelta;
    SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scroll_lines, 0);
    if (scroll_lines == WHEEL_PAGESCROLL)
      scroll_by_page = true;
    if (!scroll_by_page) {
      scroll_delta *=
          static_cast<float>(scroll_lines) * kScrollbarPixelsPerLine;
    }
  }

  // Set scroll amount based on above calculations.  WebKit expects positive
  // delta_y to mean "scroll up" and positive delta_x to mean "scroll left".
  if (horizontal_scroll) {
    delta_x = scroll_delta;
    delta_y = 0;
  } else {
    delta_x = 0;
    delta_y = scroll_delta;
  }
}

// WebKeyboardEvent -----------------------------------------------------------

bool IsKeyPad(WPARAM wparam, LPARAM lparam) {
  bool keypad = false;
  switch (wparam) {
    case VK_RETURN:
      keypad = (lparam >> 16) & KF_EXTENDED;
      break;
    case VK_INSERT:
    case VK_DELETE:
    case VK_HOME:
    case VK_END:
    case VK_PRIOR:
    case VK_NEXT:
    case VK_UP:
    case VK_DOWN:
    case VK_LEFT:
    case VK_RIGHT:
      keypad = !((lparam >> 16) & KF_EXTENDED);
      break;
    case VK_NUMLOCK:
    case VK_NUMPAD0:
    case VK_NUMPAD1:
    case VK_NUMPAD2:
    case VK_NUMPAD3:
    case VK_NUMPAD4:
    case VK_NUMPAD5:
    case VK_NUMPAD6:
    case VK_NUMPAD7:
    case VK_NUMPAD8:
    case VK_NUMPAD9:
    case VK_DIVIDE:
    case VK_MULTIPLY:
    case VK_SUBTRACT:
    case VK_ADD:
    case VK_DECIMAL:
    case VK_CLEAR:
      keypad = true;
      break;
    default:
      keypad = false;
  }

  return keypad;
}

WebKeyboardEvent::WebKeyboardEvent(HWND hwnd, UINT message, WPARAM wparam,
                                   LPARAM lparam) {
  system_key = false;

  windows_key_code = native_key_code = static_cast<int>(wparam);

  switch (message) {
    case WM_SYSKEYDOWN:
      system_key = true;
    case WM_KEYDOWN:
      type = RAW_KEY_DOWN;
      break;
    case WM_SYSKEYUP:
      system_key = true;
    case WM_KEYUP:
      type = KEY_UP;
      break;
    case WM_IME_CHAR:
      type = CHAR;
      break;
    case WM_SYSCHAR:
      system_key = true;
      type = CHAR;
    case WM_CHAR:
      type = CHAR;
      break;
    default:
      NOTREACHED() << "unexpected native message: " << message;
  }

  memset(&text, 0, sizeof(text));
  memset(&unmodified_text, 0, sizeof(unmodified_text));
  memset(&key_identifier, 0, sizeof(key_identifier));

  if (type == CHAR || type == RAW_KEY_DOWN) {
    text[0] = windows_key_code;
    unmodified_text[0] = windows_key_code;
  }
  if (type != CHAR) {
    std::string key_identifier_str =
        webkit_glue::GetKeyIdentifierForWindowsKeyCode(windows_key_code);
    base::strlcpy(key_identifier, key_identifier_str.c_str(),
                  kIdentifierLengthCap);
  }

  if (GetKeyState(VK_SHIFT) & 0x8000)
    modifiers |= SHIFT_KEY;
  if (GetKeyState(VK_CONTROL) & 0x8000)
    modifiers |= CTRL_KEY;
  if (GetKeyState(VK_MENU) & 0x8000)
    modifiers |= (ALT_KEY | META_KEY);

  if (LOWORD(lparam) > 1)
    modifiers |= IS_AUTO_REPEAT;
  if (IsKeyPad(wparam, lparam))
    modifiers |= IS_KEYPAD;
}

<|endoftext|>


<commit_before>/*
 * Logger.cpp
 *
 *  Created on: 29 Oct 2016
 *      Author: muttley
 */
#include "Logger.h"
#include <iostream>

using namespace std;

int LogLevel = 1;

void LOG(int logLevel, string text)
{
    if (logLevel >= LogLevel)
        cout << text << endl;
}

<commit_msg>Added current date to log messages<commit_after>/*
 * Logger.cpp
 *
 *  Created on: 29 Oct 2016
 *      Author: muttley
 */
#include "Logger.h"
#include <iostream>
#include <ctime>

using namespace std;

int LogLevel = 1;

void LOG(int logLevel, string text)
{
    time_t rawTime;
    tm* timeInfo;
    char buffer[30];

    time(&rawTime);
    timeInfo = localtime(&rawTime);

    strftime(buffer, 30, "[%F %T] ", timeInfo);
    if (logLevel >= LogLevel)
        cout << buffer << text << endl;
}

<|endoftext|>


<commit_before>//
//  Copyright (C) 2014 Novartis Institutes for BioMedical Research
//
//   @@ All Rights Reserved @@
//  This file is part of the RDKit.
//  The contents are covered by the terms of the BSD license
//  which is included in the file license.txt, found at the root
//  of the RDKit source tree.
//
#include <list>
#include <algorithm>
#include <math.h>
#include "SubstructMatchCustom.h"
#include "MaximumCommonSubgraph.h"

namespace RDKit {
    MCSResult findMCS (const std::vector<ROMOL_SPTR>& mols, const MCSParameters* params) {
        MCSParameters p;
        if(0 == params)
            params = &p;
        RDKit::FMCS::MaximumCommonSubgraph fmcs(params);
        return fmcs.find(mols);
    }

    bool MCSProgressCallbackTimeout(const MCSProgressData& stat, const MCSParameters &params, void* userData) {
        unsigned long long* t0 = (unsigned long long*)userData;
        unsigned long long  t  = nanoClock();
        return t - *t0 <= params.Timeout*1000000ULL;
    }

    // PREDEFINED FUNCTORS:

    //=== ATOM COMPARE ========================================================

    bool MCSAtomCompareAny      (const MCSAtomCompareParameters& p, const ROMol& mol1, unsigned int atom1, const ROMol& mol2, unsigned int atom2, void* ) {
        p;
        mol1;
        atom1;
        mol2;
        atom2;    // unused
        return true;
    }

    bool MCSAtomCompareElements (const MCSAtomCompareParameters& p, const ROMol& mol1, unsigned int atom1, const ROMol& mol2, unsigned int atom2, void* ) {
        const Atom& a1 = *mol1.getAtomWithIdx(atom1);
        const Atom& a2 = *mol2.getAtomWithIdx(atom2);
        if(p.MatchValences && a1.getTotalValence() != a2.getTotalValence())
            return false;
        return a1.getAtomicNum() == a2.getAtomicNum();
    }

    bool MCSAtomCompareIsotopes (const MCSAtomCompareParameters& p, const ROMol& mol1, unsigned int atom1, const ROMol& mol2, unsigned int atom2, void* ud) {
        // ignore everything except isotope information:
        //if( ! MCSAtomCompareElements (p, mol1, atom1, mol2, atom2, ud))
        //    return false;
        const Atom& a1 = *mol1.getAtomWithIdx(atom1);
        const Atom& a2 = *mol2.getAtomWithIdx(atom2);
        return a1.getIsotope() == a2.getIsotope();
    }

    //=== BOND COMPARE ========================================================

    class BondMatchOrderMatrix {
        bool MatchMatrix [Bond::OTHER+1] [Bond::OTHER+1];
    public:
        BondMatchOrderMatrix(bool ignoreAromatization) {
            memset(MatchMatrix, 0, sizeof(MatchMatrix));
            for(size_t i=0; i <= Bond::OTHER; i++) { // fill cells of the same and unspecified type
                MatchMatrix[i][i] = true;
                MatchMatrix[Bond::UNSPECIFIED][i] = MatchMatrix[i][Bond::UNSPECIFIED] = true;
                MatchMatrix[Bond::OTHER][i] = MatchMatrix[i][Bond::OTHER] = true;
            }
            if(ignoreAromatization) {
                MatchMatrix[Bond::SINGLE][Bond::AROMATIC] = MatchMatrix[Bond::AROMATIC][Bond::SINGLE] = true;
                MatchMatrix[Bond::SINGLE][Bond::ONEANDAHALF] = MatchMatrix[Bond::ONEANDAHALF][Bond::SINGLE] = true;
                MatchMatrix[Bond::DOUBLE][Bond::TWOANDAHALF] = MatchMatrix[Bond::TWOANDAHALF][Bond::DOUBLE] = true;
                MatchMatrix[Bond::TRIPLE][Bond::THREEANDAHALF] = MatchMatrix[Bond::THREEANDAHALF][Bond::TRIPLE] = true;
                MatchMatrix[Bond::QUADRUPLE][Bond::FOURANDAHALF] = MatchMatrix[Bond::FOURANDAHALF][Bond::QUADRUPLE] = true;
                MatchMatrix[Bond::QUINTUPLE][Bond::FIVEANDAHALF] = MatchMatrix[Bond::FIVEANDAHALF][Bond::QUINTUPLE] = true;
            }
        }
        inline bool isEqual(unsigned i, unsigned j)const {
            return MatchMatrix [i] [j];
        }
    };

    bool checkRingMatch(const MCSBondCompareParameters& p, const ROMol& mol1, unsigned int bond1, const ROMol& mol2, unsigned int bond2, void* v_ringMatchMatrixSet) {
        if(!v_ringMatchMatrixSet)
            throw "v_ringMatchMatrixSet is NULL";   // never
        FMCS::RingMatchTableSet* ringMatchMatrixSet = static_cast<FMCS::RingMatchTableSet*>(v_ringMatchMatrixSet);

        const std::vector<size_t>& ringsIdx1 = ringMatchMatrixSet->getQueryBondRings (bond1); //indeces of rings
        const std::vector<size_t>& ringsIdx2 = ringMatchMatrixSet->getTargetBondRings(&mol2, bond2); //indeces of rings
        bool bond1inRing = !ringsIdx1.empty();
        bool bond2inRing = !ringsIdx2.empty();

        if(bond1inRing != bond2inRing)
            return false;
        if((! bond1inRing) )//the same: && (! bond2inRing))  // both bonds are NOT in rings
            return true;
        // both bonds are in rings
        if(p.CompleteRingsOnly) {
            const RingInfo::VECT_INT_VECT& r1 = mol1.getRingInfo()->bondRings();
            const RingInfo::VECT_INT_VECT& r2 = mol2.getRingInfo()->bondRings();
            // for each query ring contains bond1
            for(std::vector<size_t>::const_iterator r1i = ringsIdx1.begin(); r1i != ringsIdx1.end(); r1i++) {
                const INT_VECT& br1 = r1[*r1i]; // ring contains bond1
                // check all target rings contained bond2
                for(std::vector<size_t>::const_iterator r2i = ringsIdx2.begin(); r2i != ringsIdx2.end(); r2i++) {
                    const INT_VECT& br2 = r2[*r2i]; // ring contains bond2
                    if(br1.size() != br2.size())  // rings are different
                        continue;
                    // compare rings as substructures
                    if(ringMatchMatrixSet->isEqual(&br1, &br2, &mol2))  // EQUAL Rings found
                        return true;
                }
            }
            // all rings are different
            return false;
        } else
            return true; // bond1inRing && bond2inRing;   // both bonds are in rings
    }

    bool MCSBondCompareAny (const MCSBondCompareParameters& p, const ROMol& mol1, unsigned int bond1, const ROMol& mol2, unsigned int bond2, void* ud) {
        p;
        mol1;
        bond1;
        mol2;
        bond2;    // unused
        if(p.RingMatchesRingOnly)
            return checkRingMatch(p, mol1, bond1, mol2, bond2, ud);
        return true;
    }

    bool MCSBondCompareOrder (const MCSBondCompareParameters& p, const ROMol& mol1, unsigned int bond1, const ROMol& mol2, unsigned int bond2, void* ud) {
        static const BondMatchOrderMatrix match(true); // ignore Aromatization
        const Bond* b1 = mol1.getBondWithIdx(bond1);
        const Bond* b2 = mol2.getBondWithIdx(bond2);
        Bond::BondType t1 = b1->getBondType();
        Bond::BondType t2 = b2->getBondType();
        if(match.isEqual(t1,t2)) {
            if(p.RingMatchesRingOnly)
                return checkRingMatch(p, mol1, bond1, mol2, bond2, ud);
            else
                return true;
        }
        return false;
    }

    bool MCSBondCompareOrderExact (const MCSBondCompareParameters& p, const ROMol& mol1, unsigned int bond1, const ROMol& mol2, unsigned int bond2, void* ud) {
        static const BondMatchOrderMatrix match(false); // AROMATIC != SINGLE
        const Bond* b1 = mol1.getBondWithIdx(bond1);
        const Bond* b2 = mol2.getBondWithIdx(bond2);
        Bond::BondType t1 = b1->getBondType();
        Bond::BondType t2 = b2->getBondType();
        if(match.isEqual(t1,t2)) {
            if(p.RingMatchesRingOnly)
                return checkRingMatch(p, mol1, bond1, mol2, bond2, ud);
            else
                return true;
        }
        return false;
    }

}   // namespace RDKit
<commit_msg>remove some compiler warnings; possible minor optimization<commit_after>//
//  Copyright (C) 2014 Novartis Institutes for BioMedical Research
//
//   @@ All Rights Reserved @@
//  This file is part of the RDKit.
//  The contents are covered by the terms of the BSD license
//  which is included in the file license.txt, found at the root
//  of the RDKit source tree.
//
#include <list>
#include <algorithm>
#include <math.h>
#include "SubstructMatchCustom.h"
#include "MaximumCommonSubgraph.h"

namespace RDKit {
    MCSResult findMCS (const std::vector<ROMOL_SPTR>& mols, const MCSParameters* params) {
        MCSParameters p;
        if(0 == params)
            params = &p;
        RDKit::FMCS::MaximumCommonSubgraph fmcs(params);
        return fmcs.find(mols);
    }

    bool MCSProgressCallbackTimeout(const MCSProgressData& stat, const MCSParameters &params, void* userData) {
        unsigned long long* t0 = (unsigned long long*)userData;
        unsigned long long  t  = nanoClock();
        return t - *t0 <= params.Timeout*1000000ULL;
    }

    // PREDEFINED FUNCTORS:

    //=== ATOM COMPARE ========================================================

    bool MCSAtomCompareAny      (const MCSAtomCompareParameters& p, const ROMol& mol1, unsigned int atom1, const ROMol& mol2, unsigned int atom2, void* ) {
        return true;
    }

    bool MCSAtomCompareElements (const MCSAtomCompareParameters& p, const ROMol& mol1, unsigned int atom1, const ROMol& mol2, unsigned int atom2, void* ) {
        const Atom& a1 = *mol1.getAtomWithIdx(atom1);
        const Atom& a2 = *mol2.getAtomWithIdx(atom2);
        if(a1.getAtomicNum() != a2.getAtomicNum())
          return false;
        if(p.MatchValences && a1.getTotalValence() != a2.getTotalValence())
            return false;
        return true;
    }

    bool MCSAtomCompareIsotopes (const MCSAtomCompareParameters& p, const ROMol& mol1, unsigned int atom1, const ROMol& mol2, unsigned int atom2, void* ud) {
        // ignore everything except isotope information:
        //if( ! MCSAtomCompareElements (p, mol1, atom1, mol2, atom2, ud))
        //    return false;
        const Atom& a1 = *mol1.getAtomWithIdx(atom1);
        const Atom& a2 = *mol2.getAtomWithIdx(atom2);
        return a1.getIsotope() == a2.getIsotope();
    }

    //=== BOND COMPARE ========================================================

    class BondMatchOrderMatrix {
        bool MatchMatrix [Bond::OTHER+1] [Bond::OTHER+1];
    public:
        BondMatchOrderMatrix(bool ignoreAromatization) {
            memset(MatchMatrix, 0, sizeof(MatchMatrix));
            for(size_t i=0; i <= Bond::OTHER; i++) { // fill cells of the same and unspecified type
                MatchMatrix[i][i] = true;
                MatchMatrix[Bond::UNSPECIFIED][i] = MatchMatrix[i][Bond::UNSPECIFIED] = true;
                MatchMatrix[Bond::OTHER][i] = MatchMatrix[i][Bond::OTHER] = true;
            }
            if(ignoreAromatization) {
                MatchMatrix[Bond::SINGLE][Bond::AROMATIC] = MatchMatrix[Bond::AROMATIC][Bond::SINGLE] = true;
                MatchMatrix[Bond::SINGLE][Bond::ONEANDAHALF] = MatchMatrix[Bond::ONEANDAHALF][Bond::SINGLE] = true;
                MatchMatrix[Bond::DOUBLE][Bond::TWOANDAHALF] = MatchMatrix[Bond::TWOANDAHALF][Bond::DOUBLE] = true;
                MatchMatrix[Bond::TRIPLE][Bond::THREEANDAHALF] = MatchMatrix[Bond::THREEANDAHALF][Bond::TRIPLE] = true;
                MatchMatrix[Bond::QUADRUPLE][Bond::FOURANDAHALF] = MatchMatrix[Bond::FOURANDAHALF][Bond::QUADRUPLE] = true;
                MatchMatrix[Bond::QUINTUPLE][Bond::FIVEANDAHALF] = MatchMatrix[Bond::FIVEANDAHALF][Bond::QUINTUPLE] = true;
            }
        }
        inline bool isEqual(unsigned i, unsigned j)const {
            return MatchMatrix [i] [j];
        }
    };

    bool checkRingMatch(const MCSBondCompareParameters& p, const ROMol& mol1, unsigned int bond1, const ROMol& mol2, unsigned int bond2, void* v_ringMatchMatrixSet) {
        if(!v_ringMatchMatrixSet)
            throw "v_ringMatchMatrixSet is NULL";   // never
        FMCS::RingMatchTableSet* ringMatchMatrixSet = static_cast<FMCS::RingMatchTableSet*>(v_ringMatchMatrixSet);

        const std::vector<size_t>& ringsIdx1 = ringMatchMatrixSet->getQueryBondRings (bond1); //indeces of rings
        const std::vector<size_t>& ringsIdx2 = ringMatchMatrixSet->getTargetBondRings(&mol2, bond2); //indeces of rings
        bool bond1inRing = !ringsIdx1.empty();
        bool bond2inRing = !ringsIdx2.empty();

        if(bond1inRing != bond2inRing)
            return false;
        if((! bond1inRing) )//the same: && (! bond2inRing))  // both bonds are NOT in rings
            return true;
        // both bonds are in rings
        if(p.CompleteRingsOnly) {
            const RingInfo::VECT_INT_VECT& r1 = mol1.getRingInfo()->bondRings();
            const RingInfo::VECT_INT_VECT& r2 = mol2.getRingInfo()->bondRings();
            // for each query ring contains bond1
            for(std::vector<size_t>::const_iterator r1i = ringsIdx1.begin(); r1i != ringsIdx1.end(); r1i++) {
                const INT_VECT& br1 = r1[*r1i]; // ring contains bond1
                // check all target rings contained bond2
                for(std::vector<size_t>::const_iterator r2i = ringsIdx2.begin(); r2i != ringsIdx2.end(); r2i++) {
                    const INT_VECT& br2 = r2[*r2i]; // ring contains bond2
                    if(br1.size() != br2.size())  // rings are different
                        continue;
                    // compare rings as substructures
                    if(ringMatchMatrixSet->isEqual(&br1, &br2, &mol2))  // EQUAL Rings found
                        return true;
                }
            }
            // all rings are different
            return false;
        } else
            return true; // bond1inRing && bond2inRing;   // both bonds are in rings
    }

    bool MCSBondCompareAny (const MCSBondCompareParameters& p, const ROMol& mol1, unsigned int bond1, const ROMol& mol2, unsigned int bond2, void* ud) {
        if(p.RingMatchesRingOnly)
            return checkRingMatch(p, mol1, bond1, mol2, bond2, ud);
        return true;
    }

    bool MCSBondCompareOrder (const MCSBondCompareParameters& p, const ROMol& mol1, unsigned int bond1, const ROMol& mol2, unsigned int bond2, void* ud) {
        static const BondMatchOrderMatrix match(true); // ignore Aromatization
        const Bond* b1 = mol1.getBondWithIdx(bond1);
        const Bond* b2 = mol2.getBondWithIdx(bond2);
        Bond::BondType t1 = b1->getBondType();
        Bond::BondType t2 = b2->getBondType();
        if(match.isEqual(t1,t2)) {
            if(p.RingMatchesRingOnly)
                return checkRingMatch(p, mol1, bond1, mol2, bond2, ud);
            else
                return true;
        }
        return false;
    }

    bool MCSBondCompareOrderExact (const MCSBondCompareParameters& p, const ROMol& mol1, unsigned int bond1, const ROMol& mol2, unsigned int bond2, void* ud) {
        static const BondMatchOrderMatrix match(false); // AROMATIC != SINGLE
        const Bond* b1 = mol1.getBondWithIdx(bond1);
        const Bond* b2 = mol2.getBondWithIdx(bond2);
        Bond::BondType t1 = b1->getBondType();
        Bond::BondType t2 = b2->getBondType();
        if(match.isEqual(t1,t2)) {
            if(p.RingMatchesRingOnly)
                return checkRingMatch(p, mol1, bond1, mol2, bond2, ud);
            else
                return true;
        }
        return false;
    }

}   // namespace RDKit
<|endoftext|>