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

#include "SkBitmapScaler.h"
#include "SkBitmapFilter.h"
#include "SkConvolver.h"
#include "SkImageInfo.h"
#include "SkPixmap.h"
#include "SkRect.h"
#include "SkTArray.h"

// SkResizeFilter ----------------------------------------------------------------

// Encapsulates computation and storage of the filters required for one complete
// resize operation.
class SkResizeFilter {
public:
    SkResizeFilter(SkBitmapScaler::ResizeMethod method,
                   int srcFullWidth, int srcFullHeight,
                   float destWidth, float destHeight,
                   const SkRect& destSubset,
                   const SkConvolutionProcs& convolveProcs);
    ~SkResizeFilter() { delete fBitmapFilter; }

    // Returns the filled filter values.
    const SkConvolutionFilter1D& xFilter() { return fXFilter; }
    const SkConvolutionFilter1D& yFilter() { return fYFilter; }

private:

    SkBitmapFilter* fBitmapFilter;

    // Computes one set of filters either horizontally or vertically. The caller
    // will specify the "min" and "max" rather than the bottom/top and
    // right/bottom so that the same code can be re-used in each dimension.
    //
    // |srcDependLo| and |srcDependSize| gives the range for the source
    // depend rectangle (horizontally or vertically at the caller's discretion
    // -- see above for what this means).
    //
    // Likewise, the range of destination values to compute and the scale factor
    // for the transform is also specified.

    void computeFilters(int srcSize,
                        float destSubsetLo, float destSubsetSize,
                        float scale,
                        SkConvolutionFilter1D* output,
                        const SkConvolutionProcs& convolveProcs);

    SkConvolutionFilter1D fXFilter;
    SkConvolutionFilter1D fYFilter;
};

SkResizeFilter::SkResizeFilter(SkBitmapScaler::ResizeMethod method,
                               int srcFullWidth, int srcFullHeight,
                               float destWidth, float destHeight,
                               const SkRect& destSubset,
                               const SkConvolutionProcs& convolveProcs) {

    SkASSERT(method >= SkBitmapScaler::RESIZE_FirstMethod &&
             method <= SkBitmapScaler::RESIZE_LastMethod);

    fBitmapFilter = nullptr;
    switch(method) {
        case SkBitmapScaler::RESIZE_BOX:
            fBitmapFilter = new SkBoxFilter;
            break;
        case SkBitmapScaler::RESIZE_TRIANGLE:
            fBitmapFilter = new SkTriangleFilter;
            break;
        case SkBitmapScaler::RESIZE_MITCHELL:
            fBitmapFilter = new SkMitchellFilter;
            break;
        case SkBitmapScaler::RESIZE_HAMMING:
            fBitmapFilter = new SkHammingFilter;
            break;
        case SkBitmapScaler::RESIZE_LANCZOS3:
            fBitmapFilter = new SkLanczosFilter;
            break;
    }

    float scaleX = destWidth / srcFullWidth;
    float scaleY = destHeight / srcFullHeight;

    this->computeFilters(srcFullWidth, destSubset.fLeft, destSubset.width(),
                         scaleX, &fXFilter, convolveProcs);
    if (srcFullWidth == srcFullHeight &&
        destSubset.fLeft == destSubset.fTop &&
        destSubset.width() == destSubset.height()&&
        scaleX == scaleY) {
        fYFilter = fXFilter;
    } else {
        this->computeFilters(srcFullHeight, destSubset.fTop, destSubset.height(),
                          scaleY, &fYFilter, convolveProcs);
    }
}

