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

#include "SkBBoxRecord.h"

void SkBBoxRecord::drawOval(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawOval(rect, paint);
    }
}

void SkBBoxRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
    if (this->transformBounds(rrect.rect(), &paint)) {
        INHERITED::drawRRect(rrect, paint);
    }
}

void SkBBoxRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawRect(rect, paint);
    }
}

void SkBBoxRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
                                const SkPaint& paint) {
    if (this->transformBounds(outer.rect(), &paint)) {
        this->INHERITED::onDrawDRRect(outer, inner, paint);
    }
}

void SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) {
    if (path.isInverseFillType()) {
        // If path is inverse filled, use the current clip bounds as the
        // path's device-space bounding box.
        SkIRect clipBounds;
        if (this->getClipDeviceBounds(&clipBounds)) {
            this->handleBBox(SkRect::Make(clipBounds));
            INHERITED::drawPath(path, paint);
        }
    } else if (this->transformBounds(path.getBounds(), &paint)) {
        INHERITED::drawPath(path, paint);
    }
}

void SkBBoxRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
                              const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pts, SkToInt(count));
    // Small min width value, just to ensure hairline point bounding boxes aren't empty.
    // Even though we know hairline primitives are drawn one pixel wide, we do not use a
    // minimum of 1 because the playback scale factor is unknown at record time. Later
    // outsets will take care of adding additional padding for antialiasing and rounding out
    // to integer device coordinates, guaranteeing that the rasterized pixels will be included
    // in the computed bounds.
    // Note: The device coordinate outset in SkBBoxHierarchyRecord::handleBBox is currently
    // done in the recording coordinate space, which is wrong.
    // http://code.google.com/p/skia/issues/detail?id=1021
    static const SkScalar kMinWidth = 0.01f;
    SkScalar halfStrokeWidth = SkMaxScalar(paint.getStrokeWidth(), kMinWidth) / 2;
    bbox.outset(halfStrokeWidth, halfStrokeWidth);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawPoints(mode, count, pts, paint);
    }
}

void SkBBoxRecord::drawPaint(const SkPaint& paint) {
    SkRect bbox;
    if (this->getClipBounds(&bbox)) {
        if (this->transformBounds(bbox, &paint)) {
            INHERITED::drawPaint(paint);
        }
    }
}

void SkBBoxRecord::clear(SkColor color) {
    SkISize size = this->getDeviceSize();
    SkRect bbox = {0, 0, SkIntToScalar(size.width()), SkIntToScalar(size.height())};
    this->handleBBox(bbox);
    INHERITED::clear(color);
}

void SkBBoxRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                              const SkPaint& paint) {
    SkRect bbox;
    paint.measureText(text, byteLength, &bbox);
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // Vertical and aligned text need to be offset
    if (paint.isVerticalText()) {
        SkScalar h = bbox.fBottom - bbox.fTop;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fTop    -= h / 2;
            bbox.fBottom -= h / 2;
        }
        // Pad top and bottom with max extents from FontMetrics
        bbox.fBottom += metrics.fBottom;
        bbox.fTop += metrics.fTop;
    } else {
        SkScalar w = bbox.fRight - bbox.fLeft;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fLeft  -= w / 2;
            bbox.fRight -= w / 2;
        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
            bbox.fLeft  -= w;
            bbox.fRight -= w;
        }
        // Set vertical bounds to max extents from font metrics
        bbox.fTop = metrics.fTop;
        bbox.fBottom = metrics.fBottom;
    }

    // Pad horizontal bounds on each side by half of max vertical extents (this is sort of
    // arbitrary, but seems to produce reasonable results, if there were a way of getting max
    // glyph X-extents to pad by, that may be better here, but FontMetrics fXMin and fXMax seem
    // incorrect on most platforms (too small in Linux, never even set in Windows).
    SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
    bbox.fLeft  -= pad;
    bbox.fRight += pad;

    bbox.fLeft += x;
    bbox.fRight += x;
    bbox.fTop += y;
    bbox.fBottom += y;
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::onDrawText(text, byteLength, x, y, paint);
    }
}

void SkBBoxRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
                              const SkPaint* paint) {
    SkRect bbox = {left, top, left + bitmap.width(), top + bitmap.height()};
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmap(bitmap, left, top, paint);
    }
}

void SkBBoxRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
                                        const SkRect& dst, const SkPaint* paint,
                                        DrawBitmapRectFlags flags) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapRectToRect(bitmap, src, dst, paint, flags);
    }
}

void SkBBoxRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& mat,
                                    const SkPaint* paint) {
    SkMatrix m = mat;
    SkRect bbox = {0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())};
    m.mapRect(&bbox);
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmapMatrix(bitmap, mat, paint);
    }
}

void SkBBoxRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                  const SkRect& dst, const SkPaint* paint) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapNine(bitmap, center, dst, paint);
    }
}

void SkBBoxRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
                                 const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pos, paint.countText(text, byteLength));
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);
    bbox.fTop += metrics.fTop;
    bbox.fBottom += metrics.fBottom;

    // pad on left and right by half of max vertical glyph extents
    SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
    bbox.fLeft += pad;
    bbox.fRight -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::onDrawPosText(text, byteLength, pos, paint);
    }
}

void SkBBoxRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
                                  SkScalar constY, const SkPaint& paint) {
    size_t numChars = paint.countText(text, byteLength);
    if (numChars == 0) {
        return;
    }

    const SkFlatData* flatPaintData = this->getFlatPaintData(paint);
    WriteTopBot(paint, *flatPaintData);

    SkScalar top = flatPaintData->topBot()[0];
    SkScalar bottom = flatPaintData->topBot()[1];
    SkScalar pad = top - bottom;

    SkRect bbox;
    bbox.fLeft = SK_ScalarMax;
    bbox.fRight = SK_ScalarMin;

    for (size_t i = 0; i < numChars; ++i) {
        if (xpos[i] < bbox.fLeft) {
            bbox.fLeft = xpos[i];
        }
        if (xpos[i] > bbox.fRight) {
            bbox.fRight = xpos[i];
        }
    }

    // pad horizontally by max glyph height
    bbox.fLeft  += pad;
    bbox.fRight -= pad;

    bbox.fTop    = top + constY;
    bbox.fBottom = bottom + constY;

    if (!this->transformBounds(bbox, &paint)) {
        return;
    }
    // This is the equivalent of calling:
    //  INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
    // but we filled our flat paint beforehand so that we could get font metrics.
    drawPosTextHImpl(text, byteLength, xpos, constY, paint, flatPaintData);
}

void SkBBoxRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
                              const SkPaint* paint) {
    SkRect bbox;
    bbox.set(SkIRect::MakeXYWH(left, top, bitmap.width(), bitmap.height()));
    this->handleBBox(bbox); // directly call handleBBox, matrix is ignored
    INHERITED::drawSprite(bitmap, left, top, paint);
}

void SkBBoxRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
                                    const SkMatrix* matrix, const SkPaint& paint) {
    SkRect bbox = path.getBounds();
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // pad out all sides by the max glyph height above baseline
    SkScalar pad = metrics.fTop;
    bbox.fLeft += pad;
    bbox.fRight -= pad;
    bbox.fTop += pad;
    bbox.fBottom -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, paint);
    }
}

void SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount,
                                const SkPoint vertices[], const SkPoint texs[],
                                const SkColor colors[], SkXfermode* xfer,
                                const uint16_t indices[], int indexCount,
                                const SkPaint& paint) {
    SkRect bbox;
    bbox.set(vertices, vertexCount);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawVertices(mode, vertexCount, vertices, texs,
                                colors, xfer, indices, indexCount, paint);
    }
}

void SkBBoxRecord::drawPicture(SkPicture& picture) {
    if (picture.width() > 0 && picture.height() > 0 &&
        this->transformBounds(SkRect::MakeWH(picture.width(), picture.height()), NULL)) {
        INHERITED::drawPicture(picture);
    }
}

bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) {
    SkRect outBounds = bounds;
    outBounds.sort();

    if (paint) {
        // account for stroking, path effects, shadows, etc
        if (paint->canComputeFastBounds()) {
            SkRect temp;
            outBounds = paint->computeFastBounds(outBounds, &temp);
        } else {
            // set bounds to current clip
            if (!this->getClipBounds(&outBounds)) {
                // current clip is empty
                return false;
            }
        }
    }

    if (!outBounds.isEmpty() && !this->quickReject(outBounds)) {
        this->getTotalMatrix().mapRect(&outBounds);
        this->handleBBox(outBounds);
        return true;
    }

    return false;
}
<commit_msg>hack to expand 'pad' to account for very wide glyphs<commit_after>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBBoxRecord.h"

void SkBBoxRecord::drawOval(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawOval(rect, paint);
    }
}

void SkBBoxRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
    if (this->transformBounds(rrect.rect(), &paint)) {
        INHERITED::drawRRect(rrect, paint);
    }
}

void SkBBoxRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
    if (this->transformBounds(rect, &paint)) {
        INHERITED::drawRect(rect, paint);
    }
}

void SkBBoxRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
                                const SkPaint& paint) {
    if (this->transformBounds(outer.rect(), &paint)) {
        this->INHERITED::onDrawDRRect(outer, inner, paint);
    }
}

void SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) {
    if (path.isInverseFillType()) {
        // If path is inverse filled, use the current clip bounds as the
        // path's device-space bounding box.
        SkIRect clipBounds;
        if (this->getClipDeviceBounds(&clipBounds)) {
            this->handleBBox(SkRect::Make(clipBounds));
            INHERITED::drawPath(path, paint);
        }
    } else if (this->transformBounds(path.getBounds(), &paint)) {
        INHERITED::drawPath(path, paint);
    }
}

void SkBBoxRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
                              const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pts, SkToInt(count));
    // Small min width value, just to ensure hairline point bounding boxes aren't empty.
    // Even though we know hairline primitives are drawn one pixel wide, we do not use a
    // minimum of 1 because the playback scale factor is unknown at record time. Later
    // outsets will take care of adding additional padding for antialiasing and rounding out
    // to integer device coordinates, guaranteeing that the rasterized pixels will be included
    // in the computed bounds.
    // Note: The device coordinate outset in SkBBoxHierarchyRecord::handleBBox is currently
    // done in the recording coordinate space, which is wrong.
    // http://code.google.com/p/skia/issues/detail?id=1021
    static const SkScalar kMinWidth = 0.01f;
    SkScalar halfStrokeWidth = SkMaxScalar(paint.getStrokeWidth(), kMinWidth) / 2;
    bbox.outset(halfStrokeWidth, halfStrokeWidth);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawPoints(mode, count, pts, paint);
    }
}

void SkBBoxRecord::drawPaint(const SkPaint& paint) {
    SkRect bbox;
    if (this->getClipBounds(&bbox)) {
        if (this->transformBounds(bbox, &paint)) {
            INHERITED::drawPaint(paint);
        }
    }
}

void SkBBoxRecord::clear(SkColor color) {
    SkISize size = this->getDeviceSize();
    SkRect bbox = {0, 0, SkIntToScalar(size.width()), SkIntToScalar(size.height())};
    this->handleBBox(bbox);
    INHERITED::clear(color);
}

void SkBBoxRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                              const SkPaint& paint) {
    SkRect bbox;
    paint.measureText(text, byteLength, &bbox);
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // Vertical and aligned text need to be offset
    if (paint.isVerticalText()) {
        SkScalar h = bbox.fBottom - bbox.fTop;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fTop    -= h / 2;
            bbox.fBottom -= h / 2;
        }
        // Pad top and bottom with max extents from FontMetrics
        bbox.fBottom += metrics.fBottom;
        bbox.fTop += metrics.fTop;
    } else {
        SkScalar w = bbox.fRight - bbox.fLeft;
        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
            bbox.fLeft  -= w / 2;
            bbox.fRight -= w / 2;
        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
            bbox.fLeft  -= w;
            bbox.fRight -= w;
        }
        // Set vertical bounds to max extents from font metrics
        bbox.fTop = metrics.fTop;
        bbox.fBottom = metrics.fBottom;
    }

    // Pad horizontal bounds on each side by half of max vertical extents (this is sort of
    // arbitrary, but seems to produce reasonable results, if there were a way of getting max
    // glyph X-extents to pad by, that may be better here, but FontMetrics fXMin and fXMax seem
    // incorrect on most platforms (too small in Linux, never even set in Windows).
    SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
    bbox.fLeft  -= pad;
    bbox.fRight += pad;

    bbox.fLeft += x;
    bbox.fRight += x;
    bbox.fTop += y;
    bbox.fBottom += y;
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::onDrawText(text, byteLength, x, y, paint);
    }
}

void SkBBoxRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
                              const SkPaint* paint) {
    SkRect bbox = {left, top, left + bitmap.width(), top + bitmap.height()};
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmap(bitmap, left, top, paint);
    }
}

void SkBBoxRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
                                        const SkRect& dst, const SkPaint* paint,
                                        DrawBitmapRectFlags flags) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapRectToRect(bitmap, src, dst, paint, flags);
    }
}

void SkBBoxRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& mat,
                                    const SkPaint* paint) {
    SkMatrix m = mat;
    SkRect bbox = {0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())};
    m.mapRect(&bbox);
    if (this->transformBounds(bbox, paint)) {
        INHERITED::drawBitmapMatrix(bitmap, mat, paint);
    }
}

void SkBBoxRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                  const SkRect& dst, const SkPaint* paint) {
    if (this->transformBounds(dst, paint)) {
        INHERITED::drawBitmapNine(bitmap, center, dst, paint);
    }
}

// Hack to work-around https://code.google.com/p/chromium/issues/detail?id=373785
// This logic assums that 'pad' is enough to add to the left and right to account for
// big glyphs. For the font in question (a logo font) the glyphs is much wider than just
// the pointsize (approx 3x wider).
// As a temp work-around, we scale-up pad.
// A more correct fix might be to add fontmetrics.fMaxX, but we don't have that value in hand
// at the moment, and (possibly) the value in the font may not be accurate (but who knows).
//
static SkScalar hack_373785_amend_pad(SkScalar pad) {
    return pad * 4;
}

void SkBBoxRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
                                 const SkPaint& paint) {
    SkRect bbox;
    bbox.set(pos, paint.countText(text, byteLength));
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);
    bbox.fTop += metrics.fTop;
    bbox.fBottom += metrics.fBottom;

    // pad on left and right by half of max vertical glyph extents
    SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
    pad = hack_373785_amend_pad(pad);
    bbox.fLeft += pad;
    bbox.fRight -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::onDrawPosText(text, byteLength, pos, paint);
    }
}

void SkBBoxRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
                                  SkScalar constY, const SkPaint& paint) {
    size_t numChars = paint.countText(text, byteLength);
    if (numChars == 0) {
        return;
    }

    const SkFlatData* flatPaintData = this->getFlatPaintData(paint);
    WriteTopBot(paint, *flatPaintData);

    SkScalar top = flatPaintData->topBot()[0];
    SkScalar bottom = flatPaintData->topBot()[1];
    SkScalar pad = top - bottom;

    SkRect bbox;
    bbox.fLeft = SK_ScalarMax;
    bbox.fRight = SK_ScalarMin;

    for (size_t i = 0; i < numChars; ++i) {
        if (xpos[i] < bbox.fLeft) {
            bbox.fLeft = xpos[i];
        }
        if (xpos[i] > bbox.fRight) {
            bbox.fRight = xpos[i];
        }
    }

    // pad horizontally by max glyph height
    pad = hack_373785_amend_pad(pad);
    bbox.fLeft  += pad;
    bbox.fRight -= pad;

    bbox.fTop    = top + constY;
    bbox.fBottom = bottom + constY;

    if (!this->transformBounds(bbox, &paint)) {
        return;
    }
    // This is the equivalent of calling:
    //  INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
    // but we filled our flat paint beforehand so that we could get font metrics.
    drawPosTextHImpl(text, byteLength, xpos, constY, paint, flatPaintData);
}

void SkBBoxRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
                              const SkPaint* paint) {
    SkRect bbox;
    bbox.set(SkIRect::MakeXYWH(left, top, bitmap.width(), bitmap.height()));
    this->handleBBox(bbox); // directly call handleBBox, matrix is ignored
    INHERITED::drawSprite(bitmap, left, top, paint);
}

void SkBBoxRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
                                    const SkMatrix* matrix, const SkPaint& paint) {
    SkRect bbox = path.getBounds();
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    // pad out all sides by the max glyph height above baseline
    SkScalar pad = metrics.fTop;
    bbox.fLeft += pad;
    bbox.fRight -= pad;
    bbox.fTop += pad;
    bbox.fBottom -= pad;

    if (this->transformBounds(bbox, &paint)) {
        INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, paint);
    }
}

void SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount,
                                const SkPoint vertices[], const SkPoint texs[],
                                const SkColor colors[], SkXfermode* xfer,
                                const uint16_t indices[], int indexCount,
                                const SkPaint& paint) {
    SkRect bbox;
    bbox.set(vertices, vertexCount);
    if (this->transformBounds(bbox, &paint)) {
        INHERITED::drawVertices(mode, vertexCount, vertices, texs,
                                colors, xfer, indices, indexCount, paint);
    }
}

void SkBBoxRecord::drawPicture(SkPicture& picture) {
    if (picture.width() > 0 && picture.height() > 0 &&
        this->transformBounds(SkRect::MakeWH(picture.width(), picture.height()), NULL)) {
        INHERITED::drawPicture(picture);
    }
}

bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) {
    SkRect outBounds = bounds;
    outBounds.sort();

    if (paint) {
        // account for stroking, path effects, shadows, etc
        if (paint->canComputeFastBounds()) {
            SkRect temp;
            outBounds = paint->computeFastBounds(outBounds, &temp);
        } else {
            // set bounds to current clip
            if (!this->getClipBounds(&outBounds)) {
                // current clip is empty
                return false;
            }
        }
    }

    if (!outBounds.isEmpty() && !this->quickReject(outBounds)) {
        this->getTotalMatrix().mapRect(&outBounds);
        this->handleBBox(outBounds);
        return true;
    }

    return false;
}
<|endoftext|>


<commit_before>/*
 * =====================================================================================
 *
 *       Filename:  file_utils.cpp
 *
 *    Description:  A collection of helper functions related to file operations
 *
 *        Version:  1.0
 *        Created:  12/15/2014 11:37:05 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Mohamed Ashraf (m0hamed)
 *   Organization:  GUC
 *
 * =====================================================================================
 */
#include "file_utils.h"
#include <dirent.h>

bool file_exists(string path) {
  if (FILE *file = fopen(path.c_str(), "r")) {
    fclose(file);
    return true;
  } else {
    return false;
  }
}

vector<string> get_files_in_directory(string path) {
  DIR *dir;
  struct dirent *ent;
  vector<string> files;
  if ((dir = opendir(path.c_str())) != NULL) {
    /* print all the files and directories within directory */
    while ((ent = readdir(dir)) != NULL) {
      files.push_back(ent->d_name);
    }
    closedir(dir);
  }
  return files;
}
<commit_msg>Removed dotfiles from file listing<commit_after>/*
 * =====================================================================================
 *
 *       Filename:  file_utils.cpp
 *
 *    Description:  A collection of helper functions related to file operations
 *
 *        Version:  1.0
 *        Created:  12/15/2014 11:37:05 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Mohamed Ashraf (m0hamed)
 *   Organization:  GUC
 *
 * =====================================================================================
 */
#include "file_utils.h"
#include <dirent.h>

bool file_exists(string path) {
  if (FILE *file = fopen(path.c_str(), "r")) {
    fclose(file);
    return true;
  } else {
    return false;
  }
}

vector<string> get_files_in_directory(string path) {
  DIR *dir;
  struct dirent *ent;
  vector<string> files;
  if ((dir = opendir(path.c_str())) != NULL) {
    /* print all the files and directories within directory */
    while ((ent = readdir(dir)) != NULL) {
      if (ent->d_name[0] != '.') { // remove hidden files
        files.push_back(path + ent->d_name);
      }
    }
    closedir(dir);
  }
  return files;
}
<|endoftext|>


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

#include "NodeRippleLikeBlockchainExplorer.h"
#include <api/RippleConfigurationDefaults.hpp>
#include <api/Configuration.hpp>
#include <rapidjson/document.h>
#include <wallet/currencies.hpp>