// TODO(egouriou): Take advantage of periods in the convolution.
// Practical resizing filters are periodic outside of the border area.
// For Lanczos, a scaling by a (reduced) factor of p/q (q pixels in the
// source become p pixels in the destination) will have a period of p.
// A nice consequence is a period of 1 when downscaling by an integral
// factor. Downscaling from typical display resolutions is also bound
// to produce interesting periods as those are chosen to have multiple
// small factors.
// Small periods reduce computational load and improve cache usage if
// the coefficients can be shared. For periods of 1 we can consider
// loading the factors only once outside the borders.
void SkResizeFilter::computeFilters(int srcSize,
                                  float destSubsetLo, float destSubsetSize,
                                  float scale,
                                  SkConvolutionFilter1D* output,
                                  const SkConvolutionProcs& convolveProcs) {
  float destSubsetHi = destSubsetLo + destSubsetSize;  // [lo, hi)

  // When we're doing a magnification, the scale will be larger than one. This
  // means the destination pixels are much smaller than the source pixels, and
  // that the range covered by the filter won't necessarily cover any source
  // pixel boundaries. Therefore, we use these clamped values (max of 1) for
  // some computations.
  float clampedScale = SkTMin(1.0f, scale);

  // This is how many source pixels from the center we need to count
  // to support the filtering function.
  float srcSupport = fBitmapFilter->width() / clampedScale;

  float invScale = 1.0f / scale;

  SkSTArray<64, float, true> filterValuesArray;
  SkSTArray<64, SkConvolutionFilter1D::ConvolutionFixed, true> fixedFilterValuesArray;

  // Loop over all pixels in the output range. We will generate one set of
  // filter values for each one. Those values will tell us how to blend the
  // source pixels to compute the destination pixel.

  // This is the pixel in the source directly under the pixel in the dest.
  // Note that we base computations on the "center" of the pixels. To see
  // why, observe that the destination pixel at coordinates (0, 0) in a 5.0x
  // downscale should "cover" the pixels around the pixel with *its center*
  // at coordinates (2.5, 2.5) in the source, not those around (0, 0).
  // Hence we need to scale coordinates (0.5, 0.5), not (0, 0).
  destSubsetLo = SkScalarFloorToScalar(destSubsetLo);
  destSubsetHi = SkScalarCeilToScalar(destSubsetHi);
  float srcPixel = (destSubsetLo + 0.5f) * invScale;
  int destLimit = SkScalarTruncToInt(destSubsetHi - destSubsetLo);
  output->reserveAdditional(destLimit, SkScalarCeilToInt(destLimit * srcSupport * 2));
  for (int destI = 0; destI < destLimit; srcPixel += invScale, destI++)
  {
    // Compute the (inclusive) range of source pixels the filter covers.
    float srcBegin = SkTMax(0.f, SkScalarFloorToScalar(srcPixel - srcSupport));
    float srcEnd = SkTMin(srcSize - 1.f, SkScalarCeilToScalar(srcPixel + srcSupport));

    // Compute the unnormalized filter value at each location of the source
    // it covers.

    // Sum of the filter values for normalizing.
    // Distance from the center of the filter, this is the filter coordinate
    // in source space. We also need to consider the center of the pixel
    // when comparing distance against 'srcPixel'. In the 5x downscale
    // example used above the distance from the center of the filter to
    // the pixel with coordinates (2, 2) should be 0, because its center
    // is at (2.5, 2.5).
    float destFilterDist = (srcBegin + 0.5f - srcPixel) * clampedScale;
    int filterCount = SkScalarTruncToInt(srcEnd - srcBegin) + 1;
    SkASSERT(filterCount > 0);
    filterValuesArray.reset(filterCount);
    float filterSum = fBitmapFilter->evaluate_n(destFilterDist, clampedScale, filterCount,
                                                filterValuesArray.begin());

    // The filter must be normalized so that we don't affect the brightness of
    // the image. Convert to normalized fixed point.
    int fixedSum = 0;
    fixedFilterValuesArray.reset(filterCount);
    const float* filterValues = filterValuesArray.begin();
    SkConvolutionFilter1D::ConvolutionFixed* fixedFilterValues = fixedFilterValuesArray.begin();
    float invFilterSum = 1 / filterSum;
    for (int fixedI = 0; fixedI < filterCount; fixedI++) {
      int curFixed = SkConvolutionFilter1D::FloatToFixed(filterValues[fixedI] * invFilterSum);
      fixedSum += curFixed;
      fixedFilterValues[fixedI] = SkToS16(curFixed);
    }
    SkASSERT(fixedSum <= 0x7FFF);

    // The conversion to fixed point will leave some rounding errors, which
    // we add back in to avoid affecting the brightness of the image. We
    // arbitrarily add this to the center of the filter array (this won't always
    // be the center of the filter function since it could get clipped on the
    // edges, but it doesn't matter enough to worry about that case).
    int leftovers = SkConvolutionFilter1D::FloatToFixed(1) - fixedSum;
    fixedFilterValues[filterCount / 2] += leftovers;

    // Now it's ready to go.
    output->AddFilter(SkScalarFloorToInt(srcBegin), fixedFilterValues, filterCount);
  }

  if (convolveProcs.fApplySIMDPadding) {
      convolveProcs.fApplySIMDPadding(output);
  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////

static bool valid_for_resize(const SkPixmap& source, int dstW, int dstH) {
    // TODO: Seems like we shouldn't care about the swizzle of source, just that it's 8888
    return source.addr() && source.colorType() == kN32_SkColorType &&
           source.width() >= 1 && source.height() >= 1 && dstW >= 1 && dstH >= 1;
}

bool SkBitmapScaler::Resize(const SkPixmap& result, const SkPixmap& source, ResizeMethod method) {
    if (!valid_for_resize(source, result.width(), result.height())) {
        return false;
    }
    if (!result.addr() || result.colorType() != source.colorType()) {
        return false;
    }

    SkConvolutionProcs convolveProcs= { 0, nullptr, nullptr, nullptr, nullptr };
    PlatformConvolutionProcs(&convolveProcs);

    SkRect destSubset = SkRect::MakeIWH(result.width(), result.height());

    SkResizeFilter filter(method, source.width(), source.height(),
                          result.width(), result.height(), destSubset, convolveProcs);

    // Get a subset encompassing this touched area. We construct the
    // offsets and row strides such that it looks like a new bitmap, while
    // referring to the old data.
    const uint8_t* sourceSubset = reinterpret_cast<const uint8_t*>(source.addr());

    return BGRAConvolve2D(sourceSubset, static_cast<int>(source.rowBytes()),
                          !source.isOpaque(), filter.xFilter(), filter.yFilter(),
                          static_cast<int>(result.rowBytes()),
                          static_cast<unsigned char*>(result.writable_addr()),
                          convolveProcs, true);
}

bool SkBitmapScaler::Resize(SkBitmap* resultPtr, const SkPixmap& source, ResizeMethod method,
                            int destWidth, int destHeight, SkBitmap::Allocator* allocator) {
    // Preflight some of the checks, to avoid allocating the result if we don't need it.
    if (!valid_for_resize(source, destWidth, destHeight)) {
        return false;
    }

    SkBitmap result;
    result.setInfo(SkImageInfo::MakeN32(destWidth, destHeight, source.alphaType()));
    result.allocPixels(allocator, nullptr);

    SkPixmap resultPM;
    if (!result.peekPixels(&resultPM) || !Resize(resultPM, source, method)) {
        return false;
    }

    *resultPtr = result;
    resultPtr->lockPixels();
    SkASSERT(resultPtr->getPixels());
    return true;
}

<commit_msg>exit computeFilters if filter width is zero<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBitmapScaler.h"
#include "SkBitmapFilter.h"
#include "SkConvolver.h"
#include "SkImageInfo.h"
#include "SkPixmap.h"
#include "SkRect.h"
#include "SkTArray.h"

// SkResizeFilter ----------------------------------------------------------------

// Encapsulates computation and storage of the filters required for one complete
// resize operation.
class SkResizeFilter {
public:
    SkResizeFilter(SkBitmapScaler::ResizeMethod method,
                   int srcFullWidth, int srcFullHeight,
                   float destWidth, float destHeight,
                   const SkRect& destSubset,
                   const SkConvolutionProcs& convolveProcs);
    ~SkResizeFilter() { delete fBitmapFilter; }

    // Returns the filled filter values.
    const SkConvolutionFilter1D& xFilter() { return fXFilter; }
    const SkConvolutionFilter1D& yFilter() { return fYFilter; }

private:

    SkBitmapFilter* fBitmapFilter;

    // Computes one set of filters either horizontally or vertically. The caller
    // will specify the "min" and "max" rather than the bottom/top and
    // right/bottom so that the same code can be re-used in each dimension.
    //
    // |srcDependLo| and |srcDependSize| gives the range for the source
    // depend rectangle (horizontally or vertically at the caller's discretion
    // -- see above for what this means).
    //
    // Likewise, the range of destination values to compute and the scale factor
    // for the transform is also specified.

    void computeFilters(int srcSize,
                        float destSubsetLo, float destSubsetSize,
                        float scale,
                        SkConvolutionFilter1D* output,
                        const SkConvolutionProcs& convolveProcs);

    SkConvolutionFilter1D fXFilter;
    SkConvolutionFilter1D fYFilter;
};

SkResizeFilter::SkResizeFilter(SkBitmapScaler::ResizeMethod method,
                               int srcFullWidth, int srcFullHeight,
                               float destWidth, float destHeight,
                               const SkRect& destSubset,
                               const SkConvolutionProcs& convolveProcs) {

    SkASSERT(method >= SkBitmapScaler::RESIZE_FirstMethod &&
             method <= SkBitmapScaler::RESIZE_LastMethod);

    fBitmapFilter = nullptr;
    switch(method) {
        case SkBitmapScaler::RESIZE_BOX:
            fBitmapFilter = new SkBoxFilter;
            break;
        case SkBitmapScaler::RESIZE_TRIANGLE:
            fBitmapFilter = new SkTriangleFilter;
            break;
        case SkBitmapScaler::RESIZE_MITCHELL:
            fBitmapFilter = new SkMitchellFilter;
            break;
        case SkBitmapScaler::RESIZE_HAMMING:
            fBitmapFilter = new SkHammingFilter;
            break;
        case SkBitmapScaler::RESIZE_LANCZOS3:
            fBitmapFilter = new SkLanczosFilter;
            break;
    }

    float scaleX = destWidth / srcFullWidth;
    float scaleY = destHeight / srcFullHeight;

    this->computeFilters(srcFullWidth, destSubset.fLeft, destSubset.width(),
                         scaleX, &fXFilter, convolveProcs);
    if (srcFullWidth == srcFullHeight &&
        destSubset.fLeft == destSubset.fTop &&
        destSubset.width() == destSubset.height()&&
        scaleX == scaleY) {
        fYFilter = fXFilter;
    } else {
        this->computeFilters(srcFullHeight, destSubset.fTop, destSubset.height(),
                          scaleY, &fYFilter, convolveProcs);
    }
}

// TODO(egouriou): Take advantage of periods in the convolution.
// Practical resizing filters are periodic outside of the border area.
// For Lanczos, a scaling by a (reduced) factor of p/q (q pixels in the
// source become p pixels in the destination) will have a period of p.
// A nice consequence is a period of 1 when downscaling by an integral
// factor. Downscaling from typical display resolutions is also bound
// to produce interesting periods as those are chosen to have multiple
// small factors.
// Small periods reduce computational load and improve cache usage if
// the coefficients can be shared. For periods of 1 we can consider
// loading the factors only once outside the borders.
void SkResizeFilter::computeFilters(int srcSize,
                                  float destSubsetLo, float destSubsetSize,
                                  float scale,
                                  SkConvolutionFilter1D* output,
                                  const SkConvolutionProcs& convolveProcs) {
  float destSubsetHi = destSubsetLo + destSubsetSize;  // [lo, hi)

  // When we're doing a magnification, the scale will be larger than one. This
  // means the destination pixels are much smaller than the source pixels, and
  // that the range covered by the filter won't necessarily cover any source
  // pixel boundaries. Therefore, we use these clamped values (max of 1) for
  // some computations.
  float clampedScale = SkTMin(1.0f, scale);

  // This is how many source pixels from the center we need to count
  // to support the filtering function.
  float srcSupport = fBitmapFilter->width() / clampedScale;

  float invScale = 1.0f / scale;

  SkSTArray<64, float, true> filterValuesArray;
  SkSTArray<64, SkConvolutionFilter1D::ConvolutionFixed, true> fixedFilterValuesArray;

  // Loop over all pixels in the output range. We will generate one set of
  // filter values for each one. Those values will tell us how to blend the
  // source pixels to compute the destination pixel.

  // This is the pixel in the source directly under the pixel in the dest.
  // Note that we base computations on the "center" of the pixels. To see
  // why, observe that the destination pixel at coordinates (0, 0) in a 5.0x
  // downscale should "cover" the pixels around the pixel with *its center*
  // at coordinates (2.5, 2.5) in the source, not those around (0, 0).
  // Hence we need to scale coordinates (0.5, 0.5), not (0, 0).
  destSubsetLo = SkScalarFloorToScalar(destSubsetLo);
  destSubsetHi = SkScalarCeilToScalar(destSubsetHi);
  float srcPixel = (destSubsetLo + 0.5f) * invScale;
  int destLimit = SkScalarTruncToInt(destSubsetHi - destSubsetLo);
  output->reserveAdditional(destLimit, SkScalarCeilToInt(destLimit * srcSupport * 2));
  for (int destI = 0; destI < destLimit; srcPixel += invScale, destI++)
  {
    // Compute the (inclusive) range of source pixels the filter covers.
    float srcBegin = SkTMax(0.f, SkScalarFloorToScalar(srcPixel - srcSupport));
    float srcEnd = SkTMin(srcSize - 1.f, SkScalarCeilToScalar(srcPixel + srcSupport));

    // Compute the unnormalized filter value at each location of the source
    // it covers.

    // Sum of the filter values for normalizing.
    // Distance from the center of the filter, this is the filter coordinate
    // in source space. We also need to consider the center of the pixel
    // when comparing distance against 'srcPixel'. In the 5x downscale
    // example used above the distance from the center of the filter to
    // the pixel with coordinates (2, 2) should be 0, because its center
    // is at (2.5, 2.5).
    float destFilterDist = (srcBegin + 0.5f - srcPixel) * clampedScale;
    int filterCount = SkScalarTruncToInt(srcEnd - srcBegin) + 1;
    if (filterCount <= 0) {
        // true when srcSize is equal to srcPixel - srcSupport; this may be a bug
        return;
    }
    filterValuesArray.reset(filterCount);
    float filterSum = fBitmapFilter->evaluate_n(destFilterDist, clampedScale, filterCount,
                                                filterValuesArray.begin());

    // The filter must be normalized so that we don't affect the brightness of
    // the image. Convert to normalized fixed point.
    int fixedSum = 0;
    fixedFilterValuesArray.reset(filterCount);
    const float* filterValues = filterValuesArray.begin();
    SkConvolutionFilter1D::ConvolutionFixed* fixedFilterValues = fixedFilterValuesArray.begin();
    float invFilterSum = 1 / filterSum;
    for (int fixedI = 0; fixedI < filterCount; fixedI++) {
      int curFixed = SkConvolutionFilter1D::FloatToFixed(filterValues[fixedI] * invFilterSum);
      fixedSum += curFixed;
      fixedFilterValues[fixedI] = SkToS16(curFixed);
    }
    SkASSERT(fixedSum <= 0x7FFF);

    // The conversion to fixed point will leave some rounding errors, which
    // we add back in to avoid affecting the brightness of the image. We
    // arbitrarily add this to the center of the filter array (this won't always
    // be the center of the filter function since it could get clipped on the
    // edges, but it doesn't matter enough to worry about that case).
    int leftovers = SkConvolutionFilter1D::FloatToFixed(1) - fixedSum;
    fixedFilterValues[filterCount / 2] += leftovers;

    // Now it's ready to go.
    output->AddFilter(SkScalarFloorToInt(srcBegin), fixedFilterValues, filterCount);
  }

  if (convolveProcs.fApplySIMDPadding) {
      convolveProcs.fApplySIMDPadding(output);
  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////

static bool valid_for_resize(const SkPixmap& source, int dstW, int dstH) {
    // TODO: Seems like we shouldn't care about the swizzle of source, just that it's 8888
    return source.addr() && source.colorType() == kN32_SkColorType &&
           source.width() >= 1 && source.height() >= 1 && dstW >= 1 && dstH >= 1;
}

bool SkBitmapScaler::Resize(const SkPixmap& result, const SkPixmap& source, ResizeMethod method) {
    if (!valid_for_resize(source, result.width(), result.height())) {
        return false;
    }
    if (!result.addr() || result.colorType() != source.colorType()) {
        return false;
    }

    SkConvolutionProcs convolveProcs= { 0, nullptr, nullptr, nullptr, nullptr };
    PlatformConvolutionProcs(&convolveProcs);

    SkRect destSubset = SkRect::MakeIWH(result.width(), result.height());

    SkResizeFilter filter(method, source.width(), source.height(),
                          result.width(), result.height(), destSubset, convolveProcs);

    // Get a subset encompassing this touched area. We construct the
    // offsets and row strides such that it looks like a new bitmap, while
    // referring to the old data.
    const uint8_t* sourceSubset = reinterpret_cast<const uint8_t*>(source.addr());

    return BGRAConvolve2D(sourceSubset, static_cast<int>(source.rowBytes()),
                          !source.isOpaque(), filter.xFilter(), filter.yFilter(),
                          static_cast<int>(result.rowBytes()),
                          static_cast<unsigned char*>(result.writable_addr()),
                          convolveProcs, true);
}

bool SkBitmapScaler::Resize(SkBitmap* resultPtr, const SkPixmap& source, ResizeMethod method,
                            int destWidth, int destHeight, SkBitmap::Allocator* allocator) {
    // Preflight some of the checks, to avoid allocating the result if we don't need it.
    if (!valid_for_resize(source, destWidth, destHeight)) {
        return false;
    }

    SkBitmap result;
    result.setInfo(SkImageInfo::MakeN32(destWidth, destHeight, source.alphaType()));
    result.allocPixels(allocator, nullptr);

    SkPixmap resultPM;
    if (!result.peekPixels(&resultPM) || !Resize(resultPM, source, method)) {
        return false;
    }

    *resultPtr = result;
    resultPtr->lockPixels();
    SkASSERT(resultPtr->getPixels());
    return true;
}

<|endoftext|>


<commit_before>// #undef UNICODE
//
#include <sstream>
#include "logconsole.h"

std::ostream& Core::Color::operator<<(std::ostream& os,
                                      Core::Color::CodeFG code) {
#ifndef _WIN32
  return os << "\033[1;" << static_cast<int>(code) << "m";
#else
  return os;
#endif
}

std::ostream& Core::Color::operator<<(std::ostream& os,
                                      Core::Color::CodeBG code) {
#ifndef _WIN32
  return os << "\033[" << static_cast<int>(code) << "m";
#else
  return os;
#endif
}

namespace Core {

spdlog::level::level_enum CLog::level_ = spdlog::level::notice;

void CLog::SetLevel(spdlog::level::level_enum _level) {
  level_ = _level;

  std::ostringstream format;
  format << "[%H:%M:%S.%e %z] [%L]";

  if (level_ <= spdlog::level::debug) format << " [thread %t]";
  format << " [%n]" << " %v ";
  spdlog::set_pattern(format.str());
}

std::weak_ptr<spdlog::logger> CLog::GetLogger(
    log_type _type) {
  std::weak_ptr<spdlog::logger> logger;
  try
  {
    switch (_type) {
      case log_type::NETWORK:
        logger = spdlog::get("net");
        break;

      case log_type::DATABASE:
        logger = spdlog::get("db");
        break;

      case log_type::GENERAL:
      default:
        logger = spdlog::get("server");
        break;
    }

    if (logger.expired()) {
      std::ostringstream format;
      format << "[%H:%M:%S.%e %z] [%L]";

      if (level_ <= spdlog::level::debug) format << " [thread %t]";
      format << " [%n]" << " %v ";

      size_t q_size = 1048576;
      spdlog::set_async_mode(q_size, spdlog::async_overflow_policy::discard_log_msg,
                             nullptr, std::chrono::seconds(30));

      std::string path, name;

      switch (_type) {
        case log_type::NETWORK: {
          path = "logs/network";
          name = "net";
          break;
        }
        case log_type::DATABASE: {
          path = "logs/database";
          name = "db";
          break;
        }
        case log_type::GENERAL:
        default: {
          path = "logs/server";
          name = "server";
          break;
        }
      }

      std::vector<spdlog::sink_ptr> net_sink;
//      auto console_out = spdlog::sinks::stdout_sink_mt::instance();
#ifdef _WIN32
      auto console_out = spdlog::sinks::stdout_sink_st::instance();
      auto console_sink = std::make_shared<spdlog::sinks::wincolor_sink_mt>(console_out);
#else
      auto console_out = spdlog::sinks::stdout_sink_mt::instance();
      auto console_sink = std::make_shared<spdlog::sinks::ansicolor_sink>(console_out);
#endif
//       auto daily_sink = std::make_shared<spdlog::sinks::daily_file_sink_mt>(
//           path.c_str(), "txt", 23, 59);
      net_sink.push_back(console_sink);
//      net_sink.push_back(daily_sink);

      auto net_logger = std::make_shared<spdlog::logger>(
          name.c_str(), begin(net_sink), end(net_sink));
      net_logger->set_level(level_);
      net_logger->set_pattern(format.str());

      spdlog::register_logger(net_logger);

      return net_logger;
    }
  } catch (const spdlog::spdlog_ex& ex) {
    std::cout << "Log failed: " << ex.what() << std::endl;
  }
  return logger;
}
}
<commit_msg>Added microseconds to the log output<commit_after>// #undef UNICODE
//
#include <sstream>
#include "logconsole.h"

std::ostream& Core::Color::operator<<(std::ostream& os,
                                      Core::Color::CodeFG code) {
#ifndef _WIN32
  return os << "\033[1;" << static_cast<int>(code) << "m";
#else
  return os;
#endif
}

std::ostream& Core::Color::operator<<(std::ostream& os,
                                      Core::Color::CodeBG code) {
#ifndef _WIN32
  return os << "\033[" << static_cast<int>(code) << "m";
#else
  return os;
#endif
}

namespace Core {

spdlog::level::level_enum CLog::level_ = spdlog::level::notice;

void CLog::SetLevel(spdlog::level::level_enum _level) {
  level_ = _level;

  std::ostringstream format;
  format << "[%H:%M:%S.%e %z] [%L]";

  if (level_ <= spdlog::level::debug) format << " [thread %t]";
  format << " [%n]" << " %v ";
  spdlog::set_pattern(format.str());
}

std::weak_ptr<spdlog::logger> CLog::GetLogger(
    log_type _type) {
  std::weak_ptr<spdlog::logger> logger;
  try
  {
    switch (_type) {
      case log_type::NETWORK:
        logger = spdlog::get("net");
        break;

      case log_type::DATABASE:
        logger = spdlog::get("db");
        break;

      case log_type::GENERAL:
      default:
        logger = spdlog::get("server");
        break;
    }

    if (logger.expired()) {
      std::ostringstream format;
      format << "[%H:%M:%S.%e.%f %z] [%L]";

      if (level_ <= spdlog::level::debug) format << " [thread %t]";
      format << " [%n]" << " %v ";

      size_t q_size = 1048576;
      spdlog::set_async_mode(q_size, spdlog::async_overflow_policy::discard_log_msg,
                             nullptr, std::chrono::seconds(30));

      std::string path, name;

      switch (_type) {
        case log_type::NETWORK: {
          path = "logs/network";
          name = "net";
          break;
        }
        case log_type::DATABASE: {
          path = "logs/database";
          name = "db";
          break;
        }
        case log_type::GENERAL:
        default: {
          path = "logs/server";
          name = "server";
          break;
        }
      }

      std::vector<spdlog::sink_ptr> net_sink;
//      auto console_out = spdlog::sinks::stdout_sink_mt::instance();
#ifdef _WIN32
      auto console_out = spdlog::sinks::stdout_sink_st::instance();
      auto console_sink = std::make_shared<spdlog::sinks::wincolor_sink_mt>(console_out);
#else
      auto console_out = spdlog::sinks::stdout_sink_mt::instance();
      auto console_sink = std::make_shared<spdlog::sinks::ansicolor_sink>(console_out);
#endif
//       auto daily_sink = std::make_shared<spdlog::sinks::daily_file_sink_mt>(
//           path.c_str(), "txt", 23, 59);
      net_sink.push_back(console_sink);
//      net_sink.push_back(daily_sink);

      auto net_logger = std::make_shared<spdlog::logger>(
          name.c_str(), begin(net_sink), end(net_sink));
      net_logger->set_level(level_);
      net_logger->set_pattern(format.str());

      spdlog::register_logger(net_logger);

      return net_logger;
    }
  } catch (const spdlog::spdlog_ex& ex) {
    std::cout << "Log failed: " << ex.what() << std::endl;
  }
  return logger;
}
}
<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "strigithread.h"
#include "strigi_thread.h"
#include "strigilogging.h"

#include <string>
#include <cstring>
#include <errno.h>
#include <signal.h>
#include <vector>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/syscall.h>

// define two enums and a constant for use of ioprio
enum {
    IOPRIO_CLASS_NONE,
    IOPRIO_CLASS_RT,
    IOPRIO_CLASS_BE,
    IOPRIO_CLASS_IDLE,
};

enum {
    IOPRIO_WHO_PROCESS = 1,
    IOPRIO_WHO_PGRP,
    IOPRIO_WHO_USER,
};
#define IOPRIO_CLASS_SHIFT  13

using namespace std;

vector<StrigiThread*> threads;

void
StrigiThread::stopThreads() {
    vector<StrigiThread*>::const_iterator i;
    for (i=threads.begin(); i!=threads.end(); ++i) {
        STRIGI_LOG_INFO ("strigi.daemon", string("stopping thread ")
            + (*i)->name);
        (*i)->stop();
        STRIGI_LOG_INFO ("strigi.daemon", "stopped another thread ");
    }
}

extern "C" void
quit_daemon(int signum) {
    STRIGI_LOG_INFO("strigi.daemon", "quit_daemon");
    static int interruptcount = 0;
    vector<StrigiThread*>::const_iterator i;
    switch (++interruptcount) {
    case 1:
        STRIGI_LOG_INFO ("strigi.daemon", "stopping threads ");
        StrigiThread::stopThreads();
        break;
    case 2:
        STRIGI_LOG_INFO ("strigi.daemon", "terminating threads ");
        for (i=threads.begin(); i!=threads.end(); ++i) {
            (*i)->terminate();
        }
        break;
    case 3:
    default:
        STRIGI_LOG_FATAL ("strigi.daemon", "calling exit(1)")
        exit(1);
    }
}

struct sigaction quitaction;
void
set_quit_on_signal(int signum) {
    quitaction.sa_handler = quit_daemon;
    sigaction(signum, &quitaction, 0);
}
struct sigaction dummyaction;
extern "C" void nothing(int) {}
void
set_wakeup_on_signal(int signum) {
    dummyaction.sa_handler = nothing;
    sigaction(signum, &dummyaction, 0);
}

extern "C" void*
threadstarter(void *d) {
    // give this thread job batch job priority
    struct sched_param param;
    memset(&param, 0, sizeof(param));
    param.sched_priority = 0;
    StrigiThread* thread = static_cast<StrigiThread*>(d);

#ifndef __APPLE__
    if (thread->getPriority() > 0) {
#ifndef SCHED_BATCH
#define SCHED_BATCH 3
#endif
        // renice the thread
        int r  = setpriority(PRIO_PROCESS, 0, thread->getPriority());
        if (r != 0) {
            STRIGI_LOG_ERROR (string("strigi.daemon.") + thread->name
                + ".threadstarter",
                string("error setting priority: ") + strerror(errno));
        }
        r = sched_setscheduler(0, SCHED_BATCH, &param);
        if (r != 0) {
            STRIGI_LOG_INFO (string("strigi.daemon.") + thread->name
                + ".threadstarter",
                string("error setting to batch: ") + strerror(errno));
        }
#ifdef SYS_ioprio_set
        if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0,
                IOPRIO_CLASS_IDLE<<IOPRIO_CLASS_SHIFT ) < 0 ) {
            fprintf(stderr, "cannot set io scheduling to idle (%s). "
                "Trying best effort.\n",  strerror( errno ));
            if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0,
                    7|IOPRIO_CLASS_BE<<IOPRIO_CLASS_SHIFT ) < 0 ) {
                fprintf( stderr, "cannot set io scheduling to best effort.\n");
            }
        }
#endif
    }
#endif

    // start the actual work
    thread->run(0);
    STRIGI_LOG_DEBUG(string("strigi.daemon.") + thread->name + ".threadstarter", "end of thread");
    STRIGI_THREAD_EXIT(0);
    return 0;
}