namespace ledger {
    namespace core {
        NodeRippleLikeBlockchainExplorer::NodeRippleLikeBlockchainExplorer(
                const std::shared_ptr<api::ExecutionContext> &context,
                const std::shared_ptr<HttpClient> &http,
                const api::RippleLikeNetworkParameters &parameters,
                const std::shared_ptr<api::DynamicObject> &configuration) :
                DedicatedContext(context),
                RippleLikeBlockchainExplorer(configuration, {api::Configuration::BLOCKCHAIN_EXPLORER_API_ENDPOINT}) {
            _http = http;
            _parameters = parameters;
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getBalance(const std::vector<RippleLikeKeychain::Address> &addresses) {
            auto size = addresses.size();
            if (size != 1) {
                throw make_exception(api::ErrorCode::INVALID_ARGUMENT,
                                     "Can only get balance of 1 address from Ripple Node, but got {} addresses", addresses.size());
            }
            std::string addressesStr = addresses[0]->toBase58();
            return getAccountInfo(addressesStr, "Balance", BigInt::ZERO);
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getSequence(const std::string &address) {
            return getAccountInfo(address, "Sequence", BigInt::ZERO);
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getFees() {
            return getServerState("base_fee");
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getBaseReserve() {
            return getServerState("reserve_base");
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getLedgerSequence() {
            return getServerState("seq");
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getServerState(const std::string &field) {
            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("server_state");
            auto requestBody = bodyRequest.getString();
            bool parseNumberAsString = true;
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .json(parseNumberAsString).mapPtr<BigInt>(getContext(), [field](const HttpRequest::JsonResult &result) {
                        auto &json = *std::get<1>(result);
                        //Is there a result field ?
                        if (!json.IsObject() || !json.HasMember("result") ||
                            !json["result"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR,
                                                 "Failed to get base reserve from network, no (or malformed) field \"result\" in response");
                        }

                        //Is there an info field ?
                        auto resultObj = json["result"].GetObject();
                        if (!resultObj.HasMember("state") || !resultObj["state"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR,
                                                 "Failed to get base reserve from network, no (or malformed) field \"state\" in response");
                        }

                        //Is there a validated_ledger field ?
                        auto infoObj = resultObj["state"].GetObject();
                        if (!infoObj.HasMember("validated_ledger") || !infoObj["validated_ledger"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR,
                                                 "Failed to get base reserve from network, no (or malformed) field \"validated_ledger\" in response");
                        }

                        auto reserveObj = infoObj["validated_ledger"].GetObject();
                        if (!reserveObj.HasMember(field.c_str()) || !reserveObj[field.c_str()].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR,
                                                 fmt::format("Failed to get {} from network, no (or malformed) field \"{}\" in response", field, field));
                        }
                        auto value = reserveObj[field.c_str()].GetString();
                        return std::make_shared<BigInt>(value);
                    });
        }

        Future<String>
        NodeRippleLikeBlockchainExplorer::pushLedgerApiTransaction(const std::vector<uint8_t> &transaction) {
            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("submit");
            bodyRequest.pushParameter("tx_blob", hex::toString(transaction));
            auto requestBody = bodyRequest.getString();
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .json().template map<String>(getExplorerContext(), [](const HttpRequest::JsonResult &result) -> String {
                        auto &json = *std::get<1>(result);
                        if (!json.IsObject() || !json.HasMember("result") ||
                            !json["result"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to broadcast transaction, no (or malformed) field \"result\" in response");
                        }

                        auto resultObj = json["result"].GetObject();

                        if (resultObj.HasMember("engine_result") &&
                            (resultObj["engine_result"] == "tesSUCCESS" ||
                             resultObj["engine_result"] == "terQUEUED")) {
                          // Check presence of tx_json field
                          if (!resultObj.HasMember("tx_json") || !resultObj["tx_json"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to broadcast transaction, no (or malformed) field \"tx_json\" in response");
                          }
                          auto txnObj = resultObj["tx_json"].GetObject();

                          // Check presence of hash field
                          if (!txnObj.HasMember("hash") || !txnObj["hash"].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to broadcast transaction, no (or malformed) field \"hash\" in response");
                          }

                          return txnObj["hash"].GetString();
                        }

                        throw make_exception(api::ErrorCode::HTTP_ERROR,
                                             "Failed to broadcast transaction: {}",
                                             resultObj["engine_result"].GetString());
                    });
        }

        Future<void *> NodeRippleLikeBlockchainExplorer::startSession() {
            return Future<void *>::successful(new std::string("", 0));
        }

        Future<Unit> NodeRippleLikeBlockchainExplorer::killSession(void *session) {
            return Future<Unit>::successful(unit);
        }

        Future<Bytes> NodeRippleLikeBlockchainExplorer::getRawTransaction(const String &transactionHash) {
            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("tx");
            bodyRequest.pushParameter("transaction", transactionHash);
            bodyRequest.pushParameter("binary", "true");
            auto requestBody = bodyRequest.getString();
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .json().template map<Bytes>(getExplorerContext(), [](const HttpRequest::JsonResult &result) -> Bytes {
                        auto &json = *std::get<1>(result);
                        if (!json.IsObject() || !json.HasMember("result") ||
                            !json["result"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get raw transaction, no (or malformed) field \"result\" in response");
                        }
                        //Is there a tx field ?
                        auto resultObj = json["result"].GetObject();
                        if (!resultObj.HasMember("tx") || !resultObj["tx"].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get raw transaction, no (or malformed) field \"tx\" in response");
                        }
                        return Bytes(hex::toByteArray(std::string(resultObj["tx"].GetString(), resultObj["tx"].GetStringLength())));
                    });
        }

        Future<String> NodeRippleLikeBlockchainExplorer::pushTransaction(const std::vector<uint8_t> &transaction) {
            return pushLedgerApiTransaction(transaction);
        }

        FuturePtr<RippleLikeBlockchainExplorer::TransactionsBulk>
        NodeRippleLikeBlockchainExplorer::getTransactions(
            const std::vector<std::string> &addresses,
            Option<std::string> fromBlockHash,
            Option<void *> session
        ) {
            if (addresses.size() != 1) {
                throw make_exception(api::ErrorCode::INVALID_ARGUMENT,
                                     "Can only get transactions for 1 address from Ripple Node, but got {} addresses", addresses.size());
            }

            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("account_tx");
            bodyRequest.pushParameter("account", addresses[0]);
            if (fromBlockHash.hasValue() && _paginationMarker.empty()) {
                bodyRequest.pushParameter("ledger_index_min", fromBlockHash.getValue());
            }

            // handle transaction pagination in the case we have a pagination marker, which happens
            // when a getTransactions returns a TransactionsBulk containing such a marker
            if (!_paginationMarker.empty()) {
                auto marker = strings::split(_paginationMarker, "-");
                bodyRequest.pushPagination(marker[0], marker[1]);
            }

            auto requestBody = bodyRequest.getString();
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};

            auto self = shared_from_this();

            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .template json<TransactionsBulk, Exception>(
                            LedgerApiParser<TransactionsBulk, RippleLikeTransactionsBulkParser>())
                    .template mapPtr<TransactionsBulk>(getExplorerContext(), [self, fromBlockHash](
                            const Either<Exception, std::shared_ptr<TransactionsBulk>> &result) {
                        if (result.isLeft()) {
                            // Only case where we should emit block not found error
                            if (!fromBlockHash.isEmpty() && result.getLeft().getErrorCode() == api::ErrorCode::HTTP_ERROR) {
                                throw make_exception(api::ErrorCode::BLOCK_NOT_FOUND, "Unable to find block with hash {}", fromBlockHash.getValue());
                            } else {
                                throw result.getLeft();
                            }
                        } else {
                            // handle pagination if a pagination marker is present
                            auto bulk = result.getRight();

                            if (!bulk->paginationMarker.empty()) {
                                bulk->hasNext = true;
                                self->_paginationMarker = bulk->paginationMarker;
                            } else {
                                self->_paginationMarker = "";
                            }

                            return bulk;
                        }
                    });
        }

        FuturePtr<Block> NodeRippleLikeBlockchainExplorer::getCurrentBlock() const {
            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("ledger");
            bodyRequest.pushParameter("ledger_index", std::string("validated"));
            auto requestBody = bodyRequest.getString();
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .template json<Block, Exception>(LedgerApiParser<Block, RippleLikeBlockParser>())
                    .template mapPtr<Block>(getExplorerContext(),
                                                   [](const Either<Exception, std::shared_ptr<Block>> &result) {
                                                       if (result.isLeft()) {
                                                           throw result.getLeft();
                                                       } else {
                                                           return result.getRight();
                                                       }
                                                   });
        }

        FuturePtr<RippleLikeBlockchainExplorerTransaction>
        NodeRippleLikeBlockchainExplorer::getTransactionByHash(const String &transactionHash) const {
            return getLedgerApiTransactionByHash(transactionHash);
        }

        Future<int64_t> NodeRippleLikeBlockchainExplorer::getTimestamp() const {
            return getLedgerApiTimestamp();
        }

        std::shared_ptr<api::ExecutionContext> NodeRippleLikeBlockchainExplorer::getExplorerContext() const {
            return _executionContext;
        }

        api::RippleLikeNetworkParameters NodeRippleLikeBlockchainExplorer::getNetworkParameters() const {
            return _parameters;
        }

        std::string NodeRippleLikeBlockchainExplorer::getExplorerVersion() const {
            return "";
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getAccountInfo(const std::string &address,
                                                         const std::string &key,
                                                         const BigInt &defaultValue) {
            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("account_info");
            bodyRequest.pushParameter("account", address);
            bodyRequest.pushParameter("ledger_index", std::string("validated"));
            auto requestBody = bodyRequest.getString();
            bool parseNumberAsString = true;
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .json(parseNumberAsString).mapPtr<BigInt>(getContext(), [address, key, defaultValue](const HttpRequest::JsonResult &result) {
                        auto &json = *std::get<1>(result);
                        //Is there a result field ?
                        if (!json.IsObject() || !json.HasMember("result") ||
                            !json["result"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get {} for {}, no (or malformed) field \"result\" in response",
                                                 key, address);
                        }

                        //Is there an account_data field ?
                        auto resultObj = json["result"].GetObject();
                        if (!resultObj.HasMember("account_data") || !resultObj["account_data"].IsObject()) {
                            // Case of account not found (not activated yet)
                            return std::make_shared<BigInt>(defaultValue);
                        }

                        //Is there an field with key name ?
                        auto accountObj = resultObj["account_data"].GetObject();
                        if (!accountObj.HasMember(key.c_str()) || !accountObj[key.c_str()].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get {} for {}, no (or malformed) field \"{}\" in response",
                                                 key, address, key);
                        }

                        auto value = accountObj[key.c_str()].GetString();
                        return std::make_shared<BigInt>(value);
                    });
        }
    }
}
<commit_msg>Fetch transactions for an account in chronological order<commit_after>/*
 *
 * NodeRippleLikeBlockchainExplorer
 *
 * Created by El Khalil Bellakrid on 09/01/2019.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2019 Ledger
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include "NodeRippleLikeBlockchainExplorer.h"
#include <api/RippleConfigurationDefaults.hpp>
#include <api/Configuration.hpp>
#include <rapidjson/document.h>
#include <wallet/currencies.hpp>

namespace ledger {
    namespace core {
        NodeRippleLikeBlockchainExplorer::NodeRippleLikeBlockchainExplorer(
                const std::shared_ptr<api::ExecutionContext> &context,
                const std::shared_ptr<HttpClient> &http,
                const api::RippleLikeNetworkParameters &parameters,
                const std::shared_ptr<api::DynamicObject> &configuration) :
                DedicatedContext(context),
                RippleLikeBlockchainExplorer(configuration, {api::Configuration::BLOCKCHAIN_EXPLORER_API_ENDPOINT}) {
            _http = http;
            _parameters = parameters;
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getBalance(const std::vector<RippleLikeKeychain::Address> &addresses) {
            auto size = addresses.size();
            if (size != 1) {
                throw make_exception(api::ErrorCode::INVALID_ARGUMENT,
                                     "Can only get balance of 1 address from Ripple Node, but got {} addresses", addresses.size());
            }
            std::string addressesStr = addresses[0]->toBase58();
            return getAccountInfo(addressesStr, "Balance", BigInt::ZERO);
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getSequence(const std::string &address) {
            return getAccountInfo(address, "Sequence", BigInt::ZERO);
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getFees() {
            return getServerState("base_fee");
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getBaseReserve() {
            return getServerState("reserve_base");
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getLedgerSequence() {
            return getServerState("seq");
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getServerState(const std::string &field) {
            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("server_state");
            auto requestBody = bodyRequest.getString();
            bool parseNumberAsString = true;
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .json(parseNumberAsString).mapPtr<BigInt>(getContext(), [field](const HttpRequest::JsonResult &result) {
                        auto &json = *std::get<1>(result);
                        //Is there a result field ?
                        if (!json.IsObject() || !json.HasMember("result") ||
                            !json["result"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR,
                                                 "Failed to get base reserve from network, no (or malformed) field \"result\" in response");
                        }

                        //Is there an info field ?
                        auto resultObj = json["result"].GetObject();
                        if (!resultObj.HasMember("state") || !resultObj["state"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR,
                                                 "Failed to get base reserve from network, no (or malformed) field \"state\" in response");
                        }

                        //Is there a validated_ledger field ?
                        auto infoObj = resultObj["state"].GetObject();
                        if (!infoObj.HasMember("validated_ledger") || !infoObj["validated_ledger"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR,
                                                 "Failed to get base reserve from network, no (or malformed) field \"validated_ledger\" in response");
                        }

                        auto reserveObj = infoObj["validated_ledger"].GetObject();
                        if (!reserveObj.HasMember(field.c_str()) || !reserveObj[field.c_str()].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR,
                                                 fmt::format("Failed to get {} from network, no (or malformed) field \"{}\" in response", field, field));
                        }
                        auto value = reserveObj[field.c_str()].GetString();
                        return std::make_shared<BigInt>(value);
                    });
        }

        Future<String>
        NodeRippleLikeBlockchainExplorer::pushLedgerApiTransaction(const std::vector<uint8_t> &transaction) {
            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("submit");
            bodyRequest.pushParameter("tx_blob", hex::toString(transaction));
            auto requestBody = bodyRequest.getString();
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .json().template map<String>(getExplorerContext(), [](const HttpRequest::JsonResult &result) -> String {
                        auto &json = *std::get<1>(result);
                        if (!json.IsObject() || !json.HasMember("result") ||
                            !json["result"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to broadcast transaction, no (or malformed) field \"result\" in response");
                        }

                        auto resultObj = json["result"].GetObject();

                        if (resultObj.HasMember("engine_result") &&
                            (resultObj["engine_result"] == "tesSUCCESS" ||
                             resultObj["engine_result"] == "terQUEUED")) {
                          // Check presence of tx_json field
                          if (!resultObj.HasMember("tx_json") || !resultObj["tx_json"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to broadcast transaction, no (or malformed) field \"tx_json\" in response");
                          }
                          auto txnObj = resultObj["tx_json"].GetObject();

                          // Check presence of hash field
                          if (!txnObj.HasMember("hash") || !txnObj["hash"].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to broadcast transaction, no (or malformed) field \"hash\" in response");
                          }

                          return txnObj["hash"].GetString();
                        }

                        throw make_exception(api::ErrorCode::HTTP_ERROR,
                                             "Failed to broadcast transaction: {}",
                                             resultObj["engine_result"].GetString());
                    });
        }

        Future<void *> NodeRippleLikeBlockchainExplorer::startSession() {
            return Future<void *>::successful(new std::string("", 0));
        }

        Future<Unit> NodeRippleLikeBlockchainExplorer::killSession(void *session) {
            return Future<Unit>::successful(unit);
        }

        Future<Bytes> NodeRippleLikeBlockchainExplorer::getRawTransaction(const String &transactionHash) {
            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("tx");
            bodyRequest.pushParameter("transaction", transactionHash);
            bodyRequest.pushParameter("binary", "true");
            auto requestBody = bodyRequest.getString();
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .json().template map<Bytes>(getExplorerContext(), [](const HttpRequest::JsonResult &result) -> Bytes {
                        auto &json = *std::get<1>(result);
                        if (!json.IsObject() || !json.HasMember("result") ||
                            !json["result"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get raw transaction, no (or malformed) field \"result\" in response");
                        }
                        //Is there a tx field ?
                        auto resultObj = json["result"].GetObject();
                        if (!resultObj.HasMember("tx") || !resultObj["tx"].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get raw transaction, no (or malformed) field \"tx\" in response");
                        }
                        return Bytes(hex::toByteArray(std::string(resultObj["tx"].GetString(), resultObj["tx"].GetStringLength())));
                    });
        }

        Future<String> NodeRippleLikeBlockchainExplorer::pushTransaction(const std::vector<uint8_t> &transaction) {
            return pushLedgerApiTransaction(transaction);
        }

        FuturePtr<RippleLikeBlockchainExplorer::TransactionsBulk>
        NodeRippleLikeBlockchainExplorer::getTransactions(
            const std::vector<std::string> &addresses,
            Option<std::string> fromBlockHash,
            Option<void *> session
        ) {
            if (addresses.size() != 1) {
                throw make_exception(api::ErrorCode::INVALID_ARGUMENT,
                                     "Can only get transactions for 1 address from Ripple Node, but got {} addresses", addresses.size());
            }

            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("account_tx");
            bodyRequest.pushParameter("account", addresses[0]);
            bodyRequest.pushParameter("forward", true);
            if (fromBlockHash.hasValue() && _paginationMarker.empty()) {
                bodyRequest.pushParameter("ledger_index_min", fromBlockHash.getValue());
            }

            // handle transaction pagination in the case we have a pagination marker, which happens
            // when a getTransactions returns a TransactionsBulk containing such a marker
            if (!_paginationMarker.empty()) {
                auto marker = strings::split(_paginationMarker, "-");
                bodyRequest.pushPagination(marker[0], marker[1]);
            }

            auto requestBody = bodyRequest.getString();
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};

            auto self = shared_from_this();

            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .template json<TransactionsBulk, Exception>(
                            LedgerApiParser<TransactionsBulk, RippleLikeTransactionsBulkParser>())
                    .template mapPtr<TransactionsBulk>(getExplorerContext(), [self, fromBlockHash](
                            const Either<Exception, std::shared_ptr<TransactionsBulk>> &result) {
                        if (result.isLeft()) {
                            // Only case where we should emit block not found error
                            if (!fromBlockHash.isEmpty() && result.getLeft().getErrorCode() == api::ErrorCode::HTTP_ERROR) {
                                throw make_exception(api::ErrorCode::BLOCK_NOT_FOUND, "Unable to find block with hash {}", fromBlockHash.getValue());
                            } else {
                                throw result.getLeft();
                            }
                        } else {
                            // handle pagination if a pagination marker is present
                            auto bulk = result.getRight();

                            if (!bulk->paginationMarker.empty()) {
                                bulk->hasNext = true;
                                self->_paginationMarker = bulk->paginationMarker;
                            } else {
                                self->_paginationMarker = "";
                            }

                            return bulk;
                        }
                    });
        }

        FuturePtr<Block> NodeRippleLikeBlockchainExplorer::getCurrentBlock() const {
            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("ledger");
            bodyRequest.pushParameter("ledger_index", std::string("validated"));
            auto requestBody = bodyRequest.getString();
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .template json<Block, Exception>(LedgerApiParser<Block, RippleLikeBlockParser>())
                    .template mapPtr<Block>(getExplorerContext(),
                                                   [](const Either<Exception, std::shared_ptr<Block>> &result) {
                                                       if (result.isLeft()) {
                                                           throw result.getLeft();
                                                       } else {
                                                           return result.getRight();
                                                       }
                                                   });
        }

        FuturePtr<RippleLikeBlockchainExplorerTransaction>
        NodeRippleLikeBlockchainExplorer::getTransactionByHash(const String &transactionHash) const {
            return getLedgerApiTransactionByHash(transactionHash);
        }

        Future<int64_t> NodeRippleLikeBlockchainExplorer::getTimestamp() const {
            return getLedgerApiTimestamp();
        }

        std::shared_ptr<api::ExecutionContext> NodeRippleLikeBlockchainExplorer::getExplorerContext() const {
            return _executionContext;
        }

        api::RippleLikeNetworkParameters NodeRippleLikeBlockchainExplorer::getNetworkParameters() const {
            return _parameters;
        }

        std::string NodeRippleLikeBlockchainExplorer::getExplorerVersion() const {
            return "";
        }

        Future<std::shared_ptr<BigInt>>
        NodeRippleLikeBlockchainExplorer::getAccountInfo(const std::string &address,
                                                         const std::string &key,
                                                         const BigInt &defaultValue) {
            NodeRippleLikeBodyRequest bodyRequest;
            bodyRequest.setMethod("account_info");
            bodyRequest.pushParameter("account", address);
            bodyRequest.pushParameter("ledger_index", std::string("validated"));
            auto requestBody = bodyRequest.getString();
            bool parseNumberAsString = true;
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST("", std::vector<uint8_t>(requestBody.begin(), requestBody.end()), headers)
                    .json(parseNumberAsString).mapPtr<BigInt>(getContext(), [address, key, defaultValue](const HttpRequest::JsonResult &result) {
                        auto &json = *std::get<1>(result);
                        //Is there a result field ?
                        if (!json.IsObject() || !json.HasMember("result") ||
                            !json["result"].IsObject()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get {} for {}, no (or malformed) field \"result\" in response",
                                                 key, address);
                        }

                        //Is there an account_data field ?
                        auto resultObj = json["result"].GetObject();
                        if (!resultObj.HasMember("account_data") || !resultObj["account_data"].IsObject()) {
                            // Case of account not found (not activated yet)
                            return std::make_shared<BigInt>(defaultValue);
                        }

                        //Is there an field with key name ?
                        auto accountObj = resultObj["account_data"].GetObject();
                        if (!accountObj.HasMember(key.c_str()) || !accountObj[key.c_str()].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get {} for {}, no (or malformed) field \"{}\" in response",
                                                 key, address, key);
                        }

                        auto value = accountObj[key.c_str()].GetString();
                        return std::make_shared<BigInt>(value);
                    });
        }
    }
}
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
 *  Main authors:
 *     Guido Tack <tack@gecode.org>
 *  Modified:
 *     Laurent Perron (lperron@google.com)
 *
 *  Copyright:
 *     Guido Tack, 2007
 *
 *
 *  This file is part of Gecode, the generic constraint
 *  development environment:
 *     http://www.gecode.org
 *
 *  Permission is hereby granted, free of charge, to any person obtaining
 *  a copy of this software and associated documentation files (the
 *  "Software"), to deal in the Software without restriction, including
 *  without limitation the rights to use, copy, modify, merge, publish,
 *  distribute, sublicense, and/or sell copies of the Software, and to
 *  permit persons to whom the Software is furnished to do so, subject to
 *  the following conditions:
 *
 *  The above copyright notice and this permission notice shall be
 *  included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include <iostream>
#include <fstream>
#include <cstring>
#include "base/commandlineflags.h"
#include "base/commandlineflags.h"
#include "base/integral_types.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/stringprintf.h"
#include "flatzinc/flatzinc.h"

DEFINE_int32(log_frequency, 100000, "Search log frequency");
DEFINE_bool(log, false, "Show search log");
DEFINE_bool(all, false, "Search for all solutions");
DEFINE_bool(free, false, "Ignore search annotations");
DEFINE_int32(num_solutions, 0, "Number of solution to search for");
DEFINE_int32(time_limit, 0, "time limit in ms");
DECLARE_bool(log_prefix);

namespace operations_research {
void Run(const std::string& file) {
  FlatZincModel fz_model;
  if (file == "-") {
    fz_model.Parse(std::cin);
  } else {
    fz_model.Parse(file);
  }

  fz_model.Solve(FLAGS_log_frequency,
                 FLAGS_log,
                 FLAGS_all,
                 FLAGS_free,
                 FLAGS_num_solutions,
                 FLAGS_time_limit);
}
}

int main(int argc, char** argv) {
  FLAGS_log_prefix=false;
  google::ParseCommandLineFlags(&argc, &argv, true);
  if (argc <= 1) {
    LOG(ERROR) << "Usage: " << argv[0] << " <file>";
    exit(EXIT_FAILURE);
  }
  operations_research::Run(argv[1]);
  return 0;
}
<commit_msg>support official flags -p, -f, -a<commit_after>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
 *  Main authors:
 *     Guido Tack <tack@gecode.org>
 *  Modified:
 *     Laurent Perron (lperron@google.com)
 *
 *  Copyright:
 *     Guido Tack, 2007
 *
 *
 *  This file is part of Gecode, the generic constraint
 *  development environment:
 *     http://www.gecode.org
 *
 *  Permission is hereby granted, free of charge, to any person obtaining
 *  a copy of this software and associated documentation files (the
 *  "Software"), to deal in the Software without restriction, including
 *  without limitation the rights to use, copy, modify, merge, publish,
 *  distribute, sublicense, and/or sell copies of the Software, and to
 *  permit persons to whom the Software is furnished to do so, subject to
 *  the following conditions:
 *
 *  The above copyright notice and this permission notice shall be
 *  included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include <iostream>
#include <fstream>
#include <cstring>
#include "base/commandlineflags.h"
#include "base/commandlineflags.h"
#include "base/integral_types.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/stringprintf.h"
#include "flatzinc/flatzinc.h"

DEFINE_int32(log_frequency, 100000, "Search log frequency");
DEFINE_bool(log, false, "Show search log");
DEFINE_bool(all, false, "Search for all solutions");
DEFINE_bool(free, false, "Ignore search annotations");
DEFINE_int32(num_solutions, 0, "Number of solution to search for");
DEFINE_int32(time_limit, 0, "time limit in ms");
DEFINE_int32(threads, 0, "threads");
DECLARE_bool(log_prefix);

namespace operations_research {
void Run(const std::string& file) {
  FlatZincModel fz_model;
  if (file == "-") {
    fz_model.Parse(std::cin);
  } else {
    fz_model.Parse(file);
  }

  fz_model.Solve(FLAGS_log_frequency,
                 FLAGS_log,
                 FLAGS_all,
                 FLAGS_free,
                 FLAGS_num_solutions,
                 FLAGS_time_limit);
}
}

int main(int argc, char** argv) {
  FLAGS_log_prefix=false;
  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "-a") == 0) {
      argv[i] = "--all";
    }
    if (strcmp(argv[i], "-f") == 0) {
      argv[i] = "--free";
    }
    if (strcmp(argv[i], "-p") == 0) {
      argv[i] = "--threads";
    }
  }
  google::ParseCommandLineFlags(&argc, &argv, true);
  if (argc <= 1) {
    LOG(ERROR) << "Usage: " << argv[0] << " <file>";
    exit(EXIT_FAILURE);
  }
  operations_research::Run(argv[1]);
  return 0;
}
<|endoftext|>


<commit_before>#ifndef KEYCODE_HPP
#define KEYCODE_HPP

namespace org_pqrs_KeyRemap4MacBook {
  class KeyCode;
  class Flags;
  class Buttons;

  // ======================================================================
  class EventType {
  public:
    EventType(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(EventType other) const { return value_ == other.get(); }
    bool operator!=(EventType other) const { return ! (*this == other); }

    bool isKeyDownOrModifierDown(KeyCode key, Flags flags) const;

#include "keycode/output/include.EventType.hpp"

  private:
    unsigned int value_;
  };

  // ======================================================================
  class KeyboardType {
  public:
    KeyboardType(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(KeyboardType other) const { return value_ == other.get(); }
    bool operator!=(KeyboardType other) const { return ! (*this == other); }

#include "keycode/output/include.KeyboardType.hpp"

  private:
    unsigned int value_;
  };

  // ======================================================================
  class ModifierFlag {
  public:
    unsigned int get(void) const { return value_; }
    bool operator==(ModifierFlag other) const { return value_ == other.get(); }
    bool operator!=(ModifierFlag other) const { return ! (*this == other); }

    unsigned int operator~(void) const { return ~value_; }

    KeyCode getKeyCode(void) const;

#include "keycode/output/include.ModifierFlag.hpp"

  private:
    ModifierFlag(unsigned int v) : value_(v) {}
    unsigned int value_;
  };
  class Flags {
  public:
    Flags(unsigned int v = 0) : value_(v) {}
    Flags(ModifierFlag v) : value_(v.get()) {}
    unsigned int get(void) const { return value_; }
    bool operator==(Flags other) const { return value_ == other.get(); }
    bool operator!=(Flags other) const { return ! (*this == other); }

    unsigned int operator~(void) const { return ~value_; }
    Flags operator|(Flags other) const { return value_ | other.get(); }
    Flags operator&(Flags other) const { return value_ & other.get(); }

    Flags& add(Flags flags) { value_ |= flags.get(); return *this; }
    Flags& remove(Flags flags) { value_ &= ~flags; return *this; }
    Flags& stripFN(void)     { return remove(ModifierFlag::FN); }
    Flags& stripCURSOR(void) { return remove(ModifierFlag::CURSOR); }
    Flags& stripKEYPAD(void) { return remove(ModifierFlag::KEYPAD); }
    Flags& stripNONE(void)   { return remove(ModifierFlag::NONE); }
    Flags& stripEXTRA(void) {
      return remove(Flags(ModifierFlag::EXTRA1) |
                    Flags(ModifierFlag::EXTRA2) |
                    Flags(ModifierFlag::EXTRA3) |
                    Flags(ModifierFlag::EXTRA4) |
                    Flags(ModifierFlag::EXTRA5));
    }

    bool isOn(ModifierFlag flag) const {
      return (value_ & flag.get()) == flag.get();
    }
    bool isOn(Flags flags) const {
      if (flags.isOn(ModifierFlag::NONE)) {
        return (value_ | ModifierFlag::NONE.get()) == flags.get();
      } else {
        return (value_ & flags.get()) == flags.get();
      }
    }

  private:
    unsigned int value_;
  };
  inline Flags operator|(ModifierFlag lhs, ModifierFlag rhs) { return lhs.get() | rhs.get(); }

  // ======================================================================
  class KeyCode {
  public:
    KeyCode(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(KeyCode other) const { return value_ == other.get(); }
    bool operator!=(KeyCode other) const { return ! (*this == other); }

    bool operator>(KeyCode other) const { return value_ > other.get(); }
    bool operator>=(KeyCode other) const { return value_ >= other.get(); }

    void normalizeKey(Flags& flags, EventType eventType, KeyboardType keyboardType);
    void reverseNormalizeKey(Flags& flags, EventType eventType, KeyboardType keyboardType);

    ModifierFlag getModifierFlag(void) const;
    bool isModifier(void) const { return getModifierFlag() != ModifierFlag::NONE; }

#include "keycode/output/include.KeyCode.hpp"

    // When FN key and Arrow key were pushed together, another key code was sent (Home,End,PageUp,PageDown or something).
    // We need to change these Home,End,PageUp,PageDown keys to FN+Arrow key before sending key code to remapper.
    // (If we change FN to Control_L, FN+Up-Arrow must be changed to Control_L+Up-Arrow. Not Control_L+PageUp).
    // We also need to change FN+Arrow to Home,End,PageUp,PageDown before outputting key code.
    //
    // This class handles the above.
    class FNKeyHack {
    public:
      FNKeyHack(const KeyCode& fk, const KeyCode& tk) : fromKeyCode_(fk), toKeyCode_(tk), active_normalize_(false), active_reverse_(false) {}
      // FN+PageUp to FN+Up-Arrow
      bool normalize(KeyCode& key, Flags flags, EventType eventType) { return remap(key, flags, eventType, active_normalize_, fromKeyCode_, toKeyCode_); }
      // FN+Up-Arrow to PageUp
      bool reverse(KeyCode& key, Flags flags, EventType eventType) { return remap(key, flags, eventType, active_reverse_, toKeyCode_, fromKeyCode_); }

    private:
      bool remap(KeyCode& key, Flags flags, EventType eventType, bool& active, KeyCode fromKeyCode, KeyCode toKeyCode);

      const KeyCode& fromKeyCode_;
      const KeyCode& toKeyCode_;
      bool active_normalize_;
      bool active_reverse_;
    };

  private:
    unsigned int value_;
  };

  class CharCode {
  public:
    CharCode(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(CharCode other) const { return value_ == other.get(); }
    bool operator!=(CharCode other) const { return ! (*this == other); }

  private:
    unsigned int value_;
  };
  class CharSet {
  public:
    CharSet(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(CharSet other) const { return value_ == other.get(); }
    bool operator!=(CharSet other) const { return ! (*this == other); }

  private:
    unsigned int value_;
  };
  class OrigCharCode {
  public:
    OrigCharCode(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(OrigCharCode other) const { return value_ == other.get(); }
    bool operator!=(OrigCharCode other) const { return ! (*this == other); }

  private:
    unsigned int value_;
  };
  class OrigCharSet {
  public:
    OrigCharSet(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(OrigCharSet other) const { return value_ == other.get(); }
    bool operator!=(OrigCharSet other) const { return ! (*this == other); }

  private:
    unsigned int value_;
  };

  // ======================================================================
  class ConsumerKeyCode {
  public:
    ConsumerKeyCode(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(ConsumerKeyCode other) const { return value_ == other.get(); }
    bool operator!=(ConsumerKeyCode other) const { return ! (*this == other); }

    bool operator>(ConsumerKeyCode other) const { return value_ > other.get(); }
    bool operator>=(ConsumerKeyCode other) const { return value_ >= other.get(); }

#include "keycode/output/include.ConsumerKeyCode.hpp"

  private:
    unsigned int value_;
  };

  // ======================================================================
  class PointingButton {
  public:
    PointingButton(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(PointingButton other) const { return value_ == other.get(); }
    bool operator!=(PointingButton other) const { return ! (*this == other); }

    unsigned int operator~(void) const { return ~value_; }

#include "keycode/output/include.PointingButton.hpp"

  private:
    unsigned int value_;
  };
  class Buttons {
  public:
    Buttons(unsigned int v = 0) : value_(v) {}
    Buttons(PointingButton v) : value_(v.get()) {}
    unsigned int get(void) const { return value_; }
    bool operator==(Buttons other) const { return value_ == other.get(); }
    bool operator!=(Buttons other) const { return ! (*this == other); }

    unsigned int operator~(void) const { return ~value_; }
    Buttons operator|(Buttons other) const { return value_ | other.get(); }

    Buttons& add(Buttons button) { value_ |= button.get(); return *this; }
    Buttons& remove(Buttons button) { value_ &= ~button; return *this; }

    bool isNONE(void) const { return value_ == 0; }
    bool isOn(Buttons buttons) const {
      return (value_ & buttons.get()) == buttons.get();
    }

    Buttons justPressed(Buttons previous) {
      return value_ & ~(previous.get());
    }
    Buttons justReleased(Buttons previous) {
      return ~value_ & (previous.get());
    }

  private:
    unsigned int value_;
  };
  inline Buttons operator|(PointingButton lhs, PointingButton rhs) { return lhs.get() | rhs.get(); }

  // ======================================================================
  typedef unsigned int DeviceVendorID;
  typedef unsigned int DeviceProductID;

  namespace DeviceType {
    enum DeviceType {
      UNKNOWN,

      APPLE_INTERNAL,
      APPLE_EXTERNAL,

      USB_OVERDRIVE,
    };
  }
}

#endif
<commit_msg>update Buttons::justPressed,justReleased<commit_after>#ifndef KEYCODE_HPP
#define KEYCODE_HPP

namespace org_pqrs_KeyRemap4MacBook {
  class KeyCode;
  class Flags;
  class Buttons;

  // ======================================================================
  class EventType {
  public:
    EventType(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(EventType other) const { return value_ == other.get(); }
    bool operator!=(EventType other) const { return ! (*this == other); }

    bool isKeyDownOrModifierDown(KeyCode key, Flags flags) const;

#include "keycode/output/include.EventType.hpp"

  private:
    unsigned int value_;
  };

  // ======================================================================
  class KeyboardType {
  public:
    KeyboardType(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(KeyboardType other) const { return value_ == other.get(); }
    bool operator!=(KeyboardType other) const { return ! (*this == other); }

#include "keycode/output/include.KeyboardType.hpp"

  private:
    unsigned int value_;
  };

  // ======================================================================
  class ModifierFlag {
  public:
    unsigned int get(void) const { return value_; }
    bool operator==(ModifierFlag other) const { return value_ == other.get(); }
    bool operator!=(ModifierFlag other) const { return ! (*this == other); }

    unsigned int operator~(void) const { return ~value_; }

    KeyCode getKeyCode(void) const;

#include "keycode/output/include.ModifierFlag.hpp"

  private:
    ModifierFlag(unsigned int v) : value_(v) {}
    unsigned int value_;
  };
  class Flags {
  public:
    Flags(unsigned int v = 0) : value_(v) {}
    Flags(ModifierFlag v) : value_(v.get()) {}
    unsigned int get(void) const { return value_; }
    bool operator==(Flags other) const { return value_ == other.get(); }
    bool operator!=(Flags other) const { return ! (*this == other); }

    unsigned int operator~(void) const { return ~value_; }
    Flags operator|(Flags other) const { return value_ | other.get(); }
    Flags operator&(Flags other) const { return value_ & other.get(); }

    Flags& add(Flags flags) { value_ |= flags.get(); return *this; }
    Flags& remove(Flags flags) { value_ &= ~flags; return *this; }
    Flags& stripFN(void)     { return remove(ModifierFlag::FN); }
    Flags& stripCURSOR(void) { return remove(ModifierFlag::CURSOR); }
    Flags& stripKEYPAD(void) { return remove(ModifierFlag::KEYPAD); }
    Flags& stripNONE(void)   { return remove(ModifierFlag::NONE); }
    Flags& stripEXTRA(void) {
      return remove(Flags(ModifierFlag::EXTRA1) |
                    Flags(ModifierFlag::EXTRA2) |
                    Flags(ModifierFlag::EXTRA3) |
                    Flags(ModifierFlag::EXTRA4) |
                    Flags(ModifierFlag::EXTRA5));
    }

    bool isOn(ModifierFlag flag) const {
      return (value_ & flag.get()) == flag.get();
    }
    bool isOn(Flags flags) const {
      if (flags.isOn(ModifierFlag::NONE)) {
        return (value_ | ModifierFlag::NONE.get()) == flags.get();
      } else {
        return (value_ & flags.get()) == flags.get();
      }
    }

  private:
    unsigned int value_;
  };
  inline Flags operator|(ModifierFlag lhs, ModifierFlag rhs) { return lhs.get() | rhs.get(); }

  // ======================================================================
  class KeyCode {
  public:
    KeyCode(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(KeyCode other) const { return value_ == other.get(); }
    bool operator!=(KeyCode other) const { return ! (*this == other); }

    bool operator>(KeyCode other) const { return value_ > other.get(); }
    bool operator>=(KeyCode other) const { return value_ >= other.get(); }

    void normalizeKey(Flags& flags, EventType eventType, KeyboardType keyboardType);
    void reverseNormalizeKey(Flags& flags, EventType eventType, KeyboardType keyboardType);

    ModifierFlag getModifierFlag(void) const;
    bool isModifier(void) const { return getModifierFlag() != ModifierFlag::NONE; }

#include "keycode/output/include.KeyCode.hpp"

    // When FN key and Arrow key were pushed together, another key code was sent (Home,End,PageUp,PageDown or something).
    // We need to change these Home,End,PageUp,PageDown keys to FN+Arrow key before sending key code to remapper.
    // (If we change FN to Control_L, FN+Up-Arrow must be changed to Control_L+Up-Arrow. Not Control_L+PageUp).
    // We also need to change FN+Arrow to Home,End,PageUp,PageDown before outputting key code.
    //
    // This class handles the above.
    class FNKeyHack {
    public:
      FNKeyHack(const KeyCode& fk, const KeyCode& tk) : fromKeyCode_(fk), toKeyCode_(tk), active_normalize_(false), active_reverse_(false) {}
      // FN+PageUp to FN+Up-Arrow
      bool normalize(KeyCode& key, Flags flags, EventType eventType) { return remap(key, flags, eventType, active_normalize_, fromKeyCode_, toKeyCode_); }
      // FN+Up-Arrow to PageUp
      bool reverse(KeyCode& key, Flags flags, EventType eventType) { return remap(key, flags, eventType, active_reverse_, toKeyCode_, fromKeyCode_); }

    private:
      bool remap(KeyCode& key, Flags flags, EventType eventType, bool& active, KeyCode fromKeyCode, KeyCode toKeyCode);

      const KeyCode& fromKeyCode_;
      const KeyCode& toKeyCode_;
      bool active_normalize_;
      bool active_reverse_;
    };

  private:
    unsigned int value_;
  };

  class CharCode {
  public:
    CharCode(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(CharCode other) const { return value_ == other.get(); }
    bool operator!=(CharCode other) const { return ! (*this == other); }

  private:
    unsigned int value_;
  };
  class CharSet {
  public:
    CharSet(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(CharSet other) const { return value_ == other.get(); }
    bool operator!=(CharSet other) const { return ! (*this == other); }

  private:
    unsigned int value_;
  };
  class OrigCharCode {
  public:
    OrigCharCode(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(OrigCharCode other) const { return value_ == other.get(); }
    bool operator!=(OrigCharCode other) const { return ! (*this == other); }

  private:
    unsigned int value_;
  };
  class OrigCharSet {
  public:
    OrigCharSet(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(OrigCharSet other) const { return value_ == other.get(); }
    bool operator!=(OrigCharSet other) const { return ! (*this == other); }

  private:
    unsigned int value_;
  };

  // ======================================================================
  class ConsumerKeyCode {
  public:
    ConsumerKeyCode(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(ConsumerKeyCode other) const { return value_ == other.get(); }
    bool operator!=(ConsumerKeyCode other) const { return ! (*this == other); }

    bool operator>(ConsumerKeyCode other) const { return value_ > other.get(); }
    bool operator>=(ConsumerKeyCode other) const { return value_ >= other.get(); }

#include "keycode/output/include.ConsumerKeyCode.hpp"

  private:
    unsigned int value_;
  };

  // ======================================================================
  class PointingButton {
  public:
    PointingButton(unsigned int v = 0) : value_(v) {}
    unsigned int get(void) const { return value_; }
    bool operator==(PointingButton other) const { return value_ == other.get(); }
    bool operator!=(PointingButton other) const { return ! (*this == other); }

    unsigned int operator~(void) const { return ~value_; }

#include "keycode/output/include.PointingButton.hpp"

  private:
    unsigned int value_;
  };
  class Buttons {
  public:
    Buttons(unsigned int v = 0) : value_(v) {}
    Buttons(PointingButton v) : value_(v.get()) {}
    unsigned int get(void) const { return value_; }
    bool operator==(Buttons other) const { return value_ == other.get(); }
    bool operator!=(Buttons other) const { return ! (*this == other); }

    unsigned int operator~(void) const { return ~value_; }
    Buttons operator|(Buttons other) const { return value_ | other.get(); }

    Buttons& add(Buttons button) { value_ |= button.get(); return *this; }
    Buttons& remove(Buttons button) { value_ &= ~button; return *this; }

    bool isNONE(void) const { return value_ == 0; }
    bool isOn(Buttons buttons) const {
      return (value_ & buttons.get()) == buttons.get();
    }

    Buttons justPressed(Buttons previous) const {
      return value_ & ~(previous.get());
    }
    Buttons justReleased(Buttons previous) const {
      return ~value_ & (previous.get());
    }

  private:
    unsigned int value_;
  };
  inline Buttons operator|(PointingButton lhs, PointingButton rhs) { return lhs.get() | rhs.get(); }

  // ======================================================================
  typedef unsigned int DeviceVendorID;
  typedef unsigned int DeviceProductID;

  namespace DeviceType {
    enum DeviceType {
      UNKNOWN,

      APPLE_INTERNAL,
      APPLE_EXTERNAL,

      USB_OVERDRIVE,
    };
  }
}

#endif
<|endoftext|>