StrigiThread::StrigiThread(const char* n) :state(Idling),thread(0),  name(n) {
    priority = 0;
    STRIGI_MUTEX_INIT(&lock);
}
StrigiThread::~StrigiThread() {
    STRIGI_MUTEX_DESTROY(&lock);
}
void
StrigiThread::setState(State s) {
    STRIGI_MUTEX_LOCK(&lock);
    state = s;
    STRIGI_MUTEX_UNLOCK(&lock);
}
StrigiThread::State
StrigiThread::getState() {
    State s;
    STRIGI_MUTEX_LOCK(&lock);
    s = state;
    STRIGI_MUTEX_UNLOCK(&lock);
    return s;
}
std::string
StrigiThread::getStringState() {
    State s = getState();
    std::string str;
    switch (s) {
    case Idling:
        str = "idling";
        break;
    case Working:
        str = "working";
        break;
    case Stopping:
        str = "stopping";
        break;
    }
    return str;
}
int
StrigiThread::start(int prio) {
    // set up signal handling
    set_quit_on_signal(SIGINT);
    set_quit_on_signal(SIGQUIT);
    set_quit_on_signal(SIGTERM);
    set_wakeup_on_signal(SIGALRM);
    threads.push_back(this);

    priority = prio;
    // start the indexer thread
    int r = STRIGI_THREAD_CREATE(&thread, threadstarter, this);
    if (r < 0) {
        STRIGI_LOG_ERROR ("strigi.daemon." + string(name),
                          "cannot create thread");
        return 1;
    }
    return 0;
}
void
StrigiThread::stop() {
    state = Stopping;
    stopThread();
    if (thread) {
        // signal the thread to wake up
        pthread_kill(thread, SIGALRM);
        // wait for the thread to finish
        STRIGI_THREAD_JOIN(thread);
    }
    thread = 0;
}
void
StrigiThread::terminate() {
    // TODO
}
<commit_msg>SVN_SILENT remove extra ','<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "strigithread.h"
#include "strigi_thread.h"
#include "strigilogging.h"

#include <string>
#include <cstring>
#include <errno.h>
#include <signal.h>
#include <vector>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/syscall.h>

// define two enums and a constant for use of ioprio
enum {
    IOPRIO_CLASS_NONE,
    IOPRIO_CLASS_RT,
    IOPRIO_CLASS_BE,
    IOPRIO_CLASS_IDLE
};

enum {
    IOPRIO_WHO_PROCESS = 1,
    IOPRIO_WHO_PGRP,
    IOPRIO_WHO_USER
};
#define IOPRIO_CLASS_SHIFT  13

using namespace std;

vector<StrigiThread*> threads;

void
StrigiThread::stopThreads() {
    vector<StrigiThread*>::const_iterator i;
    for (i=threads.begin(); i!=threads.end(); ++i) {
        STRIGI_LOG_INFO ("strigi.daemon", string("stopping thread ")
            + (*i)->name);
        (*i)->stop();
        STRIGI_LOG_INFO ("strigi.daemon", "stopped another thread ");
    }
}

extern "C" void
quit_daemon(int signum) {
    STRIGI_LOG_INFO("strigi.daemon", "quit_daemon");
    static int interruptcount = 0;
    vector<StrigiThread*>::const_iterator i;
    switch (++interruptcount) {
    case 1:
        STRIGI_LOG_INFO ("strigi.daemon", "stopping threads ");
        StrigiThread::stopThreads();
        break;
    case 2:
        STRIGI_LOG_INFO ("strigi.daemon", "terminating threads ");
        for (i=threads.begin(); i!=threads.end(); ++i) {
            (*i)->terminate();
        }
        break;
    case 3:
    default:
        STRIGI_LOG_FATAL ("strigi.daemon", "calling exit(1)")
        exit(1);
    }
}

struct sigaction quitaction;
void
set_quit_on_signal(int signum) {
    quitaction.sa_handler = quit_daemon;
    sigaction(signum, &quitaction, 0);
}
struct sigaction dummyaction;
extern "C" void nothing(int) {}
void
set_wakeup_on_signal(int signum) {
    dummyaction.sa_handler = nothing;
    sigaction(signum, &dummyaction, 0);
}

extern "C" void*
threadstarter(void *d) {
    // give this thread job batch job priority
    struct sched_param param;
    memset(&param, 0, sizeof(param));
    param.sched_priority = 0;
    StrigiThread* thread = static_cast<StrigiThread*>(d);

#ifndef __APPLE__
    if (thread->getPriority() > 0) {
#ifndef SCHED_BATCH
#define SCHED_BATCH 3
#endif
        // renice the thread
        int r  = setpriority(PRIO_PROCESS, 0, thread->getPriority());
        if (r != 0) {
            STRIGI_LOG_ERROR (string("strigi.daemon.") + thread->name
                + ".threadstarter",
                string("error setting priority: ") + strerror(errno));
        }
        r = sched_setscheduler(0, SCHED_BATCH, &param);
        if (r != 0) {
            STRIGI_LOG_INFO (string("strigi.daemon.") + thread->name
                + ".threadstarter",
                string("error setting to batch: ") + strerror(errno));
        }
#ifdef SYS_ioprio_set
        if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0,
                IOPRIO_CLASS_IDLE<<IOPRIO_CLASS_SHIFT ) < 0 ) {
            fprintf(stderr, "cannot set io scheduling to idle (%s). "
                "Trying best effort.\n",  strerror( errno ));
            if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0,
                    7|IOPRIO_CLASS_BE<<IOPRIO_CLASS_SHIFT ) < 0 ) {
                fprintf( stderr, "cannot set io scheduling to best effort.\n");
            }
        }
#endif
    }
#endif

    // start the actual work
    thread->run(0);
    STRIGI_LOG_DEBUG(string("strigi.daemon.") + thread->name + ".threadstarter", "end of thread");
    STRIGI_THREAD_EXIT(0);
    return 0;
}

StrigiThread::StrigiThread(const char* n) :state(Idling),thread(0),  name(n) {
    priority = 0;
    STRIGI_MUTEX_INIT(&lock);
}
StrigiThread::~StrigiThread() {
    STRIGI_MUTEX_DESTROY(&lock);
}
void
StrigiThread::setState(State s) {
    STRIGI_MUTEX_LOCK(&lock);
    state = s;
    STRIGI_MUTEX_UNLOCK(&lock);
}
StrigiThread::State
StrigiThread::getState() {
    State s;
    STRIGI_MUTEX_LOCK(&lock);
    s = state;
    STRIGI_MUTEX_UNLOCK(&lock);
    return s;
}
std::string
StrigiThread::getStringState() {
    State s = getState();
    std::string str;
    switch (s) {
    case Idling:
        str = "idling";
        break;
    case Working:
        str = "working";
        break;
    case Stopping:
        str = "stopping";
        break;
    }
    return str;
}
int
StrigiThread::start(int prio) {
    // set up signal handling
    set_quit_on_signal(SIGINT);
    set_quit_on_signal(SIGQUIT);
    set_quit_on_signal(SIGTERM);
    set_wakeup_on_signal(SIGALRM);
    threads.push_back(this);

    priority = prio;
    // start the indexer thread
    int r = STRIGI_THREAD_CREATE(&thread, threadstarter, this);
    if (r < 0) {
        STRIGI_LOG_ERROR ("strigi.daemon." + string(name),
                          "cannot create thread");
        return 1;
    }
    return 0;
}
void
StrigiThread::stop() {
    state = Stopping;
    stopThread();
    if (thread) {
        // signal the thread to wake up
        pthread_kill(thread, SIGALRM);
        // wait for the thread to finish
        STRIGI_THREAD_JOIN(thread);
    }
    thread = 0;
}
void
StrigiThread::terminate() {
    // TODO
}
<|endoftext|>


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

#ifndef _SVX_DBBROWSE_HXX
#include <svx/dbbrowse.hxx>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif

class Edit;
namespace dbaui
{

class OTableGrantControl : public DbBrowseBox
{
    DECLARE_STL_USTRINGACCESS_MAP(sal_Int32,TTablePrivilegeMap);

    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >    m_xUsers;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >    m_xTables;
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory> m_xORB;
    ::com::sun::star::uno::Sequence< ::rtl::OUString>                               m_aTableNames;

    TTablePrivilegeMap  m_aPrivMap;
    ::rtl::OUString     m_sUserName;
    DbCheckBoxCtrl*     m_pCheckCell;
    Edit*               m_pEdit;
    long                m_nDataPos;
    BOOL                m_bEnable;

public:
    OTableGrantControl( Window* pParent,const ResId& _RsId);
    virtual ~OTableGrantControl();
    void UpdateTables();
    void setUserName(const ::rtl::OUString _sUserName);

    void setTablesSupplier(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XTablesSupplier >& _xTablesSup);
    void setORB(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _xORB);

    virtual void Init();
protected:
    virtual void Resize();

    virtual long PreParentNotify(NotifyEvent& rNEvt );

    virtual BOOL IsTabAllowed(BOOL bForward) const;
    virtual void InitController( DbCellControllerRef& rController, long nRow, USHORT nCol );
    virtual DbCellController* GetController( long nRow, USHORT nCol );
    virtual void PaintCell( OutputDevice& rDev, const Rectangle& rRect, USHORT nColId ) const;
    virtual BOOL SeekRow( long nRow );
    virtual BOOL SaveModified();
    virtual String GetCellText( long nRow, USHORT nColId );

    virtual void CellModified();

private:
    ULONG       m_nDeActivateEvent;
    DECL_LINK( AsynchActivate, void* );
    DECL_LINK( AsynchDeactivate, void* );

    sal_Bool isAllowed(USHORT _nColumnId,sal_Int32 _nPrivilege) const;
    sal_Int32 fillPrivilege(sal_Int32 _nRow);
};

}

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

#ifndef _SVX_DBBROWSE_HXX
#include <svx/dbbrowse.hxx>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif

class Edit;
namespace dbaui
{

class OTableGrantControl : public DbBrowseBox
{
    DECLARE_STL_USTRINGACCESS_MAP(sal_Int32,TTablePrivilegeMap);

    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >    m_xUsers;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >    m_xTables;
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory> m_xORB;
    ::com::sun::star::uno::Sequence< ::rtl::OUString>                               m_aTableNames;

    TTablePrivilegeMap  m_aPrivMap;
    ::rtl::OUString     m_sUserName;
    DbCheckBoxCtrl*     m_pCheckCell;
    Edit*               m_pEdit;
    long                m_nDataPos;
    BOOL                m_bEnable;

public:
    OTableGrantControl( Window* pParent,const ResId& _RsId);
    virtual ~OTableGrantControl();
    void UpdateTables();
    void setUserName(const ::rtl::OUString _sUserName);

    void setTablesSupplier(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XTablesSupplier >& _xTablesSup);
    void setORB(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _xORB);

    virtual void Init();
protected:
    virtual void Resize();

    virtual long PreParentNotify(NotifyEvent& rNEvt );

    virtual BOOL IsTabAllowed(BOOL bForward) const;
    virtual void InitController( DbCellControllerRef& rController, long nRow, USHORT nCol );
    virtual DbCellController* GetController( long nRow, USHORT nCol );
    virtual void PaintCell( OutputDevice& rDev, const Rectangle& rRect, USHORT nColId ) const;
    virtual BOOL SeekRow( long nRow );
    virtual BOOL SaveModified();
    virtual String GetCellText( long nRow, USHORT nColId );

    virtual void CellModified();

private:
    ULONG       m_nDeActivateEvent;
    DECL_LINK( AsynchActivate, void* );
    DECL_LINK( AsynchDeactivate, void* );

    sal_Bool isAllowed(USHORT _nColumnId,sal_Int32 _nPrivilege) const;
    sal_Int32 fillPrivilege(sal_Int32 _nRow);
};

}

#endif // DBAUI_TABLEGRANTCONTROL_HXX
<|endoftext|>


<commit_before>// doosabin_regression.cpp

// Includes
#include <algorithm>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <streambuf>
#include <utility>

#include "ceres/ceres.h"
#include "gflags/gflags.h"
#include "glog/logging.h"

#include <Eigen/Dense>

#include "rapidjson/document.h"
#include "rapidjson/filestream.h"
#include "rapidjson/prettywriter.h"

#include "Math/linalg.h"
#include "Ceres/compose_cost_functions.h"

#include "doosabin.h"

#include "ceres_surface.h"
#include "surface.h"

// DooSabinSurface
class DooSabinSurface : public Surface {
 public:
  typedef doosabin::Surface<double> Surface;

  explicit DooSabinSurface(const Surface* surface)
    : surface_(surface)
  {}

  #define EVALUATE(M, SIZE) \
  virtual void M(double* r, const int p, const double* u, \
                 const double* const* X) const { \
    const Eigen::Map<const Eigen::Vector2d> _u(u); \
    const linalg::MatrixOfColumnPointers<double> _X( \
      X, 3, surface_->patch_vertex_indices(p).size()); \
    Eigen::Map<Eigen::VectorXd> _r(r, SIZE); \
    surface_->M(p, _u, _X, &_r); \
  }
  #define SIZE_JACOBIAN_X (3 * 3 * surface_->patch_vertex_indices(p).size())
  EVALUATE(M, 3);
  EVALUATE(Mu, 3);
  EVALUATE(Mv, 3);
  EVALUATE(Muu, 3);
  EVALUATE(Muv, 3);
  EVALUATE(Mvv, 3);
  EVALUATE(Mx, SIZE_JACOBIAN_X);
  EVALUATE(Mux, SIZE_JACOBIAN_X);
  EVALUATE(Mvx, SIZE_JACOBIAN_X);
  #undef EVALUATE
  #undef SIZE_JACOBIAN_X

  virtual int number_of_vertices() const {
    return surface_->number_of_vertices();
  }

  virtual int number_of_faces() const {
    return surface_->number_of_faces();
  }

  virtual int number_of_patches() const {
    return surface_->number_of_patches();
  }

  virtual const std::vector<int>& patch_vertex_indices(const int p) const {
    return surface_->patch_vertex_indices(p);
  }

  virtual const std::vector<int>& adjacent_patch_indices(const int p) const {
    return surface_->adjacent_patch_indices(p);
  }

 private:
  const Surface* surface_;
};

// PositionErrorFunctor
class PositionErrorFunctor {
 public:
  template <typename M>
  PositionErrorFunctor(const M& m0, const double& sqrt_w = 1.0)
    : m0_(m0), sqrt_w_(sqrt_w)
  {}

  template <typename T>
  bool operator()(const T* m, T* e) const {
    e[0] = T(sqrt_w_) * (T(m0_[0]) - m[0]);
    e[1] = T(sqrt_w_) * (T(m0_[1]) - m[1]);
    e[2] = T(sqrt_w_) * (T(m0_[2]) - m[2]);
    return true;
  }

 private:
  Eigen::Vector3d m0_;
  const double sqrt_w_;
};

// PairwiseErrorFunctor
class PairwiseErrorFunctor {
 public:
  PairwiseErrorFunctor(const double& sqrt_w = 1.0)
    : sqrt_w_(sqrt_w)
  {}

  template <typename T>
  bool operator()(const T* x0, const T* x1, T* e) const {
    e[0] = T(sqrt_w_) * (x1[0] - x0[0]);
    e[1] = T(sqrt_w_) * (x1[1] - x0[1]);
    e[2] = T(sqrt_w_) * (x1[2] - x0[2]);
    return true;
  }

 private:
  const double sqrt_w_;
};

// ReadFileIntoDocument
bool ReadFileIntoDocument(const std::string& input_path,
                          rapidjson::Document* document) {
  std::ifstream input(input_path, std::ios::binary);
  if (!input) {
    LOG(ERROR) << "File \"" << input_path << "\" not found.";
    return false;
  }

  std::string input_string;
  input.seekg(0, std::ios::end);
  input_string.reserve(input.tellg());
  input.seekg(0, std::ios::beg);

  input_string.assign((std::istreambuf_iterator<char>(input)),
                      std::istreambuf_iterator<char>());

  if (document->Parse<0>(input_string.c_str()).HasParseError()) {
    LOG(ERROR) << "Failed to parse input.";
    return false;
  }
  return true;
}

// LoadProblemFromFile
bool LoadProblemFromFile(const std::string& input_path,
                         Eigen::MatrixXd* Y,
                         std::vector<int>* raw_face_array,
                         Eigen::MatrixXd* X,
                         Eigen::VectorXi* p,
                         Eigen::MatrixXd* U) {
  rapidjson::Document document;
  if (!ReadFileIntoDocument(input_path, &document)) {
    return false;
  }

  #define LOAD_MATRIXD(SRC, DST, DIM) { \
    CHECK(document.HasMember(#SRC)); \
    auto& v = document[#SRC]; \
    CHECK(v.IsArray()); \
    DST->resize(DIM, v.Size() / DIM); \
    for (rapidjson::SizeType i = 0; i < v.Size(); ++i) { \
      CHECK(v[i].IsDouble()); \
      (*DST)(i % DIM, i / DIM) = v[i].GetDouble(); \
    } \
  }

  #define LOAD_VECTORI(SRC, DST) { \
    CHECK(document.HasMember(#SRC)); \
    auto& v = document[#SRC]; \
    CHECK(v.IsArray()); \
    DST->resize(v.Size()); \
    for (rapidjson::SizeType i = 0; i < v.Size(); ++i) { \
      CHECK(v[i].IsInt()); \
      (*DST)[i] = v[i].GetInt(); \
    } \
  }

  LOAD_MATRIXD(Y, Y, 3);
  LOAD_VECTORI(raw_face_array, raw_face_array);
  LOAD_MATRIXD(X, X, 3);
  LOAD_VECTORI(p, p);
  LOAD_MATRIXD(U, U, 2);

  #undef LOAD_MATRIXD
  #undef LOAD_VECTORI

  return true;
}

// UpdateProblemToFile
bool UpdateProblemToFile(const std::string& input_path,
                         const std::string& output_path,
                         const Eigen::MatrixXd& X,
                         const Eigen::VectorXi& p,
                         const Eigen::MatrixXd& U) {

  rapidjson::Document document;
  if (!ReadFileIntoDocument(input_path, &document)) {
    return false;
  }

  #define SAVE_MATRIXD(SRC, DST) { \
    CHECK(document.HasMember(#DST)); \
    auto& v = document[#DST]; \
    CHECK(v.IsArray()); \
    CHECK_EQ(v.Size(), SRC.rows() * SRC.cols()); \
    for (rapidjson::SizeType i = 0; i < v.Size(); ++i) { \
      CHECK(v[i].IsDouble()); \
      v[i] = SRC(i % SRC.rows(), i / SRC.rows()); \
    } \
  }

  #define SAVE_VECTORI(SRC, DST) { \
    CHECK(document.HasMember(#DST)); \
    auto& v = document[#DST]; \
    CHECK(v.IsArray()); \
    CHECK_EQ(v.Size(), SRC.size()); \
    for (rapidjson::SizeType i = 0; i < v.Size(); ++i) { \
      CHECK(v[i].IsInt()); \
      v[i] = SRC[i]; \
    } \
  }

  SAVE_MATRIXD(X, X);
  SAVE_VECTORI(p, p);
  SAVE_MATRIXD(U, U);

  // Use `fopen` instead of streams for `rapidjson::FileStream`.
  FILE* output_handle = fopen(output_path.c_str(), "wb");
  if (output_handle == nullptr) {
    LOG(ERROR) << "Unable to open \"" << output_path << "\"";
  }

  rapidjson::FileStream output(output_handle);
  rapidjson::PrettyWriter<rapidjson::FileStream> writer(output);
  document.Accept(writer);

  fclose(output_handle);

  return true;
}

// main
DEFINE_int32(max_num_iterations, 1000, "Maximum number of iterations.");
DEFINE_double(function_tolerance, 0.0,
  "Minimizer terminates when "
  "(new_cost - old_cost) < function_tolerance * old_cost");
DEFINE_double(gradient_tolerance, 0.0,
  "Minimizer terminates when "
  "max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i|");
DEFINE_double(parameter_tolerance, 0.0,
  "Minimizer terminates when "
  "|step|_2 <= parameter_tolerance * ( |x|_2 +  parameter_tolerance)");
DEFINE_double(min_trust_region_radius, 1e-9,
  "Minimizer terminates when the trust region radius becomes smaller than "
  "this value");

DEFINE_int32(num_threads, 1,
  "Number of threads to use for Jacobian evaluation.");
DEFINE_int32(num_linear_solver_threads, 1,
  "Number of threads to use for the linear solver.");

int main(int argc, char** argv) {
  google::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);

  if (argc < 4) {
    LOG(ERROR) << "Usage: " << argv[0] << " input_path lambda output_path";
    return -1;
  }

  // Load the problem data ...
  Eigen::MatrixXd Y;
  std::vector<int> raw_face_array;
  Eigen::MatrixXd X;
  Eigen::VectorXi p;
  Eigen::MatrixXd U;
  if (!LoadProblemFromFile(argv[1], &Y, &raw_face_array, &X, &p, &U)) {
    return -1;
  }

  // ... and check consistency of dimensions.
  typedef Eigen::DenseIndex Index;
  const Index num_data_points = Y.cols();
  CHECK_GT(num_data_points, 0);
  CHECK_EQ(num_data_points, p.size());
  CHECK_EQ(num_data_points, U.cols());

  doosabin::GeneralMesh T(std::move(raw_face_array));
  CHECK_GT(T.number_of_faces(), 0);
  doosabin::Surface<double> surface(T);
  DooSabinSurface doosabin_surface(&surface);
  CHECK_EQ(surface.number_of_vertices(), X.cols());

  // `lambda` is the regularisation weight.
  const double lambda = atof(argv[2]);

  // Setup `problem`.
  ceres::Problem problem;

  // Encode patch indices into the preimage positions.
  for (Index i = 0; i < num_data_points; ++i) {
    EncodePatchIndexInPlace(U.data() + 2 * i, p[i]);
  }

  // Add error residuals.
  std::vector<double*> parameter_blocks;
  parameter_blocks.reserve(1 + surface.number_of_vertices());
  parameter_blocks.push_back(nullptr); // `u`.
  for (Index i = 0; i < X.cols(); ++i) {
    parameter_blocks.push_back(X.data() + 3 * i);
  }

  std::unique_ptr<ceres::CostFunction> surface_position(
    new SurfacePositionCostFunction(&doosabin_surface));

  for (Index i = 0; i < num_data_points; ++i) {
    parameter_blocks[0] = U.data() + 2 * i;

    auto position_error = new ceres_utility::GeneralCostFunctionComposition(
      new ceres::AutoDiffCostFunction<PositionErrorFunctor, 3, 3>(
        new PositionErrorFunctor(Y.col(i), 1.0 / sqrt(num_data_points))));
    position_error->AddInputCostFunction(surface_position.get(),
                                         parameter_blocks,
                                         false);
    position_error->Finalise();

    problem.AddResidualBlock(position_error, nullptr, parameter_blocks);
  }

  // Add regularisation residuals.
  // Note: `problem` takes ownership of `pairwise_error`.
  auto pairwise_error =
    new ceres::AutoDiffCostFunction<PairwiseErrorFunctor, 3, 3, 3>(
      new PairwiseErrorFunctor(sqrt(lambda)));

  std::set<std::pair<int, int>> full_edges;
  for (std::pair<int, int> e : T.iterate_half_edges()) {
    if (e.first > e.second) {
      std::swap(e.first, e.second);
    }
    if (!full_edges.count(e)) {
      problem.AddResidualBlock(pairwise_error,
                               nullptr,
                               X.data() + 3 * e.first,
                               X.data() + 3 * e.second);
      full_edges.insert(e);
    }
  }

  // Set preimage parameterisations so that they are updated using
  // `doosabin::SurfaceWalker<double>` and NOT Euclidean addition.
  // Note: `problem` takes ownership of `local_parameterisation`.
  typedef doosabin::SurfaceWalker<double> DooSabinWalker;
  DooSabinWalker walker(&surface);
  auto local_parameterisation =
    new PreimageLocalParameterisation<DooSabinWalker, Eigen::MatrixXd>(
      &walker, &X);

  for (Index i = 0; i < num_data_points; ++i) {
    problem.SetParameterization(U.data() + 2 * i, local_parameterisation);
  }

  // Initialise the solver options.
  std::cout << "Solver options:" << std::endl;
  ceres::Solver::Options options;

  options.num_threads = FLAGS_num_threads;
  options.num_linear_solver_threads = FLAGS_num_linear_solver_threads;

  // Disable auto-scaling and set LM to be additive (instead of multiplicative).
  options.min_lm_diagonal = 1.0;
  options.max_lm_diagonal = 1.0;
  options.jacobi_scaling = false;

  options.minimizer_progress_to_stdout = FLAGS_v >= 1;

  // Termination criteria.
  options.max_num_iterations = FLAGS_max_num_iterations;
  std::cout << " max_num_iterations: " << options.max_num_iterations <<
               std::endl;
  options.max_num_consecutive_invalid_steps = FLAGS_max_num_iterations;

  options.function_tolerance = FLAGS_function_tolerance;
  options.gradient_tolerance = FLAGS_gradient_tolerance;
  options.parameter_tolerance = FLAGS_parameter_tolerance;
  options.min_trust_region_radius = FLAGS_min_trust_region_radius;

  // Solver selection.
  options.dynamic_sparsity = true;

  // `update_state_every_iteration` is required by
  // `PreimageLocalParameterisation` instances.
  options.update_state_every_iteration = true;

  // Solve.
  std::cout << "Solving ..." << std::endl;
  ceres::Solver::Summary summary;
  ceres::Solve(options, &problem, &summary);

  std::cout << summary.FullReport() << std::endl;

  // Decode patch indices.
  for (Index i = 0; i < num_data_points; ++i) {
    p[i] = DecodePatchIndexInPlace(U.data() + 2 * i);
  }

  // Save.
  if (!UpdateProblemToFile(argv[1], argv[3], X, p, U)) {
    return -1;
  }
  std::cout << "Output: " << argv[3] << std::endl;

  return 0;
}
<commit_msg>Minor improvement to `ReadFileIntoDocument` in src/doosabin_regression.cpp<commit_after>// doosabin_regression.cpp

// Includes
#include <algorithm>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <sstream>
#include <utility>

#include "ceres/ceres.h"
#include "gflags/gflags.h"
#include "glog/logging.h"

#include <Eigen/Dense>

#include "rapidjson/document.h"
#include "rapidjson/filestream.h"
#include "rapidjson/prettywriter.h"

#include "Math/linalg.h"
#include "Ceres/compose_cost_functions.h"

#include "doosabin.h"

#include "ceres_surface.h"
#include "surface.h"

// DooSabinSurface
class DooSabinSurface : public Surface {
 public:
  typedef doosabin::Surface<double> Surface;

  explicit DooSabinSurface(const Surface* surface)
    : surface_(surface)
  {}

  #define EVALUATE(M, SIZE) \
  virtual void M(double* r, const int p, const double* u, \
                 const double* const* X) const { \
    const Eigen::Map<const Eigen::Vector2d> _u(u); \
    const linalg::MatrixOfColumnPointers<double> _X( \
      X, 3, surface_->patch_vertex_indices(p).size()); \
    Eigen::Map<Eigen::VectorXd> _r(r, SIZE); \
    surface_->M(p, _u, _X, &_r); \
  }
  #define SIZE_JACOBIAN_X (3 * 3 * surface_->patch_vertex_indices(p).size())
  EVALUATE(M, 3);
  EVALUATE(Mu, 3);
  EVALUATE(Mv, 3);
  EVALUATE(Muu, 3);
  EVALUATE(Muv, 3);
  EVALUATE(Mvv, 3);
  EVALUATE(Mx, SIZE_JACOBIAN_X);
  EVALUATE(Mux, SIZE_JACOBIAN_X);
  EVALUATE(Mvx, SIZE_JACOBIAN_X);
  #undef EVALUATE
  #undef SIZE_JACOBIAN_X

  virtual int number_of_vertices() const {
    return surface_->number_of_vertices();
  }

  virtual int number_of_faces() const {
    return surface_->number_of_faces();
  }

  virtual int number_of_patches() const {
    return surface_->number_of_patches();
  }

  virtual const std::vector<int>& patch_vertex_indices(const int p) const {
    return surface_->patch_vertex_indices(p);
  }

  virtual const std::vector<int>& adjacent_patch_indices(const int p) const {
    return surface_->adjacent_patch_indices(p);
  }

 private:
  const Surface* surface_;
};

// PositionErrorFunctor
class PositionErrorFunctor {
 public:
  template <typename M>
  PositionErrorFunctor(const M& m0, const double& sqrt_w = 1.0)
    : m0_(m0), sqrt_w_(sqrt_w)
  {}

  template <typename T>
  bool operator()(const T* m, T* e) const {
    e[0] = T(sqrt_w_) * (T(m0_[0]) - m[0]);
    e[1] = T(sqrt_w_) * (T(m0_[1]) - m[1]);
    e[2] = T(sqrt_w_) * (T(m0_[2]) - m[2]);
    return true;
  }

 private:
  Eigen::Vector3d m0_;
  const double sqrt_w_;
};

// PairwiseErrorFunctor
class PairwiseErrorFunctor {
 public:
  PairwiseErrorFunctor(const double& sqrt_w = 1.0)
    : sqrt_w_(sqrt_w)
  {}

  template <typename T>
  bool operator()(const T* x0, const T* x1, T* e) const {
    e[0] = T(sqrt_w_) * (x1[0] - x0[0]);
    e[1] = T(sqrt_w_) * (x1[1] - x0[1]);
    e[2] = T(sqrt_w_) * (x1[2] - x0[2]);
    return true;
  }

 private:
  const double sqrt_w_;
};

// ReadFileIntoDocument
bool ReadFileIntoDocument(const std::string& input_path,
                          rapidjson::Document* document) {
  std::ifstream input(input_path, std::ios::binary);
  if (!input) {
    LOG(ERROR) << "File \"" << input_path << "\" not found.";
    return false;
  }

  std::stringstream input_ss;
  input_ss << input.rdbuf();
  if (document->Parse<0>(input_ss.str().c_str()).HasParseError()) {
    LOG(ERROR) << "Failed to parse input.";
    return false;
  }

  return true;
}

// LoadProblemFromFile
bool LoadProblemFromFile(const std::string& input_path,
                         Eigen::MatrixXd* Y,
                         std::vector<int>* raw_face_array,
                         Eigen::MatrixXd* X,
                         Eigen::VectorXi* p,
                         Eigen::MatrixXd* U) {
  rapidjson::Document document;
  if (!ReadFileIntoDocument(input_path, &document)) {
    return false;
  }

  #define LOAD_MATRIXD(SRC, DST, DIM) { \
    CHECK(document.HasMember(#SRC)); \
    auto& v = document[#SRC]; \
    CHECK(v.IsArray()); \
    DST->resize(DIM, v.Size() / DIM); \
    for (rapidjson::SizeType i = 0; i < v.Size(); ++i) { \
      CHECK(v[i].IsDouble()); \
      (*DST)(i % DIM, i / DIM) = v[i].GetDouble(); \
    } \
  }

  #define LOAD_VECTORI(SRC, DST) { \
    CHECK(document.HasMember(#SRC)); \
    auto& v = document[#SRC]; \
    CHECK(v.IsArray()); \
    DST->resize(v.Size()); \
    for (rapidjson::SizeType i = 0; i < v.Size(); ++i) { \
      CHECK(v[i].IsInt()); \
      (*DST)[i] = v[i].GetInt(); \
    } \
  }

  LOAD_MATRIXD(Y, Y, 3);
  LOAD_VECTORI(raw_face_array, raw_face_array);
  LOAD_MATRIXD(X, X, 3);
  LOAD_VECTORI(p, p);
  LOAD_MATRIXD(U, U, 2);

  #undef LOAD_MATRIXD
  #undef LOAD_VECTORI

  return true;
}

// UpdateProblemToFile
bool UpdateProblemToFile(const std::string& input_path,
                         const std::string& output_path,
                         const Eigen::MatrixXd& X,
                         const Eigen::VectorXi& p,
                         const Eigen::MatrixXd& U) {

  rapidjson::Document document;
  if (!ReadFileIntoDocument(input_path, &document)) {
    return false;
  }

  #define SAVE_MATRIXD(SRC, DST) { \
    CHECK(document.HasMember(#DST)); \
    auto& v = document[#DST]; \
    CHECK(v.IsArray()); \
    CHECK_EQ(v.Size(), SRC.rows() * SRC.cols()); \
    for (rapidjson::SizeType i = 0; i < v.Size(); ++i) { \
      CHECK(v[i].IsDouble()); \
      v[i] = SRC(i % SRC.rows(), i / SRC.rows()); \
    } \
  }

  #define SAVE_VECTORI(SRC, DST) { \
    CHECK(document.HasMember(#DST)); \
    auto& v = document[#DST]; \
    CHECK(v.IsArray()); \
    CHECK_EQ(v.Size(), SRC.size()); \
    for (rapidjson::SizeType i = 0; i < v.Size(); ++i) { \
      CHECK(v[i].IsInt()); \
      v[i] = SRC[i]; \
    } \
  }

  SAVE_MATRIXD(X, X);
  SAVE_VECTORI(p, p);
  SAVE_MATRIXD(U, U);

  // Use `fopen` instead of streams for `rapidjson::FileStream`.
  FILE* output_handle = fopen(output_path.c_str(), "wb");
  if (output_handle == nullptr) {
    LOG(ERROR) << "Unable to open \"" << output_path << "\"";
  }

  rapidjson::FileStream output(output_handle);
  rapidjson::PrettyWriter<rapidjson::FileStream> writer(output);
  document.Accept(writer);

  fclose(output_handle);

  return true;
}

// main
DEFINE_int32(max_num_iterations, 1000, "Maximum number of iterations.");
DEFINE_double(function_tolerance, 0.0,
  "Minimizer terminates when "
  "(new_cost - old_cost) < function_tolerance * old_cost");
DEFINE_double(gradient_tolerance, 0.0,
  "Minimizer terminates when "
  "max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i|");
DEFINE_double(parameter_tolerance, 0.0,
  "Minimizer terminates when "
  "|step|_2 <= parameter_tolerance * ( |x|_2 +  parameter_tolerance)");
DEFINE_double(min_trust_region_radius, 1e-9,
  "Minimizer terminates when the trust region radius becomes smaller than "
  "this value");

DEFINE_int32(num_threads, 1,
  "Number of threads to use for Jacobian evaluation.");
DEFINE_int32(num_linear_solver_threads, 1,
  "Number of threads to use for the linear solver.");

int main(int argc, char** argv) {
  google::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);

  if (argc < 4) {
    LOG(ERROR) << "Usage: " << argv[0] << " input_path lambda output_path";
    return -1;
  }

  // Load the problem data ...
  Eigen::MatrixXd Y;
  std::vector<int> raw_face_array;
  Eigen::MatrixXd X;
  Eigen::VectorXi p;
  Eigen::MatrixXd U;
  if (!LoadProblemFromFile(argv[1], &Y, &raw_face_array, &X, &p, &U)) {
    return -1;
  }

  // ... and check consistency of dimensions.
  typedef Eigen::DenseIndex Index;
  const Index num_data_points = Y.cols();
  CHECK_GT(num_data_points, 0);
  CHECK_EQ(num_data_points, p.size());
  CHECK_EQ(num_data_points, U.cols());

  doosabin::GeneralMesh T(std::move(raw_face_array));
  CHECK_GT(T.number_of_faces(), 0);
  doosabin::Surface<double> surface(T);
  DooSabinSurface doosabin_surface(&surface);
  CHECK_EQ(surface.number_of_vertices(), X.cols());

  // `lambda` is the regularisation weight.
  const double lambda = atof(argv[2]);

  // Setup `problem`.
  ceres::Problem problem;

  // Encode patch indices into the preimage positions.
  for (Index i = 0; i < num_data_points; ++i) {
    EncodePatchIndexInPlace(U.data() + 2 * i, p[i]);
  }

  // Add error residuals.
  std::vector<double*> parameter_blocks;
  parameter_blocks.reserve(1 + surface.number_of_vertices());
  parameter_blocks.push_back(nullptr); // `u`.
  for (Index i = 0; i < X.cols(); ++i) {
    parameter_blocks.push_back(X.data() + 3 * i);
  }

  std::unique_ptr<ceres::CostFunction> surface_position(
    new SurfacePositionCostFunction(&doosabin_surface));

  for (Index i = 0; i < num_data_points; ++i) {
    parameter_blocks[0] = U.data() + 2 * i;

    auto position_error = new ceres_utility::GeneralCostFunctionComposition(
      new ceres::AutoDiffCostFunction<PositionErrorFunctor, 3, 3>(
        new PositionErrorFunctor(Y.col(i), 1.0 / sqrt(num_data_points))));
    position_error->AddInputCostFunction(surface_position.get(),
                                         parameter_blocks,
                                         false);
    position_error->Finalise();

    problem.AddResidualBlock(position_error, nullptr, parameter_blocks);
  }

  // Add regularisation residuals.
  // Note: `problem` takes ownership of `pairwise_error`.
  auto pairwise_error =
    new ceres::AutoDiffCostFunction<PairwiseErrorFunctor, 3, 3, 3>(
      new PairwiseErrorFunctor(sqrt(lambda)));

  std::set<std::pair<int, int>> full_edges;
  for (std::pair<int, int> e : T.iterate_half_edges()) {
    if (e.first > e.second) {
      std::swap(e.first, e.second);
    }
    if (!full_edges.count(e)) {
      problem.AddResidualBlock(pairwise_error,
                               nullptr,
                               X.data() + 3 * e.first,
                               X.data() + 3 * e.second);
      full_edges.insert(e);
    }
  }

  // Set preimage parameterisations so that they are updated using
  // `doosabin::SurfaceWalker<double>` and NOT Euclidean addition.
  // Note: `problem` takes ownership of `local_parameterisation`.
  typedef doosabin::SurfaceWalker<double> DooSabinWalker;
  DooSabinWalker walker(&surface);
  auto local_parameterisation =
    new PreimageLocalParameterisation<DooSabinWalker, Eigen::MatrixXd>(
      &walker, &X);

  for (Index i = 0; i < num_data_points; ++i) {
    problem.SetParameterization(U.data() + 2 * i, local_parameterisation);
  }

  // Initialise the solver options.
  std::cout << "Solver options:" << std::endl;
  ceres::Solver::Options options;

  options.num_threads = FLAGS_num_threads;
  options.num_linear_solver_threads = FLAGS_num_linear_solver_threads;

  // Disable auto-scaling and set LM to be additive (instead of multiplicative).
  options.min_lm_diagonal = 1.0;
  options.max_lm_diagonal = 1.0;
  options.jacobi_scaling = false;

  options.minimizer_progress_to_stdout = FLAGS_v >= 1;

  // Termination criteria.
  options.max_num_iterations = FLAGS_max_num_iterations;
  std::cout << " max_num_iterations: " << options.max_num_iterations <<
               std::endl;
  options.max_num_consecutive_invalid_steps = FLAGS_max_num_iterations;

  options.function_tolerance = FLAGS_function_tolerance;
  options.gradient_tolerance = FLAGS_gradient_tolerance;
  options.parameter_tolerance = FLAGS_parameter_tolerance;
  options.min_trust_region_radius = FLAGS_min_trust_region_radius;

  // Solver selection.
  options.dynamic_sparsity = true;

  // `update_state_every_iteration` is required by
  // `PreimageLocalParameterisation` instances.
  options.update_state_every_iteration = true;

  // Solve.
  std::cout << "Solving ..." << std::endl;
  ceres::Solver::Summary summary;
  ceres::Solve(options, &problem, &summary);

  std::cout << summary.FullReport() << std::endl;

  // Decode patch indices.
  for (Index i = 0; i < num_data_points; ++i) {
    p[i] = DecodePatchIndexInPlace(U.data() + 2 * i);
  }

  // Save.
  if (!UpdateProblemToFile(argv[1], argv[3], X, p, U)) {
    return -1;
  }
  std::cout << "Output: " << argv[3] << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>#include <stdexcept>
#include <iostream>
#include <csignal>
#include <boost/program_options.hpp>
#include "cppkafka/consumer.h"
#include "cppkafka/configuration.h"

using std::string;
using std::exception;
using std::cout;
using std::endl;

using cppkafka::Consumer;
using cppkafka::Configuration;
using cppkafka::Message;

namespace po = boost::program_options;

bool running = true;

int main(int argc, char* argv[]) {
    string brokers;
    string topic_name;
    string group_id;

    po::options_description options("Options");
    options.add_options()
        ("help,h",   "produce this help message")
        ("brokers",  po::value<string>(&brokers)->required(),
                     "the kafka broker list")
        ("topic",    po::value<string>(&topic_name)->required(),
                     "the topic in which to write to")
        ("group-id", po::value<string>(&group_id)->required(),
                     "the consumer group id")
        ;

    po::variables_map vm;

    try {
        po::store(po::command_line_parser(argc, argv).options(options).run(), vm);
        po::notify(vm);
    }
    catch (exception& ex) {
        cout << "Error parsing options: " << ex.what() << endl;
        cout << endl;
        cout << options << endl;
        return 1;
    }

    // Stop processing on SIGINT
    signal(SIGINT, [](int) { running = false; });

    // Construct the configuration
    Configuration config;
    config.set("metadata.broker.list", brokers);
    config.set("group.id", group_id);
    // Disable auto commit
    config.set("enable.auto.commit", false);

    // Create the consumer
    Consumer consumer(config);

    // Subscribe to the topic
    consumer.subscribe({ topic_name });

    cout << "Consuming messages from topic " << topic_name << endl;

    // Now read lines and write them into kafka
    while (running) {
        // Try to consume a message
        Message msg = consumer.poll();
        if (msg) {
            // If we managed to get a message
            if (msg.has_error()) {
                if (msg.get_error() != RD_KAFKA_RESP_ERR__PARTITION_EOF) {
                    cout << "[+] Received error notification: " << msg.get_error_string() << endl;
                }
            }
            else {
                // Print the key (if any)
                if (msg.get_key()) {
                    cout << msg.get_key() << " -> ";
                }
                // Print the payload
                cout << msg.get_payload() << endl;
                // Now commit the message
                consumer.commit(msg);
            }
        }
    }
}
<commit_msg>Print assigned and revoked partitions on consumer example<commit_after>#include <stdexcept>
#include <iostream>
#include <csignal>
#include <boost/program_options.hpp>
#include "cppkafka/consumer.h"
#include "cppkafka/configuration.h"

using std::string;
using std::exception;
using std::cout;
using std::endl;

using cppkafka::Consumer;
using cppkafka::Configuration;
using cppkafka::Message;
using cppkafka::TopicPartitionList;

namespace po = boost::program_options;

bool running = true;

int main(int argc, char* argv[]) {
    string brokers;
    string topic_name;
    string group_id;

    po::options_description options("Options");
    options.add_options()
        ("help,h",   "produce this help message")
        ("brokers",  po::value<string>(&brokers)->required(),
                     "the kafka broker list")
        ("topic",    po::value<string>(&topic_name)->required(),
                     "the topic in which to write to")
        ("group-id", po::value<string>(&group_id)->required(),
                     "the consumer group id")
        ;

    po::variables_map vm;

    try {
        po::store(po::command_line_parser(argc, argv).options(options).run(), vm);
        po::notify(vm);
    }
    catch (exception& ex) {
        cout << "Error parsing options: " << ex.what() << endl;
        cout << endl;
        cout << options << endl;
        return 1;
    }

    // Stop processing on SIGINT
    signal(SIGINT, [](int) { running = false; });

    // Construct the configuration
    Configuration config;
    config.set("metadata.broker.list", brokers);
    config.set("group.id", group_id);
    // Disable auto commit
    config.set("enable.auto.commit", false);

    // Create the consumer
    Consumer consumer(config);

    // Print the assigned partitions on assignment
    consumer.set_assignment_callback([](const TopicPartitionList& partitions) {
        cout << "Got assigned: " << partitions << endl;
    });

    // Print the revoked partitions on revocation
    consumer.set_revocation_callback([](const TopicPartitionList& partitions) {
        cout << "Got revoked: " << partitions << endl;
    });

    // Subscribe to the topic
    consumer.subscribe({ topic_name });

    cout << "Consuming messages from topic " << topic_name << endl;

    // Now read lines and write them into kafka
    while (running) {
        // Try to consume a message
        Message msg = consumer.poll();
        if (msg) {
            // If we managed to get a message
            if (msg.has_error()) {
                if (msg.get_error() != RD_KAFKA_RESP_ERR__PARTITION_EOF) {
                    cout << "[+] Received error notification: " << msg.get_error_string() << endl;
                }
            }
            else {
                // Print the key (if any)
                if (msg.get_key()) {
                    cout << msg.get_key() << " -> ";
                }
                // Print the payload
                cout << msg.get_payload() << endl;
                // Now commit the message
                consumer.commit(msg);
            }
        }
    }
}
<|endoftext|>


<commit_before>#include <fcntl.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
#include <leveldb/db.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <stdint.h>

#include <algorithm>
#include <fstream>  // NOLINT(readability/streams)
#include <string>
#include <vector>

#include "caffe/common.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/util/io.hpp"

namespace caffe {

using google::protobuf::io::FileInputStream;
using google::protobuf::io::FileOutputStream;
using google::protobuf::io::ZeroCopyInputStream;
using google::protobuf::io::CodedInputStream;
using google::protobuf::io::ZeroCopyOutputStream;
using google::protobuf::io::CodedOutputStream;
using google::protobuf::Message;

bool ReadProtoFromTextFile(const char* filename, Message* proto) {
  int fd = open(filename, O_RDONLY);
  CHECK_NE(fd, -1) << "File not found: " << filename;
  FileInputStream* input = new FileInputStream(fd);
  bool success = google::protobuf::TextFormat::Parse(input, proto);
  delete input;
  close(fd);
  return success;
}

void WriteProtoToTextFile(const Message& proto, const char* filename) {
  int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  FileOutputStream* output = new FileOutputStream(fd);
  CHECK(google::protobuf::TextFormat::Print(proto, output));
  delete output;
  close(fd);
}

bool ReadProtoFromBinaryFile(const char* filename, Message* proto) {
  int fd = open(filename, O_RDONLY);
  CHECK_NE(fd, -1) << "File not found: " << filename;
  ZeroCopyInputStream* raw_input = new FileInputStream(fd);
  CodedInputStream* coded_input = new CodedInputStream(raw_input);
  coded_input->SetTotalBytesLimit(1073741824, 536870912);

  bool success = proto->ParseFromCodedStream(coded_input);

  delete coded_input;
  delete raw_input;
  close(fd);
  return success;
}

void WriteProtoToBinaryFile(const Message& proto, const char* filename) {
  fstream output(filename, ios::out | ios::trunc | ios::binary);
  CHECK(proto.SerializeToOstream(&output));
}

bool ReadImageToDatum(const string& filename, const int label,
    const int height, const int width, const bool is_color, Datum* datum) {
  cv::Mat cv_img;
  int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR :
    CV_LOAD_IMAGE_GRAYSCALE);

  cv::Mat cv_img_origin = cv::imread(filename, cv_read_flag);
  if (!cv_img_origin.data) {
    LOG(ERROR) << "Could not open or find file " << filename;
    return false;
  }
  if (height > 0 && width > 0) {
    cv::resize(cv_img_origin, cv_img, cv::Size(width, height));
  } else {
    cv_img = cv_img_origin;
  }

  int num_channels = (is_color ? 3 : 1);
  datum->set_channels(num_channels);
  datum->set_height(cv_img.rows);
  datum->set_width(cv_img.cols);
  datum->set_label(label);
  datum->clear_data();
  datum->clear_float_data();
  string* datum_string = datum->mutable_data();
  if (is_color) {
    for (int c = 0; c < num_channels; ++c) {
      for (int h = 0; h < cv_img.rows; ++h) {
        for (int w = 0; w < cv_img.cols; ++w) {
          datum_string->push_back(
            static_cast<char>(cv_img.at<cv::Vec3b>(h, w)[c]));
        }
      }
    }
  } else {  // Faster than repeatedly testing is_color for each pixel w/i loop
    for (int h = 0; h < cv_img.rows; ++h) {
      for (int w = 0; w < cv_img.cols; ++w) {
        datum_string->push_back(
          static_cast<char>(cv_img.at<uchar>(h, w)));
        }
      }
  }
  return true;
}

leveldb::Options GetLevelDBOptions() {
  // In default, we will return the leveldb option and set the max open files
  // in order to avoid using up the operating system's limit.
  leveldb::Options options;
  options.max_open_files = 100;
  return options;
}

// Verifies format of data stored in HDF5 file and reshapes blob accordingly.
template <typename Dtype>
void hdf5_load_nd_dataset_helper(
    hid_t file_id, const char* dataset_name_, int min_dim, int max_dim,
    Blob<Dtype>* blob) {
  // Verify that the number of dimensions is in the accepted range.
  herr_t status;
  int ndims;
  status = H5LTget_dataset_ndims(file_id, dataset_name_, &ndims);
  CHECK_GE(status, 0) << "Failed to get dataset ndims for " << dataset_name_;
  CHECK_GE(ndims, min_dim);
  CHECK_LE(ndims, max_dim);

  // Verify that the data format is what we expect: float or double.
  std::vector<hsize_t> dims(ndims);
  H5T_class_t class_;
  status = H5LTget_dataset_info(
      file_id, dataset_name_, dims.data(), &class_, NULL);
  CHECK_GE(status, 0) << "Failed to get dataset info for " << dataset_name_;
  CHECK_EQ(class_, H5T_FLOAT) << "Expected float or double data";

  blob->Reshape(
    dims[0],
    (dims.size() > 1) ? dims[1] : 1,
    (dims.size() > 2) ? dims[2] : 1,
    (dims.size() > 3) ? dims[3] : 1);
}

template <>
void hdf5_load_nd_dataset<float>(hid_t file_id, const char* dataset_name_,
        int min_dim, int max_dim, Blob<float>* blob) {
  hdf5_load_nd_dataset_helper(file_id, dataset_name_, min_dim, max_dim, blob);
  herr_t status = H5LTread_dataset_float(
    file_id, dataset_name_, blob->mutable_cpu_data());
  CHECK_GE(status, 0) << "Failed to read float dataset " << dataset_name_;
}

template <>
void hdf5_load_nd_dataset<double>(hid_t file_id, const char* dataset_name_,
        int min_dim, int max_dim, Blob<double>* blob) {
  hdf5_load_nd_dataset_helper(file_id, dataset_name_, min_dim, max_dim, blob);
  herr_t status = H5LTread_dataset_double(
    file_id, dataset_name_, blob->mutable_cpu_data());
  CHECK_GE(status, 0) << "Failed to read double dataset " << dataset_name_;
}

template <>
void hdf5_save_nd_dataset<float>(
    const hid_t file_id, const string dataset_name, const Blob<float>& blob) {
  hsize_t dims[HDF5_NUM_DIMS];
  dims[0] = blob.num();
  dims[1] = blob.channels();
  dims[2] = blob.height();
  dims[3] = blob.width();
  herr_t status = H5LTmake_dataset_float(
      file_id, dataset_name.c_str(), HDF5_NUM_DIMS, dims, blob.cpu_data());
  CHECK_GE(status, 0) << "Failed to make float dataset " << dataset_name;
}

template <>
void hdf5_save_nd_dataset<double>(
    const hid_t file_id, const string dataset_name, const Blob<double>& blob) {
  hsize_t dims[HDF5_NUM_DIMS];
  dims[0] = blob.num();
  dims[1] = blob.channels();
  dims[2] = blob.height();
  dims[3] = blob.width();
  herr_t status = H5LTmake_dataset_double(
      file_id, dataset_name.c_str(), HDF5_NUM_DIMS, dims, blob.cpu_data());
  CHECK_GE(status, 0) << "Failed to make double dataset " << dataset_name;
}

}  // namespace caffe
<commit_msg>hdf5_load_nd_dataset_helper: check that dataset exists first<commit_after>#include <fcntl.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
#include <leveldb/db.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <stdint.h>

#include <algorithm>
#include <fstream>  // NOLINT(readability/streams)
#include <string>
#include <vector>

#include "caffe/common.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/util/io.hpp"

namespace caffe {

using google::protobuf::io::FileInputStream;
using google::protobuf::io::FileOutputStream;
using google::protobuf::io::ZeroCopyInputStream;
using google::protobuf::io::CodedInputStream;
using google::protobuf::io::ZeroCopyOutputStream;
using google::protobuf::io::CodedOutputStream;
using google::protobuf::Message;

bool ReadProtoFromTextFile(const char* filename, Message* proto) {
  int fd = open(filename, O_RDONLY);
  CHECK_NE(fd, -1) << "File not found: " << filename;
  FileInputStream* input = new FileInputStream(fd);
  bool success = google::protobuf::TextFormat::Parse(input, proto);
  delete input;
  close(fd);
  return success;
}

void WriteProtoToTextFile(const Message& proto, const char* filename) {
  int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  FileOutputStream* output = new FileOutputStream(fd);
  CHECK(google::protobuf::TextFormat::Print(proto, output));
  delete output;
  close(fd);
}

bool ReadProtoFromBinaryFile(const char* filename, Message* proto) {
  int fd = open(filename, O_RDONLY);
  CHECK_NE(fd, -1) << "File not found: " << filename;
  ZeroCopyInputStream* raw_input = new FileInputStream(fd);
  CodedInputStream* coded_input = new CodedInputStream(raw_input);
  coded_input->SetTotalBytesLimit(1073741824, 536870912);

  bool success = proto->ParseFromCodedStream(coded_input);

  delete coded_input;
  delete raw_input;
  close(fd);
  return success;
}

void WriteProtoToBinaryFile(const Message& proto, const char* filename) {
  fstream output(filename, ios::out | ios::trunc | ios::binary);
  CHECK(proto.SerializeToOstream(&output));
}

bool ReadImageToDatum(const string& filename, const int label,
    const int height, const int width, const bool is_color, Datum* datum) {
  cv::Mat cv_img;
  int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR :
    CV_LOAD_IMAGE_GRAYSCALE);

  cv::Mat cv_img_origin = cv::imread(filename, cv_read_flag);
  if (!cv_img_origin.data) {
    LOG(ERROR) << "Could not open or find file " << filename;
    return false;
  }
  if (height > 0 && width > 0) {
    cv::resize(cv_img_origin, cv_img, cv::Size(width, height));
  } else {
    cv_img = cv_img_origin;
  }

  int num_channels = (is_color ? 3 : 1);
  datum->set_channels(num_channels);
  datum->set_height(cv_img.rows);
  datum->set_width(cv_img.cols);
  datum->set_label(label);
  datum->clear_data();
  datum->clear_float_data();
  string* datum_string = datum->mutable_data();
  if (is_color) {
    for (int c = 0; c < num_channels; ++c) {
      for (int h = 0; h < cv_img.rows; ++h) {
        for (int w = 0; w < cv_img.cols; ++w) {
          datum_string->push_back(
            static_cast<char>(cv_img.at<cv::Vec3b>(h, w)[c]));
        }
      }
    }
  } else {  // Faster than repeatedly testing is_color for each pixel w/i loop
    for (int h = 0; h < cv_img.rows; ++h) {
      for (int w = 0; w < cv_img.cols; ++w) {
        datum_string->push_back(
          static_cast<char>(cv_img.at<uchar>(h, w)));
        }
      }
  }
  return true;
}

leveldb::Options GetLevelDBOptions() {
  // In default, we will return the leveldb option and set the max open files
  // in order to avoid using up the operating system's limit.
  leveldb::Options options;
  options.max_open_files = 100;
  return options;
}

// Verifies format of data stored in HDF5 file and reshapes blob accordingly.
template <typename Dtype>
void hdf5_load_nd_dataset_helper(
    hid_t file_id, const char* dataset_name_, int min_dim, int max_dim,
    Blob<Dtype>* blob) {
  // Verify that the dataset exists.
  CHECK(H5LTfind_dataset(file_id, dataset_name_))
      << "Failed to find HDF5 dataset " << dataset_name_;
  // Verify that the number of dimensions is in the accepted range.
  herr_t status;
  int ndims;
  status = H5LTget_dataset_ndims(file_id, dataset_name_, &ndims);
  CHECK_GE(status, 0) << "Failed to get dataset ndims for " << dataset_name_;
  CHECK_GE(ndims, min_dim);
  CHECK_LE(ndims, max_dim);

  // Verify that the data format is what we expect: float or double.
  std::vector<hsize_t> dims(ndims);
  H5T_class_t class_;
  status = H5LTget_dataset_info(
      file_id, dataset_name_, dims.data(), &class_, NULL);
  CHECK_GE(status, 0) << "Failed to get dataset info for " << dataset_name_;
  CHECK_EQ(class_, H5T_FLOAT) << "Expected float or double data";

  blob->Reshape(
    dims[0],
    (dims.size() > 1) ? dims[1] : 1,
    (dims.size() > 2) ? dims[2] : 1,
    (dims.size() > 3) ? dims[3] : 1);
}

template <>
void hdf5_load_nd_dataset<float>(hid_t file_id, const char* dataset_name_,
        int min_dim, int max_dim, Blob<float>* blob) {
  hdf5_load_nd_dataset_helper(file_id, dataset_name_, min_dim, max_dim, blob);
  herr_t status = H5LTread_dataset_float(
    file_id, dataset_name_, blob->mutable_cpu_data());
  CHECK_GE(status, 0) << "Failed to read float dataset " << dataset_name_;
}

template <>
void hdf5_load_nd_dataset<double>(hid_t file_id, const char* dataset_name_,
        int min_dim, int max_dim, Blob<double>* blob) {
  hdf5_load_nd_dataset_helper(file_id, dataset_name_, min_dim, max_dim, blob);
  herr_t status = H5LTread_dataset_double(
    file_id, dataset_name_, blob->mutable_cpu_data());
  CHECK_GE(status, 0) << "Failed to read double dataset " << dataset_name_;
}

template <>
void hdf5_save_nd_dataset<float>(
    const hid_t file_id, const string dataset_name, const Blob<float>& blob) {
  hsize_t dims[HDF5_NUM_DIMS];
  dims[0] = blob.num();
  dims[1] = blob.channels();
  dims[2] = blob.height();
  dims[3] = blob.width();
  herr_t status = H5LTmake_dataset_float(
      file_id, dataset_name.c_str(), HDF5_NUM_DIMS, dims, blob.cpu_data());
  CHECK_GE(status, 0) << "Failed to make float dataset " << dataset_name;
}

template <>
void hdf5_save_nd_dataset<double>(
    const hid_t file_id, const string dataset_name, const Blob<double>& blob) {
  hsize_t dims[HDF5_NUM_DIMS];
  dims[0] = blob.num();
  dims[1] = blob.channels();
  dims[2] = blob.height();
  dims[3] = blob.width();
  herr_t status = H5LTmake_dataset_double(
      file_id, dataset_name.c_str(), HDF5_NUM_DIMS, dims, blob.cpu_data());
  CHECK_GE(status, 0) << "Failed to make double dataset " << dataset_name;
}

}  // namespace caffe
<|endoftext|>