text:
/******************************************************************
 *
 * uEcho for C
 *
 * Copyright (C) Satoshi Konno 2015
 *
 * This is licensed under BSD-style license, see file COPYING.
 *
 ******************************************************************/

#include <boost/test/unit_test.hpp>

#include <uecho/std/database.h>
#include <uecho/util/strings.h>

BOOST_AUTO_TEST_CASE(DatabaseStandardManufacture)
{
  uEchoDatabase* db = uecho_standard_getdatabase();
  BOOST_CHECK(db);

  uEchoManufactureCode man_codes[] = { 0x00000B, 0x000005 };
  const char* man_names[] = { "Panasonic", "Sharp" };
  for (int n = 0; n < (sizeof(man_codes) / sizeof(uEchoManufactureCode)); n++) {
    uEchoManufacture* man = uecho_database_getmanufacture(db, man_codes[n]);
    BOOST_CHECK(man);
    BOOST_CHECK_EQUAL(uecho_strncmp(uecho_manufacture_getname(man), man_names[n], uecho_strlen(man_names[n])), 0);
  }
}

BOOST_AUTO_TEST_CASE(DatabaseStandardSuperObject)
{
  uEchoDatabase* db = uecho_standard_getdatabase();
  BOOST_CHECK(db);

  byte obj_group_code = 0x00;
  byte obj_class_code = 0x00;

  uEchoObject* obj = uecho_database_getobject(db, obj_group_code, obj_class_code);
  BOOST_CHECK(obj);

  byte obj_prop_codes[] = {
    0x80
  };
  uEchoPropertyAttr obj_prop_attrs[] = {
    uEchoPropertyAttr(uEchoPropertyAttrReadRequired | uEchoPropertyAttrWrite | uEchoPropertyAttrAnnoRequired),
  };
  for (int n = 0; n < (sizeof(obj_prop_codes) / sizeof(byte)); n++) {
    uEchoProperty* prop = uecho_object_getproperty(obj, obj_prop_codes[n]);
    BOOST_CHECK(prop);
    BOOST_CHECK_EQUAL(uecho_property_getattribute(prop), obj_prop_attrs[n]);
  }
}

BOOST_AUTO_TEST_CASE(DatabaseStandardNodeProfile)
{
  uEchoDatabase* db = uecho_standard_getdatabase();
  BOOST_CHECK(db);

  byte obj_group_code = 0x0E;
  byte obj_class_code = 0xF0;

  uEchoObject* obj = uecho_database_getobject(db, obj_group_code, obj_class_code);
  BOOST_CHECK(obj);

  byte obj_prop_codes[] = {
    0x80
  };
  uEchoPropertyAttr obj_prop_attrs[] = {
    uEchoPropertyAttr(uEchoPropertyAttrReadRequired | uEchoPropertyAttrAnnoRequired),
  };
  for (int n = 0; n < (sizeof(obj_prop_codes) / sizeof(byte)); n++) {
    uEchoProperty* prop = uecho_object_getproperty(obj, obj_prop_codes[n]);
    BOOST_CHECK(prop);
    BOOST_CHECK_EQUAL(uecho_property_getattribute(prop), obj_prop_attrs[n]);
  }
}

BOOST_AUTO_TEST_CASE(DatabaseStandardDevice)
{
  uEchoDatabase* db = uecho_standard_getdatabase();
  BOOST_CHECK(db);

  byte obj_group_code = 0x02;
  byte obj_class_code = 0x91;

  uEchoObject* obj = uecho_database_getobject(db, obj_group_code, obj_class_code);
  BOOST_CHECK(obj);

  byte obj_prop_codes[] = {
    0x80
  };
  uEchoPropertyAttr obj_prop_attrs[] = {
    uEchoPropertyAttr(uEchoPropertyAttrReadRequired | uEchoPropertyAttrWriteRequired | uEchoPropertyAttrAnnoRequired),
  };
  for (int n = 0; n < (sizeof(obj_prop_codes) / sizeof(byte)); n++) {
    uEchoProperty* prop = uecho_object_getproperty(obj, obj_prop_codes[n]);
    BOOST_CHECK(prop);
    BOOST_CHECK_EQUAL(uecho_property_getattribute(prop), obj_prop_attrs[n]);
  }
}

ext: cpp


text:
/**
 * @file  maximumprinciple.cc
 * @brief NPDE homework "MaximumPrinciple" code
 * @author Oliver Rietmann
 * @date 25.03.2019
 * @copyright Developed at ETH Zurich
 */

#include "maximumprinciple.h"

#include <Eigen/Core>
#include <Eigen/SparseCore>
#include <vector>

namespace MaximumPrinciple {

/**
 * @brief Assembly on a tensor product mesh
 *
 * Compute the global Galerkin matrix from the local
 * element matrix.
 *
 * @param M Number of interior vertices in x and y direction.
 * @param B_K Local element matrix.
 * @return Global Galerkin matrix of size M^2 times M^2.
 */
/* SAM_LISTING_BEGIN_1 */
Eigen::SparseMatrix<double> assemble(int M, const Eigen::Matrix3d &B_K) {
  int M2 = M * M;
  Eigen::SparseMatrix<double> A(M2, M2);
  double near_neighbour_contribution = 2.0 * B_K(0, 1);
  double far_neighbour_contribution = 2.0 * B_K(1, 2);
  double self_contribution = 2.0 * (B_K(0, 0) + B_K(1, 1) + B_K(2, 2));

  std::vector<double> contribution = {
      far_neighbour_contribution,  near_neighbour_contribution,
      near_neighbour_contribution, self_contribution,
      near_neighbour_contribution, near_neighbour_contribution,
      far_neighbour_contribution};

  std::vector<Eigen::Vector2i> shift = {{-1, -1}, {0, -1}, {-1, 0}, {0, 0},
                                        {1, 0},   {0, 1},  {1, 1}};

  std::vector<Eigen::Triplet<double>> tripletList;
  for (int i = 0; i < M; ++i) {
    for (int j = 0; j < M; ++j) {
      Eigen::Vector2i self = Eigen::Vector2i(i, j);
      for (int k = 0; k < 7; ++k) {
        Eigen::Vector2i other = self + shift[k];
        if (0 <= other(0) && other(0) < M && 0 <= other(1) && other(1) < M) {
          tripletList.push_back(Eigen::Triplet<double>(
              self(0) + M * self(1), other(0) + M * other(1), contribution[k]));
        }
      }
    }
  }
  A.setFromTriplets(tripletList.begin(), tripletList.end());
  return A;
}
/* SAM_LISTING_END_1 */

/* SAM_LISTING_BEGIN_2 */
Eigen::SparseMatrix<double> computeGalerkinMatrix(int M, double c) {
  Eigen::Matrix3d B_K;
  double h = 1.0 / (M + 1);
  Eigen::Matrix3d A_K;
  A_K << 1.0, -0.5, -0.5, -0.5, 0.5, 0.0, -0.5, 0.0, 0.5;
  Eigen::Matrix3d M_K;
  M_K << 2.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0, 2.0;
  M_K *= h * h / 24.0;
  B_K = (1.0 - c) * A_K + c * M_K;
  return assemble(M, B_K);
}
/* SAM_LISTING_END_2 */

/* SAM_LISTING_BEGIN_4 */
Eigen::SparseMatrix<double> computeGalerkinMatrixTR(int M, double c) {
  Eigen::Matrix3d B_K;
  double h = 1.0 / (M + 1);
  Eigen::Matrix3d A_K;
  A_K << 1.0, -0.5, -0.5, -0.5, 0.5, 0.0, -0.5, 0.0, 0.5;
  Eigen::Matrix3d M_K = h * h / 6.0 * Eigen::Matrix3d::Identity();
  B_K = (1.0 - c) * A_K + c * M_K;
  return assemble(M, B_K);
}
/* SAM_LISTING_END_4 */

}  // namespace MaximumPrinciple

ext: cc

max_stars_repo_name: padomu/NPDECODES

max_issues_repo_name: padomu/NPDECODES

max_forks_repo_name: padomu/NPDECODES


text:
//==================================================================================================
/**
  Copyright 2016 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
**/
//==================================================================================================
#include <boost/simd/function/scalar/store.hpp>
#include <boost/simd/mask.hpp>
#include <boost/simd/logical.hpp>

#include <scalar_test.hpp>

namespace bs = boost::simd;

STF_CASE_TPL( "Check store behavior with simple pointer with or without offset and mask", STF_NUMERIC_TYPES )
{
  T src(42), res(0);

  bs::store(src, &res);
  STF_EQUAL(res, src );

  T src1[4] = {T(1), T(2), T(3), T(4)};
  T res1[4] = {T(0), T(0), T(0), T(0)};
  for(int i=0; i < 4 ; ++i)
  {
    bs::store(src1[i], &res1[0], i);
    STF_EQUAL(res1[i], src1[i] );
  }
}

STF_CASE_TPL( "Check store behavior with masked pointer with or without offset and mask", STF_NUMERIC_TYPES )
{
  T res(0);
  bs::store(T(42), bs::mask(&res, true));
  STF_EQUAL(res, T(42) );

  bs::store(T(69), bs::mask(&res, false));
  STF_EQUAL(res, T(42) );

  T src1[4] = {T(1), T(2), T(3), T(4)};
  T res1[4] = {T(0), T(0), T(0), T(0)};

  for(int i=0; i < 4 ; ++i) bs::store(src1[i], bs::mask(&res1[0], i%2), i);
  for(int i=0; i < 4 ; ++i) STF_EQUAL(res1[i], i%2 ? src1[i] : 0);
}


text:
#include <iostream>
#include <string>

#include <openssl/md5.h>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>

std::string md5(unsigned char* ptr, size_t size) {
    char output[32 + 1];
    unsigned char digest[16];
    const char *fmt =
        "%02x%02x%02x%02x%02x%02x%02x%02x"
        "%02x%02x%02x%02x%02x%02x%02x%02x";

    MD5((const unsigned char*)ptr, size, digest);

    snprintf(output,
        sizeof(output)/sizeof(output[0]),
        fmt,
        digest[0], digest[1], digest[2], digest[3],
        digest[4], digest[5], digest[6], digest[7],
        digest[8], digest[9], digest[10], digest[11],
        digest[12], digest[13], digest[14], digest[15]
    );

    return output;
}

bool check(unsigned char* target_ptr, size_t target_size, unsigned char* signature_ptr, size_t signature_size) {
    bool has_hit = false;

    unsigned char digest[MD5_DIGEST_LENGTH];
    std::string target = md5(target_ptr, target_size);
    std::cout << target << std::endl;

    std::string signature(reinterpret_cast<char const*>(signature_ptr), signature_size -1);
    std::list<std::string> signatures_list;

    boost::split(signatures_list, signature, boost::is_any_of("\n"));
    BOOST_FOREACH(signature, signatures_list) {
        has_hit |= signature == target;
    }

    return has_hit;
}

extern "C" {
    bool scan(unsigned char* target, size_t target_size, unsigned char* signature, size_t signature_size) {
        return check(target, target_size, signature, signature_size);
    }
}


text:
#include "taskgraph/task/FileUncompress.h"
#include "taskgraph/TaskHelper.h"
#include "taskgraph/ParamImpl.h"

#include <Alloc.h>
#include <LzmaDec.h>

#include <boost/filesystem.hpp>

namespace
{

static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };

#define LZMA_PROPS_SIZE 5

struct block {
    uint8_t size[4];
    uint8_t prop[LZMA_PROPS_SIZE];
    uint8_t data[119];
};

}

namespace taskgraph
{
namespace task
{

void FileUncompress::Execute(const std::shared_ptr<dag::Context>& ctx)
{
    std::string filepath;
    auto prev_param = TaskHelper::GetInputParam(*this, 0);
    if (prev_param)
    {
        assert(prev_param->Type() == PT_FILE);
        filepath = std::static_pointer_cast<FileParam>(prev_param)->GetFilepath();
    }
    else
    {
        filepath = m_filepath;
    }

    if (!boost::filesystem::exists(filepath)) {
        return;
    }

    std::ifstream fin(filepath.c_str(), std::ios::binary | std::ios::ate);
    if (fin.fail()) {
        return;
    }

    size_t size = static_cast<uint8_t>(fin.tellg());
    fin.seekg(0, std::ios::beg);

    uint8_t* c_buf = new uint8_t[size];
    struct block* block = (struct block*)c_buf;
    fin.read(reinterpret_cast<char*>(block), size);
    fin.close();

    size_t uc_sz = size * 10;		// FIXME
    size_t guess_sz = uc_sz;
    uint8_t* uc_buf = new uint8_t[uc_sz];
    size_t c_sz = size - sizeof(block->size) - LZMA_PROPS_SIZE;
    Uncompress(uc_buf, &uc_sz, block->data, &c_sz, block->prop, LZMA_PROPS_SIZE);
    if (guess_sz == uc_sz) {
        return;
    }
    delete[] c_buf;

    m_vals.resize(1);
    m_vals[0] = std::make_shared<BufferParam>(uc_buf);
}

int FileUncompress::Uncompress(unsigned char* dst, size_t* dst_len, const unsigned char* src, size_t* src_len,
                               const unsigned char* props, size_t props_sz)
{
    ELzmaStatus status;
    return LzmaDecode(dst, dst_len, src, src_len, props, (unsigned)props_sz, LZMA_FINISH_ANY, &status, &g_Alloc);
}

}
}

max_stars_repo_name: xzrunner/taskgraph

max_issues_repo_name: xzrunner/taskgraph

max_forks_repo_name: xzrunner/taskgraph


text:
// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#ifdef _MSC_VER
#pragma warning(disable:4244)
#pragma warning(disable:4267)
#pragma warning(disable:4996)
#endif

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <iostream>

#include <boost/program_options.hpp>
namespace po = boost::program_options;

#include <vw/Core/Cache.h>
#include <vw/Core/ProgressCallback.h>
#include <vw/Math/Matrix.h>
#include <vw/Image/Palette.h>
#include <vw/Image/Transform.h>
#include <vw/FileIO/DiskImageResource.h>
#include <vw/FileIO/DiskImageResourceGDAL.h>
#include <vw/FileIO/DiskImageView.h>
#include <vw/Cartography/GeoReference.h>

using namespace vw;
using namespace vw::math;
using namespace vw::cartography;

int main( int argc, char *argv[] ) {

  std::string input_filename, output_filename, copy_filename, tfw_filename;
  double north_lat=90.0, south_lat=-90.0;
  double east_lon=180.0, west_lon=-180.0;
  double proj_lat=0, proj_lon=0, proj_scale=1;
  unsigned utm_zone;
  double nudge_x=0, nudge_y=0;

  po::options_description general_options("General Options");
  general_options.add_options()
    ("output-file,o", po::value<std::string>(&output_filename)->default_value("output.tif"), "Specify the base output filename")
    ("help,h", "Display this help message");

  po::options_description projection_options("Projection Options");
  projection_options.add_options()
    ("copy", po::value<std::string>(&copy_filename), "Copy the projection from the given file")
    ("tfw", po::value<std::string>(&tfw_filename), "Create a .tfw sidecar file with the given filename rather than a full copy of the image file")
    ("north", po::value<double>(&north_lat), "The northernmost latitude in degrees")
    ("south", po::value<double>(&south_lat), "The southernmost latitude in degrees")
    ("east", po::value<double>(&east_lon), "The easternmost longitude in degrees")
    ("west", po::value<double>(&west_lon), "The westernmost longitude in degrees")
    ("sinusoidal", "Assume a sinusoidal projection")
    ("mercator", "Assume a Mercator projection")
    ("transverse-mercator", "Assume a transverse Mercator projection")
    ("orthographic", "Assume an orthographic projection")
    ("stereographic", "Assume a stereographic projection")
    ("lambert-azimuthal", "Assume a Lambert azimuthal projection")
    ("utm", po::value<unsigned>(&utm_zone), "Assume UTM projection with the given zone")
    ("proj-lat", po::value<double>(&proj_lat), "The center of projection latitude (if applicable)")
    ("proj-lon", po::value<double>(&proj_lon), "The center of projection longitude (if applicable)")
    ("proj-scale", po::value<double>(&proj_scale), "The projection scale (if applicable)")
    ("nudge-x", po::value<double>(&nudge_x), "Nudge the image, in projected coordinates")
    ("nudge-y", po::value<double>(&nudge_y), "Nudge the image, in projected coordinates")
    ("pixel-as-point", "Encode that the pixel location (0,0) is the center of the upper left hand pixel (the default, if you specify nothing, is to set the upper left hand corner of the upper left pixel as (0,0) (i.e. PixelAsArea).");

  po::options_description hidden_options("");
  hidden_options.add_options()
    ("input-file", po::value<std::string>(&input_filename));

  po::options_description options("Allowed Options");
  options.add(general_options).add(projection_options).add(hidden_options);

  po::positional_options_description p;
  p.add("input-file", -1);

  std::ostringstream usage;
  usage << "Description: Specify planetary coordinates for an image" << std::endl << std::endl;
  usage << "Usage: " << argv[0] << " [options] <filename>..." << std::endl << std::endl;
  usage << general_options << std::endl;
  usage << projection_options << std::endl;

  po::variables_map vm;
  try {
    po::store( po::command_line_parser( argc, argv ).options(options).positional(p).run(), vm );
    po::notify( vm );
  } catch(po::error &e) {
    std::cout << "An error occured while parsing command line arguments.\n";
    std::cout << "\t" << e.what() << "\n\n";
    std::cout << usage.str();
    return 1;
  }

  if( vm.count("help") ) {
    std::cout << usage.str();
    return 1;
  }

  if( vm.count("input-file") < 1 ) {
    std::cout << "Error: Must specify at least one input file!" << std::endl << std::endl;
    std::cout << usage.str();
    return 1;
  }

  GeoReference output_georef;
  output_georef.set_well_known_geogcs("WGS84");

  // Read in georeference info and compute total resolution
  bool manual = vm.count("north") || vm.count("south") || vm.count("east") || vm.count("west");

  DiskImageResourceGDAL file_resource( input_filename );
  GeoReference georef;
  if( vm.count("copy") ) {
    read_georeference( georef, copy_filename );
  } else {
    read_georeference( georef, file_resource );
  }

  if ( georef.proj4_str() == "" ) georef.set_well_known_geogcs("WGS84");
  if( manual || georef.transform() == identity_matrix<3>() ) {
    if( manual ) {
      vw_out() << "Using manual Plate Carree coordinates: ";
      georef = GeoReference(georef.datum());
    } else {
      vw_out() << "No georeferencing info found.  Assuming Plate Carree WGS84: ";
      georef = GeoReference();
      georef.set_well_known_geogcs("WGS84");
    }
    vw_out() << east_lon << " E to " << west_lon << " W, "
             << south_lat << " S to " << north_lat << " N." << std::endl;

    Matrix3x3 m;
    m(0,0) = (east_lon - west_lon) / file_resource.cols();
    m(0,2) = west_lon;
    m(1,1) = (south_lat - north_lat) / file_resource.rows();
    m(1,2) = north_lat;
    m(2,2) = 1;
    georef.set_transform( m );
    manual = true;
  }
  else if( vm.count("sinusoidal") ) georef.set_sinusoidal(proj_lon);
  else if( vm.count("mercator") ) georef.set_mercator(proj_lat,proj_lon,proj_scale);
  else if( vm.count("transverse-mercator") ) georef.set_transverse_mercator(proj_lat,proj_lon,proj_scale);
  else if( vm.count("orthographic") ) georef.set_orthographic(proj_lat,proj_lon);
  else if( vm.count("stereographic") ) georef.set_stereographic(proj_lat,proj_lon,proj_scale);
  else if( vm.count("lambert-azimuthal") ) georef.set_lambert_azimuthal(proj_lat,proj_lon);
  else if( vm.count("utm") ) georef.set_UTM( utm_zone );

  if (vm.count("pixel-as-point"))
    georef.set_pixel_interpretation(GeoReference::PixelAsPoint);
  else // Default: PixelAsArea
    georef.set_pixel_interpretation(GeoReference::PixelAsArea);

  if( vm.count("nudge-x") || vm.count("nudge-y") ) {
    Matrix3x3 m = georef.transform();
    m(0,2) += nudge_x;
    m(1,2) += nudge_y;
    georef.set_transform( m );
  }

  vw_out() << "Writing file with Proj4 String: " << georef.proj4_str() << "\n";

  // Our file readers do a better job that GDAL's of coping with large
  // image files in some cases, so we make a fresh DiskImageView rather
  // than making an ImageResourceView of the existing GDAL resource.

  if (vm.count("tfw")) {
    std::ofstream tfw_file(tfw_filename.c_str());
    tfw_file << georef.transform()(0,0) << "\n";
    tfw_file << georef.transform()(0,1) << "\n";
    tfw_file << georef.transform()(1,0) << "\n";
    tfw_file << georef.transform()(1,1) << "\n";
    if (vm.count("pixel-as-point")) {
      tfw_file << georef.transform()(0,2) << "\n";
      tfw_file << georef.transform()(1,2) << "\n";
    } else {
      tfw_file << georef.transform()(0,2) + 0.5*georef.transform()(0,0) << "\n";
      tfw_file << georef.transform()(1,2) + 0.5*georef.transform()(1,1) << "\n";
    }
    tfw_file.close();
  } else {
    TerminalProgressCallback bar( "tools.georef", "Writing:" );
    switch( file_resource.channel_type() ) {
    case VW_CHANNEL_INT16:
      switch( file_resource.pixel_format() ) {
      case VW_PIXEL_SCALAR: {
        DiskImageView<int16> input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_GRAY: {
        DiskImageView<PixelGray<int16> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_GRAYA: {
        DiskImageView<PixelGrayA<int16> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_RGB: {
        DiskImageView<PixelRGB<int16> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_RGBA: {
        DiskImageView<PixelRGBA<int16> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      default: {
        vw_throw( NoImplErr() << "Unsupported pixel format: " << file_resource.pixel_format() );
        break;
      }
      }
      break;
    case VW_CHANNEL_UINT16:
      switch( file_resource.pixel_format() ) {
      case VW_PIXEL_SCALAR: {
        DiskImageView<uint16> input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_GRAY: {
        DiskImageView<PixelGray<uint16> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_GRAYA: {
        DiskImageView<PixelGrayA<uint16> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_RGB: {
        DiskImageView<PixelRGB<uint16> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_RGBA: {
        DiskImageView<PixelRGBA<uint16> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      default: {
        vw_throw( NoImplErr() << "Unsupported pixel format: " << file_resource.pixel_format() );
        break;
      }
      }
      break;
    case VW_CHANNEL_FLOAT32:
      switch( file_resource.pixel_format() ) {
      case VW_PIXEL_SCALAR: {
        DiskImageView<float32> input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_GRAY: {
        DiskImageView<PixelGray<float32> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_GRAYA: {
        DiskImageView<PixelGrayA<float32> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_RGB: {
        DiskImageView<PixelRGB<float32> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_RGBA: {
        DiskImageView<PixelRGBA<float32> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      default: {
        vw_throw( NoImplErr() << "Unsupported pixel format: " << file_resource.pixel_format() );
        break;
      }
      }
      break;
    default:
      switch( file_resource.pixel_format() ) {
      case VW_PIXEL_SCALAR: {
        DiskImageView<uint8> input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_GRAY: {
        DiskImageView<PixelGray<uint8> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_GRAYA: {
        DiskImageView<PixelGrayA<uint8> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_RGB: {
        DiskImageView<PixelRGB<uint8> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      case VW_PIXEL_RGBA: {
        DiskImageView<PixelRGBA<uint8> > input_image( input_filename );
        write_georeferenced_image( output_filename, input_image, georef, bar );
        break;
      }
      default: {
        vw_throw( NoImplErr() << "Unsupported pixel format: " << file_resource.pixel_format() );
        break;
      }
      }
      break;
    }
  }
  return 0;
}

max_stars_repo_name: tkeemon/visionworkbench

max_issues_repo_name: tkeemon/visionworkbench

max_forks_repo_name: tkeemon/visionworkbench


text:
/*
// Licensed to DynamoBI Corporation (DynamoBI) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  DynamoBI licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at

//   http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
*/

#include "fennel/common/CommonPreamble.h"
#include "fennel/test/TestBase.h"
#include "fennel/calculator/SqlRegExp.h"
#include "fennel/common/TraceSource.h"
#include "fennel/calctest/SqlStringBuffer.h"

#include <boost/test/test_tools.hpp>
#include <boost/scoped_array.hpp>
#include <boost/regex.hpp>

#include <string>
#include <limits>
#include <iostream>

#ifdef HAVE_ICU
#include <unicode/unistr.h>
#include <unicode/uloc.h>
#endif

using namespace fennel;
using namespace std;

class SqlRegExpTest : virtual public TestBase, public TraceSource
{
    void testSqlRegExpLikeAsciiTrue();
    void testSqlRegExpLikeAsciiFalse();
    void testSqlRegExpLikeAsciiEscapeTrue();
    void testSqlRegExpLikeAsciiEscapeFalse();
    void testSqlRegExpLikeAsciiException();

    void testSqlRegExpSimilarAscii();
    void testSqlRegExpSimilarAsciiEscape();
    void testSqlRegExpSimilarAsciiException();

public:
    explicit SqlRegExpTest()
        : TraceSource(shared_from_this(), "SqlRegExpTest")
    {
        srand(time(NULL));

        FENNEL_UNIT_TEST_CASE(SqlRegExpTest, testSqlRegExpLikeAsciiTrue);
        FENNEL_UNIT_TEST_CASE(SqlRegExpTest, testSqlRegExpLikeAsciiFalse);
        FENNEL_UNIT_TEST_CASE(SqlRegExpTest, testSqlRegExpLikeAsciiEscapeTrue);
        FENNEL_UNIT_TEST_CASE(SqlRegExpTest, testSqlRegExpLikeAsciiEscapeFalse);
        FENNEL_UNIT_TEST_CASE(SqlRegExpTest, testSqlRegExpLikeAsciiException);

        FENNEL_UNIT_TEST_CASE(SqlRegExpTest, testSqlRegExpSimilarAscii);
        FENNEL_UNIT_TEST_CASE(SqlRegExpTest, testSqlRegExpSimilarAsciiEscape);
        FENNEL_UNIT_TEST_CASE(
            SqlRegExpTest, testSqlRegExpSimilarAsciiException);
    }

    virtual ~SqlRegExpTest()
    {
    }
};

void
SqlRegExpTest::testSqlRegExpLikeAsciiTrue()
{
    bool result = false;
    int i;

    const char* test[][2] = {
        // pattern, matchValue

        // SQL99 Part 2 Section 8.5 General Rule 3.d.i
        { "",    "" },

        { "_",   "a" },
        { "a",   "a" },
        { "abc", "abc" },
        { "_bc", "abc" },
        { "a_c", "abc" },
        { "ab_", "abc" },
        { "a__", "abc" },
        { "_b_", "abc" },
        { "__c", "abc" },

        { "%",   "" },
        { "%",   "a" },
        { "%",   "abc" },
        { "%b",  "ab" },
        { "a%",  "ab" },
        { "ab%", "abc" },
        { "a%c", "abc" },
        { "%bc", "abc" },
        { "a%",  "abc" },
        { "%b%", "abc" },
        { "%c",  "abc" },
        { "%abc", "abc" },
        { "abc%", "abc" },

        // ensure that regex special chars are OK
        // and escaped properly
        { ".|*?+(){}[]^$\\",  ".|*?+(){}[]^$\\" },
        { "%.|*?+(){}[]^$\\", ".|*?+(){}[]^$\\" },
        { ".|*?+(){}[]^$\\%", ".|*?+(){}[]^$\\" },
        { "%){}[]^$\\",       ".|*?+(){}[]^$\\" },
        { ".|*?+()%",         ".|*?+(){}[]^$" },
        { "%$",               ".|*?+(){}[]^$" },
        { ".|*%",             ".|*?+(){}[]^$" },

        { "\\",      "\\" },
        { "a\\c",    "a\\c" },
        { "a\\%de",  "a\\cde" },
        { "a\\_de",  "a\\cde" },
        { "a\\.de",  "a\\.de" },

        { "X", "X" }  // end sentinel
    };
    string expPat;
    for (i = 0; *test[i][0] != 'X'; i++) {
        BOOST_MESSAGE("      true " << i << " " <<test[i][0]);
        try {
            SqlLikePrep<1, 1>(
                test[i][0],
                strlen(test[i][0]),
                0, 0,    // no escape
                expPat);
            boost::regex exp(expPat);
            result = SqlRegExp<1, 1>(
                test[i][1],
                strlen(test[i][1]),
                strlen(test[i][0]),
                exp);
        } catch (char const * const ptr) {
            // unexpected exception
            BOOST_MESSAGE("unexpected SQL exception: " << ptr);
            BOOST_CHECK(0);
        } catch (boost::bad_expression badexp) {
            // regex format problem
            BOOST_MESSAGE(
                "unexpected regex exception: " << badexp.what());
            BOOST_CHECK(0);
        } catch (...) {
            // unexpected exception
            BOOST_MESSAGE("unexpected unknown exception");
            BOOST_CHECK(0);
        }

        if (!result) {
            BOOST_MESSAGE(
                "|" << test[i][1]
                << "| |" << test[i][0] << "|");
        }

        BOOST_CHECK(result);
    }
}

void
SqlRegExpTest::testSqlRegExpLikeAsciiFalse()
{
    bool result = false;
    int i;
    const char* test[][2] = {
        // pattern,    matchValue
        { "",    "a" },
        { "_",    "" },
        { "a",    "" },
        { "a",    "b" },
        { "b",    "ab" },
        { "a",    "ab" },
        { "__",    "a" },
        { "abc",    "Abc" },
        { "abc",    "aBc" },
        { "abc",    "abC" },
        { "_bc",    "aBc" },
        { "_bc",    "abC" },
        { "a_c",    "Abc" },
        { "ab_",    "aBc" },
        { "a__",    "Abc" },
        { "_b_",    "aBc" },
        { "__c",    "abC" },

        { "%b",     "a" },
        { "a%",     "b" },
        { "ab%",    "ac" },
        { "a%c",    "ab" },
        { "%bc",    "ab" },
        { "%b%",    "aBc" },
        { "%c",     "ab" },
        { "%abc", "ac" },
        { "%abc", "bc" },
        { "%abc", "ab" },
        { "abc%", "ab" },
        { "abc%", "ac" },
        { "abc%", "bc" },

        { "\\",      "a" },
        { "a",       "\\" },
        { "a\\c",    "a\\" },
        { "a\\c",    "\\c" },
        { "\\c",    "a\\" },
        { "a\\",    "\\c" },

        { "X",    "X" }  // end sentinel
    };
    string expPat;
    for (i = 0; *test[i][0] != 'X'; i++) {
        BOOST_MESSAGE("      false " << i << " " <<test[i][0]);
        try {
            SqlLikePrep<1, 1>(
                test[i][0],
                strlen(test[i][0]),
                0, 0,   // no escape
                expPat);
            boost::regex exp(expPat);
            result = SqlRegExp<1, 1>(
                test[i][1],
                strlen(test[i][1]),
                strlen(test[i][0]),
                exp);
        } catch (char const * const ptr) {
            // unexpected exception
            BOOST_MESSAGE("unexpected SQL exception: " << ptr);
            BOOST_CHECK(0);
        } catch (boost::bad_expression badexp) {
            // regex format problem
            BOOST_MESSAGE(
                "unexpected regex exception: " << badexp.what());
            BOOST_CHECK(0);
        } catch (...) {
            // unexpected exception
            BOOST_MESSAGE("unexpected unknown exception");
            BOOST_CHECK(0);
        }

        if (result) {
            BOOST_MESSAGE(
                "|" << test[i][1]
                << "| |" << test[i][0] << "|");
        }

        BOOST_CHECK(!result);
    }
}

void
SqlRegExpTest::testSqlRegExpLikeAsciiEscapeTrue()
{
    bool result = false;
    int i;

    const char* test[][3] = {
        // pattern, matchValue, escape
        // define new escape
        { "_",      "a",  "#" },
        { "#_",    "_",   "#" },
        { "##",    "#",   "#" },
        { "#_bc",  "_bc", "#" },
        { "a#_c",  "a_c", "#" },
        { "ab#_",  "ab_", "#" },

        { "#%",    "%",   "#" },
        { "#%bc",  "%bc", "#" },
        { "a#%c",  "a%c", "#" },
        { "ab#%",  "ab%", "#" },
        { "%",     "a",   "#" },
        { "#%",    "%",   "#" },

        // define new escape that is special regexp char
        { "_",     "a",   "|" },
        { "|_",    "_",   "|" },
        { "||",    "|",   "|" },
        { "|_bc",  "_bc", "|" },
        { "a|_c",  "a_c", "|" },
        { "ab|_",  "ab_", "|" },

        { "|%",    "%",   "|" },
        { "|%bc",  "%bc", "|" },
        { "a|%c",  "a%c", "|" },
        { "ab|%",  "ab%", "|" },
        { "%",     "a",   "|" },
        { "|%",    "%",   "|" },

        // define new escape that is special regexp char
        { "_",     "a",   ")" },
        { ")_",    "_",   ")" },
        { "))",    ")",   ")" },
        { ")_bc",  "_bc", ")" },
        { "a)_c",  "a_c", ")" },
        { "ab)_",  "ab_", ")" },

        { ")%",    "%",   ")" },
        { ")%bc",  "%bc", ")" },
        { "a)%c",  "a%c", ")" },
        { "ab)%",  "ab%", ")" },
        { "%",     "a",   ")" },
        { ")%",    "%",   ")" },

        { "X",     "X",   "X" }  // end sentinel
    };
    string expPat;
    for (i = 0; *test[i][0] != 'X'; i++) {
        BOOST_MESSAGE("      escape true " << i << " " <<test[i][0]);
        try {
            SqlLikePrep<1, 1>(
                test[i][0],
                strlen(test[i][0]),
                test[i][2],
                strlen(test[i][2]),
                expPat);
            boost::regex exp(expPat);
            result = SqlRegExp<1, 1>(
                test[i][1],
                strlen(test[i][1]),
                strlen(test[i][0]),
                exp);
        } catch (char const * const ptr) {
            // unexpected exception
            BOOST_MESSAGE("unexpected SQL exception: " << ptr);
            BOOST_CHECK(0);
        } catch (boost::bad_expression badexp) {
            // regex format problem
            BOOST_MESSAGE(
                "unexpected regex exception: " << badexp.what());
            BOOST_CHECK(0);
        } catch (...) {
            // unexpected exception
            BOOST_MESSAGE("unexpected unknown exception");
            BOOST_CHECK(0);
        }

        if (!result) {
            BOOST_MESSAGE(
                "|" << test[i][1]
                << "| |" << test[i][0] << "|");
        }

        BOOST_CHECK(result);
    }
}

void
SqlRegExpTest::testSqlRegExpLikeAsciiEscapeFalse()
{
    bool result = false;
    int i;

    const char* test[][3] = {
        // pattern, matchValue, escape

        { "_",    "ab",  "#" },
        { "#_",   "_a",  "#" },
        { "#_",   "a_",  "#" },
        { "#_",   "a",   "#" },
        { "#_",   "__",  "#" },
        { "#_",   "a",   "#" },
        { "##",   "a",   "#" },
        { "#_#_", "a",   "#" },
        { "#_#_", "_",   "#" },
        { "#_#_", "_a",  "#" },
        { "#_#_", "a_",  "#" },
        { "#_bc", "abc", "#" },
        { "a#_c", "abc", "#" },
        { "ab#_", "abc", "#" },

        { "#%",   "a",   "#" },
        { "#%",   "ab",  "#" },
        { "#%",   "a",   "#" },
        { "#%bc", "abc", "#" },
        { "a#%c", "abc", "#" },
        { "ab#%", "abc", "#" },

        // define escape that is special regexp char
        { "_",    "ab",  "|" },
        { "|_",   "_a",  "|" },
        { "|_",   "a_",  "|" },
        { "|_",   "a",   "|" },
        { "||",   "a",   "|" },
        { "|%",   "a",   "|" },
        { "|%",   "ab",  "|" },

        // define escape that is special regexp char
        { "_",    "ab",  ")" },
        { ")_",   "_a",  ")" },
        { ")_",   "a_",  ")" },
        { ")_",   "a",   ")" },
        { "))",   "a",   ")" },
        { ")%",   "a",   ")" },
        { ")%",   "ab",  ")" },

        { "X",    "X",   "X" }  // end sentinel
    };
    string expPat;
    for (i = 0; *test[i][0] != 'X'; i++) {
        BOOST_MESSAGE("      escapefalse " << i << " " <<test[i][0]);
        try {
            SqlLikePrep<1, 1>(
                test[i][0],
                strlen(test[i][0]),
                test[i][2],
                strlen(test[i][2]),
                expPat);
            boost::regex exp(expPat);
            result = SqlRegExp<1, 1>(
                test[i][1],
                strlen(test[i][1]),
                strlen(test[i][0]),
                exp);
        } catch (char const * const ptr) {
            // unexpected exception
            BOOST_MESSAGE("unexpected SQL exception: " << ptr);
            BOOST_CHECK(0);
        } catch (boost::bad_expression badexp) {
            // regex format problem
            BOOST_MESSAGE(
                "unexpected regex exception: " << badexp.what());
            BOOST_CHECK(0);
        } catch (...) {
            // unexpected exception
            BOOST_MESSAGE("unexpected unknown exception");
            BOOST_CHECK(0);
        }

        if (result) {
            BOOST_MESSAGE(
                "|" << test[i][1]
                << "| |" << test[i][0] << "|");
        }

        BOOST_CHECK(!result);
    }
}

void
SqlRegExpTest::testSqlRegExpLikeAsciiException()
{
    bool caught = false;
    bool result = false;
    int i;

    const char* test[][4] = {
        // pattern, matchValue, escape, exception
        { "=",       "a",       "=",       "22025" },
        { "=a",       "a",       "=",      "22025" },

        { "a",       "a",       "ab",      "22019" },
        { "a",       "a",       "\\\\",    "22019" },

        { "X",       "X",       "X",       "X" }  // end sentinel
    };
    string expPat;
    for (i = 0; *test[i][0] != 'X'; i++) {
        BOOST_MESSAGE("      exception " << i << " " <<test[i][0]);
        caught = false;
        try {
            SqlLikePrep<1, 1>(
                test[i][0],
                strlen(test[i][0]),
                test[i][2],
                strlen(test[i][2]),
                expPat);
            boost::regex exp(expPat);
            result = SqlRegExp<1, 1>(
                test[i][1],
                strlen(test[i][1]),
                strlen(test[i][0]),
                exp);
        } catch (SqlStateInfo const &ex) {
            caught = true;
            BOOST_CHECK(!strcmp(ex.str().c_str(), test[i][3]));
        }
        if (!caught) {
            BOOST_CHECK(0);
        }
    }
}

void
SqlRegExpTest::testSqlRegExpSimilarAscii()
{
    bool result = false;
    int i;

    const char* test[][3] = {
        // pattern, matchValue, result

        // {2}
        // SQL2003 Part 2 Section 8.6 General Rule 6.a & 7.d
        { "a{2}",      "aa",     "t" },
        { "a{2}b",     "aab",    "t" },
        { "(bc){2}",   "bcbc",   "t" },
        { "(bc){2}d",  "bcbcd",  "t" },
        { "a(bc){2}",  "abcbc",  "t" },
        { "[bc]{2}",   "bb",     "t" },
        { "[bc]{2}",   "cc",     "t" },
        { "[bc]{2}",   "bc",     "t" },
        { "[bc]{2}",   "cb",     "t" },

        { "a{2}",      "",       "f" },
        { "a{2}",      "a",      "f" },
        { "a{2}",      "ac",     "f" },
        { "a{2}",      "aaa",    "f" },
        { "a{2}",      "ab",     "f" },
        { "a{2}b",     "",       "f" },
        { "a{2}b",     "b",      "f" },
        { "a{2}b",     "ab",     "f" },
        { "a{2}b",     "aa",     "f" },
        { "a{2}b",     "ab",     "f" },
        { "(bc){2}",   "",       "f" },
        { "(bc){2}",   "a",      "f" },
        { "(bc){2}",   "bc",     "f" },
        { "(bc){2}",   "bcbcb",  "f" },
        { "[bc]{2}",   "",       "f" },
        { "[bc]{2}",   "a",      "f" },
        { "[bc]{2}",   "b",      "f" },
        { "[bc]{2}",   "c",      "f" },
        { "[bc]{2}",   "ad",     "f" },
        { "[bc]{2}",   "",       "f" },
        { "[bc]{2}",   "bbc",    "f" },

        // {2,3}
        // SQL2003 Part 2 Section 8.6 General Rule 6.b & 7.d
        // <upper limit> w/ <high value>
        { "a{2,3}",    "aa",     "t" },
        { "a{2,3}",    "aaa",    "t" },
        { "a{2,3}b",   "aab",    "t" },
        { "a{2,3}b",   "aaab",   "t" },
        { "(bc){2,3}", "bcbc",   "t" },
        { "(bc){2,3}", "bcbcbc", "t" },
        { "[bc]{2,3}", "bb",     "t" },
        { "[bc]{2,3}", "bbb",    "t" },
        { "[bc]{2,3}", "cc",     "t" },
        { "[bc]{2,3}", "ccc",    "t" },
        { "[bc]{2,3}", "bcb",    "t" },
        { "[bc]{2,3}", "cbc",    "t" },

        { "a{2,3}",    "",       "f" },
        { "a{2,3}",    "a",      "f" },
        { "a{2,3}",    "aaaa",   "f" },
        { "a{2,3}",    "aab",    "f" },
        { "(bc){2,3}", "",       "f" },
        { "(bc){2,3}", "a",      "f" },
        { "(bc){2,3}", "bc",     "f" },
        { "(bc){2,3}", "cbcb",   "f" },
        { "[bc]{2,3}", "",       "f" },
        { "[bc]{2,3}", "a",      "f" },
        { "[bc]{2,3}", "b",      "f" },
        { "[bc]{2,3}", "c",      "f" },
        { "[bc]{2,3}", "bcbcbc", "f" },
        { "[bc]{2,3}", "bcbcbcb", "f" },
        { "[bc]{2,3}", "",       "f" },
        { "[bc]{2,3}", "bbcc",   "f" },

        // {2,}
        // SQL2003 Part 2 Section 8.6 General Rule 6.c & 7.d
        // <upper limit> w/o <high value>
        // 98.6% sure that I'm interpreting this correctly. -JK 2004/6
        { "a{2,}",    "aa",     "t" },
        { "a{2,}",    "aaa",    "t" },
        { "a{2,}",    "aaaa",    "t" },
        { "a{2,}b",   "aab",    "t" },
        { "a{2,}b",   "aaab",   "t" },
        { "(bc){2,}", "bcbc",   "t" },
        { "(bc){2,}", "bcbcbc", "t" },
        { "[bc]{2,}", "bb",     "t" },
        { "[bc]{2,}", "bbb",    "t" },
        { "[bc]{2,}", "cc",     "t" },
        { "[bc]{2,}", "ccc",    "t" },
        { "[bc]{2,}", "bcb",    "t" },
        { "[bc]{2,}", "cbc",    "t" },

        { "a{2,}",    "",       "f" },
        { "a{2,}",    "a",      "f" },
        { "a{2,}",    "aab",    "f" },
        { "(bc){2,}", "",       "f" },
        { "(bc){2,}", "a",      "f" },
        { "(bc){2,}", "bc",     "f" },
        { "(bc){2,}", "cbcb",   "f" },
        { "(bc){2,}", "bcbcb",  "f" },
        { "[bc]{2,}", "",       "f" },
        { "[bc]{2,}", "a",      "f" },
        { "[bc]{2,}", "b",      "f" },
        { "[bc]{2,}", "c",      "f" },
        { "[bc]{2,}", "bcd",    "f" },

        // |
        // SQL2003 Part 2 Section 8.6 General Rule 7.a
        { "a|b",      "a",      "t" },
        { "a|b",      "b",      "t" },
        { "a|bc",     "a",      "t" },
        { "a|bc",     "bc",     "t" },
        { "(a|b)c",   "ac",     "t" },
        { "(a|b)c",   "bc",     "t" },

        { "a|b",      "c",      "f" },
        { "a|bc",     "c",      "f" },
        { "a|bc",     "ac",     "f" },
        { "(a|b)c",   "c",      "f" },
        { "(a|b)c",   "dc",     "f" },

        // *
        // SQL2003 Part 2 Section 8.6 General Rule 7.b
        { "a*b",      "b",      "t" },
        { "a*b",      "ab",     "t" },
        { "a*b",      "aab",    "t" },
        { "ab*",      "a",      "t" },
        { "ab*",      "ab",     "t" },
        { "ab*",      "abb",    "t" },
        { "a(bc)*",   "a",      "t" },
        { "a(bc)*",   "abc",    "t" },
        { "a(bc)*",   "abcbc",  "t" },
        { "a[bc]*",   "a",      "t" },
        { "a[bc]*",   "ab",     "t" },
        { "a[bc]*",   "ac",     "t" },
        { "a[bc]*",   "abb",    "t" },
        { "a[bc]*",   "abc",    "t" },
        { "a[bc]*",   "abc",    "t" },
        { "a[bc]*",   "acc",    "t" },
        { "a[bc]*",   "abbb",   "t" },
        { "a[bc]*",   "accc",   "t" },

        { "a*b",      "",       "f" },
        { "a*b",      "a",      "f" },
        { "a*b",      "ac",     "f" },
        { "ab*",      "b",      "f" },
        { "ab*",      "ac",     "f" },
        { "a(bc)*",   "",       "f" },
        { "a(bc)*",   "ad",     "f" },
        { "a(bc)*",   "abd",    "f" },
        { "a(bc)*",   "adb",    "f" },
        { "a[bc]*",   "",       "f" },
        { "a[bc]*",   "ad",     "f" },
        { "a[bc]*",   "abd",    "f" },
        { "a[bc]*",   "acd",    "f" },

        // +
        // SQL2003 Part 2 Section 8.6 General Rule 7.c
        { "a+b",      "ab",     "t" },
        { "a+b",      "aab",    "t" },
        { "ab+",      "ab",     "t" },
        { "ab+",      "abb",    "t" },
        { "a(bc)+",   "abc",    "t" },
        { "a(bc)+",   "abcbc",  "t" },
        { "a[bc]+",   "ab",     "t" },
        { "a[bc]+",   "abb",    "t" },
        { "a[bc]+",   "ac",     "t" },
        { "a[bc]+",   "acc",    "t" },
        { "a[bc]+",   "abc",    "t" },
        { "a[bc]+",   "abccb",  "t" },

        { "a+b",      "",       "f" },
        { "a+b",      "a",      "f" },
        { "a+b",      "b",      "f" },
        { "a+b",      "ac",     "f" },
        { "ab+",      "",       "f" },
        { "ab+",      "a",      "f" },
        { "ab+",      "b",      "f" },
        { "ab+",      "ac",     "f" },
        { "a(bc)+",   "",       "f" },
        { "a(bc)+",   "a",      "f" },
        { "a(bc)+",   "ad",     "f" },
        { "a(bc)+",   "abd",    "f" },
        { "a(bc)+",   "adb",    "f" },
        { "a[bc]+",   "",       "f" },
        { "a[bc]+",   "a",      "f" },
        { "a[bc]+",   "ad",     "f" },
        { "a[bc]+",   "abd",    "f" },
        { "a[bc]+",   "acd",    "f" },

        // General Rule 7.d is above with GR6

        // SQL2003 Part 2 Section 8.6 General Rule 7.e
        { "a",         "a",     "t" },
        { "a",         "",      "f" },

        // %
        // SQL2003 Part 2 Section 8.6 General Rule 7.f
        { "%",        "",       "t" },
        { "%",        "a",      "t" },
        { "%",        "abc",    "t" },
        { "%b",       "ab",     "t" },
        { "a%",       "ab",     "t" },
        { "ab%",      "abc",    "t" },
        { "a%c",      "abc",    "t" },
        { "%bc",      "abc",    "t" },
        { "a%",       "abc",    "t" },
        { "%b%",      "abc",    "t" },
        { "%c",       "abc",    "t" },
        { "%abc",     "abc",    "t" },
        { "abc%",     "abc",    "t" },

        { "%b",       "a",      "f" },
        { "a%",       "b",      "f" },
        { "ab%",      "ac",     "f" },
        { "a%c",      "ab",     "f" },
        { "%bc",      "ab",     "f" },
        { "%b%",      "aBc",    "f" },
        { "%c",       "ab",     "f" },
        { "%abc",     "ac",     "f" },
        { "%abc",     "bc",     "f" },
        { "%abc",     "ab",     "f" },
        { "abc%",     "ab",     "f" },
        { "abc%",     "ac",     "f" },
        { "abc%",     "bc",     "f" },

        // ?
        // SQL2003 Part 2 Section 8.6 General Rule 7.g
        { "a?b",      "b",      "t" },
        { "a?b",      "ab",     "t" },
        { "ab?",      "a",      "t" },
        { "ab?",      "ab",     "t" },
        { "a(bc)?",   "a",      "t" },
        { "a(bc)?",   "abc",    "t" },
        { "a[bc]?",   "a",      "t" },
        { "a[bc]?",   "ab",     "t" },
        { "a[bc]?",   "ac",     "t" },

        { "a?b",      "",       "f" },
        { "a?b",      "a",      "f" },
        { "a?b",      "ac",     "f" },
        { "a?b",      "aab",    "f" },
        { "ab?",      "abb",    "f" },
        { "ab?",      "b",      "f" },
        { "ab?",      "ac",     "f" },
        { "a(bc)?",   "",       "f" },
        { "a(bc)?",   "abcbc",  "f" },
        { "a(bc)?",   "ad",     "f" },
        { "a(bc)?",   "abd",    "f" },
        { "a(bc)?",   "adb",    "f" },
        { "a[bc]?",   "",       "f" },
        { "a[bc]?",   "ad",     "f" },
        { "a[bc]?",   "abd",    "f" },
        { "a[bc]?",   "acd",    "f" },
        { "a[bc]?",   "abb",    "f" },
        { "a[bc]?",   "abc",    "f" },
        { "a[bc]?",   "abc",    "f" },
        { "a[bc]?",   "acc",    "f" },
        { "a[bc]?",   "abbb",   "f" },
        { "a[bc]?",   "accc",   "f" },

        // SQL2003 Part 2 Section 8.6 General Rule 7.h
        // also mixed with other tests
        { "(a)",      "a",      "t" },
        { "(ab)",     "ab",     "t" },
        { "(a)(b)",   "ab",     "t" },
        { "a(b)(c)d", "abcd",   "t" },
        { "(a(b))",   "ab",     "t" },

        { "(a)",      "",       "f" },
        { "(a)",      "b",      "f" },
        { "(ab)",     "a",      "f" },
        { "(ab)",     "b",      "f" },
        { "(a)(b)",   "a",      "f" },
        { "(a)(b)",   "b",      "f" },
        { "(a)(b)",   "abc",    "f" },
        { "a(b)(c)d", "abc",    "f" },
        { "a(b)(c)d", "bcd",    "f" },
        { "(a(b))",   "abc",    "f" },

        // _
        // SQL2003 Part 2 Section 8.6 General Rule 7.i
        { "_",        "a",      "t" },
        { "a",        "a",      "t" },
        { "abc",      "abc",    "t" },
        { "_bc",      "abc",    "t" },
        { "a_c",      "abc",    "t" },
        { "ab_",      "abc",    "t" },
        { "a__",      "abc",    "t" },
        { "_b_",      "abc",    "t" },
        { "__c",      "abc",    "t" },

        { "_",        "",       "f" },
        { "a",        "",       "f" },
        { "a",        "b",      "f" },
        { "b",        "ab",     "f" },
        { "a",        "ab",     "f" },
        { "__",       "a",      "f" },
        { "abc",      "Abc",    "f" },
        { "abc",      "aBc",    "f" },
        { "abc",      "abC",    "f" },
        { "_bc",      "aBc",    "f" },
        { "_bc",      "abC",    "f" },
        { "a_c",      "Abc",    "f" },
        { "ab_",      "aBc",    "f" },
        { "a__",      "Abc",    "f" },
        { "_b_",      "aBc",    "f" },
        { "__c",      "abC",    "f" },

        // [a], [ab], [a-c]
        // SQL2003 Part 2 Section 8.6 General Rule 7.j
        // SQL2003 Part 2 Section 8.6 General Rule 5.a & 5.b
        // (General Rule 5b is tested throughout below)
        { "[a]",       "a",     "t" },
        { "[ab]",      "a",     "t" },
        { "[ab]",      "b",     "t" },
        { "[a-c]",     "a",     "t" },
        { "[a-c]",     "b",     "t" },
        { "[a-c]",     "c",     "t" },

        { "[a]",       "",      "f" },
        { "[a]",       "b",     "f" },
        { "[a]",       "ab",    "f" },
        { "[ab]",      "",      "f" },
        { "[ab]",      "c",     "f" },
        { "[ab]",      "ab",    "f" },
        { "[a-c]",     "",      "f" },
        { "[a-c]",     "Z",     "f" },
        { "[a-c]",     "d",     "f" },

        // [^a], [^ab], [^a-c]
        // SQL2003 Part 2 Section 8.6 General Rule 7.k
        // SQL2003 Part 2 Section 8.6 General Rule 5.a & 5.b
        { "[^a]",      "b",     "t" },
        { "[^ab]",     "c",     "t" },
        { "[^a-c]",    "d",     "t" },

        { "[^a]",      "",      "f" },
        { "[^a]",      "a",     "f" },
        { "[^a]",      "ab",    "f" },
        { "[^ab]",     "",      "f" },
        { "[^ab]",     "a",     "f" },
        { "[^ab]",     "b",     "f" },
        { "[^ab]",     "ab",    "f" },
        { "[^a-c]",    "",      "f" },
        { "[^a-c]",    "a",     "f" },
        { "[^a-c]",    "b",     "f" },
        { "[^a-c]",    "c",     "f" },
        { "[^a-c]",    "ab",    "f" },

        // [a^b], [a-c^d-f]
        // SQL2003 Part 2 Section 8.6 General Rule 7.l (7L)
        // boost regex does not support this
        // SqlSimilarPrep does not currently have a workaround.
        // TODO: Add a workaround in SqlSimilarPrep to allow this to work
#if 0
        { "[a^b]",     "ac",    "t" },
        { "[a^b]",     "aa",    "t" },
        { "[a-c^d-f]", "ad",    "t" },
        { "[a-c^d-f]", "cf",    "t" },

        { "[a^b]",     "",      "f" },
        { "[a^b]",     "a",     "f" },
        { "[a^b]",     "b",     "f" },
        { "[a^b]",     "bb",    "f" },
        { "[a^b]",     "ab",    "f" },
        { "[a^b]",     "acd",   "f" },
        { "[a-c^d-f]", "",      "f" },
        { "[a-c^d-f]", "aa",    "f" },
        { "[a-c^d-f]", "ag",    "f" },
        { "[a-c^d-f]", "ca",    "f" },
        { "[a-c^d-f]", "cg",    "f" },
        { "[a-c^d-f]", "ad",    "f" },
        { "[a-c^d-f]", "af",    "f" },
        { "[a-c^d-f]", "aaa",   "f" },
#endif

        // SQL2003 Part 2 Section 8.6 General Rule 7.m
        { "[[:alpha:]]",  "a",  "t" },
        { "[[:ALPHA:]]",  "a",  "t" },
        { "[[:ALPHA:]]",  "A",  "t" },
        { "[^[:alpha:]]", "1",  "t" },
        { "[^[:ALPHA:]]", "1",  "t" },

        { "[[:ALPHA:]]",  "",   "f" },
        { "[[:ALPHA:]]",  " ",  "f" },
        { "[[:ALPHA:]]",  "\t", "f" },
        { "[[:ALPHA:]]",  "\n", "f" },
        { "[[:ALPHA:]]",  "1",  "f" },
        { "[[:ALPHA:]]",  "@",  "f" },
        { "[[:ALPHA:]]",  "a1", "f" },
        { "[[:ALPHA:]]",  "aa", "f" },
        { "[^[:ALPHA:]]", "a",  "f" },
        { "[^[:ALPHA:]]", "A",  "f" },

        // SQL2003 Part 2 Section 8.6 General Rule 7.n
        { "[[:upper:]]",  "A",  "t" },
        { "[[:UPPER:]]",  "A",  "t" },
        { "[^[:upper:]]", "1",  "t" },
        { "[^[:UPPER:]]", "1",  "t" },
        { "[^[:UPPER:]]", "a",  "t" },

        { "[[:UPPER:]]",  "",   "f" },
        { "[[:UPPER:]]",  " ",  "f" },
        { "[[:UPPER:]]",  "\t", "f" },
        { "[[:UPPER:]]",  "\n", "f" },
        { "[[:UPPER:]]",  "1",  "f" },
        { "[[:UPPER:]]",  "@",  "f" },
        { "[[:UPPER:]]",  "a",  "f" },
        { "[[:UPPER:]]",  "AA", "f" },
        { "[^[:UPPER:]]", "A",  "f" },

        // SQL2003 Part 2 Section 8.6 General Rule 7.o
        { "[[:lower:]]",  "a",  "t" },
        { "[[:LOWER:]]",  "a",  "t" },
        { "[^[:lower:]]", "1",  "t" },
        { "[^[:LOWER:]]", "1",  "t" },
        { "[^[:LOWER:]]", "A",  "t" },

        { "[[:LOWER:]]",  "",   "f" },
        { "[[:LOWER:]]",  " ",  "f" },
        { "[[:LOWER:]]",  "\t", "f" },
        { "[[:LOWER:]]",  "\n", "f" },
        { "[[:LOWER:]]",  "1",  "f" },
        { "[[:LOWER:]]",  "@",  "f" },
        { "[[:LOWER:]]",  "A",  "f" },
        { "[[:LOWER:]]",  "aa", "f" },
        { "[^[:LOWER:]]", "a",  "f" },

        // SQL2003 Part 2 Section 8.6 General Rule 7.p
        { "[[:digit:]]",  "1",  "t" },
        { "[[:DIGIT:]]",  "1",  "t" },
        { "[^[:digit:]]", "a",  "t" },
        { "[^[:DIGIT:]]", "a",  "t" },
        { "[^[:DIGIT:]]", "a",  "t" },

        { "[[:DIGIT:]]",  "",   "f" },
        { "[[:DIGIT:]]",  " ",  "f" },
        { "[[:DIGIT:]]",  "\t", "f" },
        { "[[:DIGIT:]]",  "\n", "f" },
        { "[[:DIGIT:]]",  "a",  "f" },
        { "[[:DIGIT:]]",  "@",  "f" },

        // SQL2003 Part 2 Section 8.6 General Rule 7.q
        { "[[:space:]]",  " ",  "t" },
        { "[[:SPACE:]]",  " ",  "t" },
        { "[^[:space:]]", "a",  "t" },
        { "[^[:SPACE:]]", "a",  "t" },
        { "[^[:SPACE:]]", "\t", "t" },
        { "[^[:SPACE:]]", "\n", "t" },

        { "[[:SPACE:]]",  "",   "f" },
        { "[^[:SPACE:]]", " ",  "f" },
        { "[^[:SPACE:]]", "  ", "f" },
        { "[[:SPACE:]]",  "\t", "f" },
        { "[[:SPACE:]]",  "\n", "f" },
        { "[[:SPACE:]]",  "a",  "f" },
        { "[[:SPACE:]]",  "@",  "f" },

        // SQL2003 Part 2 Section 8.6 General Rule 7.r
        { "[[:whitespace:]]",  " ",  "t" },
        { "[[:WHITESPACE:]]",  " ",  "t" },
        { "[[:WHITESPACE:]]",  "\t",  "t" },
        { "[[:WHITESPACE:]]",  "\n",  "t" },
        { "[[:WHITESPACE:]]",  "\v",  "t" },
        { "[[:WHITESPACE:]]",  "\f",  "t" },
        { "[[:WHITESPACE:]]",  "\r",  "t" },
        { "[[:WHITESPACE:]]",  "\x20",  "t" },
        { "[[:WHITESPACE:]]",  "\xa0",  "t" },
        { "[[:WHITESPACE:]]",  "\x09",  "t" },
        { "[[:WHITESPACE:]]",  "\x0a",  "t" },
        { "[[:WHITESPACE:]]",  "\x0b",  "t" },
        { "[[:WHITESPACE:]]",  "\x0c",  "t" },
        { "[[:WHITESPACE:]]",  "\x0d",  "t" },
        { "[[:WHITESPACE:]]",  "\x85",  "t" },
        { "[^[:whitespace:]]", "a",  "t" },
        { "[^[:WHITESPACE:]]", "a",  "t" },

        { "[^[:WHITESPACE:]]", "\t", "f" },
        { "[^[:WHITESPACE:]]", "\n", "f" },
        { "[[:WHITESPACE:]]",  "",   "f" },
        { "[^[:WHITESPACE:]]", " ",  "f" },
        { "[^[:WHITESPACE:]]", "  ", "f" },
        { "[[:WHITESPACE:]]",  "a",  "f" },
        { "[[:WHITESPACE:]]",  "@",  "f" },

        // SQL2003 Part 2 Section 8.6 General Rule 7.s
        { "[[:alnum:]]",  "a",  "t" },
        { "[[:ALNUM:]]",  "a",  "t" },
        { "[[:ALNUM:]]",  "1",  "t" },
        { "[[:ALNUM:]]",  "A",  "t" },
        { "[^[:alnum:]]", "!",  "t" },
        { "[^[:ALNUM:]]", "!",  "t" },
        { "[^[:ALNUM:]]", " ",  "t" },
        { "[^[:ALNUM:]]", "\t", "t" },
        { "[^[:ALNUM:]]", "\n", "t" },

        { "[[:ALNUM:]]",  "",   "f" },
        { "[[:ALNUM:]]",  " ",  "f" },
        { "[[:ALNUM:]]",  "\t", "f" },
        { "[[:ALNUM:]]",  "\n", "f" },
        { "[^[:ALNUM:]]", "1",  "f" },
        { "[^[:ALNUM:]]", "a",  "f" },
        { "[^[:ALNUM:]]", "A",  "f" },
        { "[[:ALNUM:]]",  "aa", "f" },

        // SQL2003 Part 2 Section 8.6 General Rule 7.t
        // TODO: Understand and implement 7.t. (Confused.)
#if 0
        { "||",       "a",      "t" },
        { "||",       "aa",     "f" },
#endif

        // SQL2003 Part 2 Section 8.6 General Rule 7.u
        { "",         "",       "t" },
        { "",         "a",      "f" },

        // search for characters special to regex, but not to SQL
        { "\\",       "\\",     "t" },
        { "\\",       "a",      "f" },
        { "$",        "$",      "t" },
        { "a$c",      "a$c",    "t" },
        { "a$c",      "abc",    "f" },
        { ".",        ".",      "t" },
        { ".",        "a",      "f" },

        { "X",  "X",  "X" }  // end sentinel
    };
    string expPat;
    for (i = 0; *test[i][0] != 'X'; i++) {
        BOOST_MESSAGE(
            " ===== Ascii Similar " << i
            << " " << test[i][0] << " "
            << test[i][1] << " " << test[i][2]);
        try {
            SqlSimilarPrep<1, 1>(
                test[i][0],
                strlen(test[i][0]),
                0, 0,   // no escape
                expPat);

            boost::regex exp(expPat);
            result = SqlRegExp<1, 1>(
                test[i][1],
                strlen(test[i][1]),
                strlen(test[i][0]),
                exp);
        } catch (char const * const ptr) {
            // unexpected exception
            BOOST_MESSAGE("unexpected SQL exception: " << ptr);
            BOOST_CHECK(0);
        } catch (boost::bad_expression badexp) {
            // regex format problem
            BOOST_MESSAGE(
                "unexpected regex exception: "
                << badexp.what());
            BOOST_CHECK(0);
        } catch (...) {
            // unexpected exception
            BOOST_MESSAGE("unexpected unknown exception");
            BOOST_CHECK(0);
        }

        if (*(test[i][2]) == 't') {
            if (!result) {
                BOOST_MESSAGE(
                    "|" << test[i][1]
                    << "| |" << test[i][0] << "| expPat=|"
                    << expPat << "|");
            }
            BOOST_CHECK(result);
        } else {
            if (result) {
                BOOST_MESSAGE(
                    "|" << test[i][1]
                    << "| |" << test[i][0] << "| expPat=|"
                    << expPat << "|");
            }
            BOOST_CHECK(!result);
        }
    }
}

void
SqlRegExpTest::testSqlRegExpSimilarAsciiEscape()
{
    bool result = false;
    int i;

    const char* test[][4] = {
        // pattern, matchValue, escape

        // define a new escape
        { "_",       "a",       "#", "t" },
        { "#_",      "_",       "#", "t" },
        { "#_bc",    "_bc",     "#", "t" },
        { "a#_c",    "a_c",     "#", "t" },
        { "ab#_",    "ab_",     "#", "t" },
        { "#%",      "%",       "#", "t" },
        { "#%bc",    "%bc",     "#", "t" },
        { "a#%c",    "a%c",     "#", "t" },
        { "ab#%",    "ab%",     "#", "t" },
        { "%",       "a",       "#", "t" },
        { "#%",      "%",       "#", "t" },
        { "##",      "#",       "#", "t" },
        // try all special chars (both to SIMILAR & regex)
        {
            "#[#]#(#)#|#^#-#+#*#_#%#?#{#}$.\\",
            "[]()|^-+*_%?{}$.\\",  "#", "t"
        },
        {
            "#[#{#(#|#?#^#*#%#+#-#_#)#}#]$.\\",
            "[{(|?^*%+-_)}]$.\\",  "#", "t"
        },

        { "#%",      "a",       "#", "f" },
        { "##",      "a",       "#", "f" },
        { "#%",      "ab",      "#", "f" },
        { "#%",      "a",       "#", "f" },
        { "#%bc",    "abc",     "#", "f" },
        { "a#%c",    "abc",     "#", "f" },
        { "ab#%",    "abc",     "#", "f" },

        { "_",       "ab",      "#", "f" },
        { "#_",      "_a",      "#", "f" },
        { "#_",      "a_",      "#", "f" },
        { "#_",      "a",       "#", "f" },
        { "#_",      "__",      "#", "f" },
        { "#_",      "a",       "#", "f" },
        { "#_#_",    "a",       "#", "f" },
        { "#_#_",    "_",       "#", "f" },
        { "#_#_",    "_a",      "#", "f" },
        { "#_#_",    "a_",      "#", "f" },
        { "#_bc",    "abc",     "#", "f" },
        { "a#_c",    "abc",     "#", "f" },
        { "ab#_",    "abc",     "#", "f" },

        // define new escape that is special regexp char
        { "_",       "a",       "|", "t" },
        { "|_",      "_",       "|", "t" },
        { "|_bc",    "_bc",     "|", "t" },
        { "a|_c",    "a_c",     "|", "t" },
        { "ab|_",    "ab_",     "|", "t" },
        { "||",      "|",       "|", "t" },
        { "((",      "(",       "(", "t" },

        { "|%",      "%",       "|", "t" },
        { "|%bc",    "%bc",     "|", "t" },
        { "a|%c",    "a%c",     "|", "t" },
        { "ab|%",    "ab%",     "|", "t" },
        { "%",       "a",       "|", "t" },
        { "|%",      "%",       "|", "t" },

        // try a other special chars as escape
        {
            "[[[][([)[|[^[-[+[*[_[%[?[{[}$.\\",
            "[]()|^-+*_%?{}$.\\", "[", "t"
        },
        {
            "[[[{[([|[?[^[*[%[+[-[_[)[}[]$.\\",
            "[{(|?^*%+-_)}]$.\\", "[", "t"
        },
        {
            "][]]](])]|]^]-]+]*]_]%]?]{]}$.\\",
            "[]()|^-+*_%?{}$.\\", "]", "t"
        },
        {
            ".[.].(.).|.^.-.+.*._.%.?.{.}$\\",
            "[]()|^-+*_%?{}$\\", ".", "t"
        },
        {
            "*[*]*(*)*|*^*-*+***_*%*?*{*}$.\\",
          "[]()|^-+*_%?{}$.\\", "*", "t"
        },
        {
            "_[_]_(_)_|_^_-_+_*___%_?_{_}$.\\",
            "[]()|^-+*_%?{}$.\\", "_", "t"
        },
        {
            "%[%]%(%)%|%^%-%+%*%_%%%?%{%}$.\\",
            "[]()|^-+*_%?{}$.\\", "%", "t"
        },

        { "_",       "ab",      "|", "f" },
        { "|_",      "_a",      "|", "f" },
        { "|_",      "a_",      "|", "f" },
        { "|_",      "a",       "|", "f" },
        { "|%",      "a",       "|", "f" },
        { "|%",      "ab",      "|", "f" },
        { "||",      "a",       "|", "f" },
        { "((",      "a",       "(", "f" },

        { "X",       "X",       "X", "X" }  // end sentinel
    };
    string expPat;
    for (i = 0; *test[i][0] != 'X'; i++) {
        BOOST_MESSAGE(
            " ========== escape " << i << " " <<test[i][0]
            << test[i][1] << " " << test[i][2] << " "
            << test[i][3]);
        try {
            SqlSimilarPrep<1, 1>(
                test[i][0],
                strlen(test[i][0]),
                test[i][2],
                strlen(test[i][2]),
                expPat);
            boost::regex exp(expPat);
            result = SqlRegExp<1, 1>(
                test[i][1],
                strlen(test[i][1]),
                strlen(test[i][0]),
                exp);
        } catch (char const * const ptr) {
            // unexpected exception
            BOOST_MESSAGE("unexpected SQL exception: " << ptr);
            BOOST_CHECK(0);
        } catch (boost::bad_expression badexp) {
            // regex format problem
            BOOST_MESSAGE(
                "unexpected regex exception: " << badexp.what());
            BOOST_CHECK(0);
        } catch (...) {
            // unexpected exception
            BOOST_MESSAGE("unexpected unknown exception");
            BOOST_CHECK(0);
        }

        if (*(test[i][3]) == 't') {
            if (!result) {
                BOOST_MESSAGE(
                    "|" << test[i][1]
                    << "| |" << test[i][0] << "| expPat=|"
                    << expPat << "|");
            }
            BOOST_CHECK(result);
        } else {
            if (result) {
                BOOST_MESSAGE(
                    "|" << test[i][1]
                    << "| |" << test[i][0] << "| expPat=|"
                    << expPat << "|");
            }
            BOOST_CHECK(!result);
        }
    }
}

void
SqlRegExpTest::testSqlRegExpSimilarAsciiException()
{
    bool caught = false;
    bool result = false;
    int i;

    const char* test[][4] = {
        // pattern, matchValue, escape, exception
        { "[[:ALPHA:]]", "a",   ":",     "2200B" },
        { "[[:alpha:]]", "a",   ":",     "2200B" },

        { "a",    "a",   "ab",    "22019" },
        { "a",    "a",   "\\\\",  "22019" },

        // escape char at end of string
        { "=",    "a",   "=",     "2201B" },
        // escaping a non-special char
        { "=a",   "a",   "=",     "2201B" },
        // invalid regular character set name
        { "[[:foo:]]", "a",   "=",     "2201B" },
        // mixed case regular character set name
        // (code allows lower case, outside of standard)
        { "[[:Alnum:]]", "a",   "=",     "2201B" },
        // sql-only special character in character set
        { "[_]",  "a",   "=",     "2201B" },
        { "[a_]", "a",   "=",     "2201B" },
        { "[%]",  "a",   "=",     "2201B" },
        { "[a%]", "a",   "=",     "2201B" },
        // regex & sql special character in character set
        { "[[]",  "a",   "=",     "2201B" }, // also opening w/o close
        { "[]]",  "a",   "=",     "2201B" }, // also close w/o open
        { "[(]",  "a",   "=",     "2201B" },
        { "[)]",  "a",   "=",     "2201B" },
        { "[|]",  "a",   "=",     "2201B" },
        { "[^]",  "a",   "=",     "regex" }, // thrown by regex
        // TODO: ? Could make this work, but seems at vanishing point of
        // utility. BNF says this is not legal.
        //{ "[-]",  "a",   "=",     "2201B" }, // technically should be caught
        { "[+]",  "a",   "=",     "2201B" },
        { "[*]",  "a",   "=",     "2201B" },
        { "[_]",  "a",   "=",     "2201B" },
        { "[?]",  "a",   "=",     "2201B" },
        { "[{]",  "a",   "=",     "2201B" },
        { "[}]",  "a",   "=",     "2201B" },

        { "[a]",  "a",   "[",    "2200C" },
        { "[a]",  "a",   "]",    "2200C" },
        { "(a)",  "a",   "(",    "2200C" },
        { "(a)",  "a",   ")",    "2200C" },
        { "a|b",  "a",   "|",    "2200C" },
        { "[^a]", "a",   "^",    "2200C" },
        { "[a-b]", "a",  "-",    "2200C" },
        { "(a)+", "a",   "+",    "2200C" },
        { "(a)*", "a",   "*",    "2200C" },
        { "a_",   "a",   "_",    "2200C" },
        { "a%",   "a",   "%",    "2200C" },

        { "X",    "X",   "X",     "X" }  // end sentinel
    };
    string expPat;
    for (i = 0; *test[i][0] != 'X'; i++) {
        BOOST_MESSAGE(" ===== exception " << i << " " <<test[i][0]);
        caught = false;
        try {
            SqlSimilarPrep<1, 1>(
                test[i][0],
                strlen(test[i][0]),
                test[i][2],
                strlen(test[i][2]),
                expPat);
            boost::regex exp(expPat);
            result = SqlRegExp<1, 1>(
                test[i][1],
                strlen(test[i][1]),
                strlen(test[i][0]),
                exp);
        } catch (SqlStateInfo const &info) {
            const char *ex = info.str().c_str();
            caught = true;
            if (strcmp(ex, test[i][3])) {
                BOOST_MESSAGE(
                    test[i][0] << " " << test[i][1]
                    << " " << test[i][2] << " expected: |"
                    << test[i][3] << "| got: |" << ex << "|");
                BOOST_CHECK(0);
            }
        } catch (boost::bad_expression badexp) {
            // regex format problem
            BOOST_MESSAGE("got boost exception " << test[i][3]);
            if (!strcmp("regex", test[i][3])) {
                BOOST_MESSAGE("setting caught to true");
                caught = true;
            } else {
                BOOST_MESSAGE(
                    "unexpected regex exception: " << badexp.what());
                BOOST_CHECK(0);
            }
        } catch (...) {
            // unexpected exception
            BOOST_MESSAGE("unexpected unknown exception");
            BOOST_CHECK(0);
        }

        if (!caught) {
            BOOST_CHECK(0);
        }
    }
}

FENNEL_UNIT_TEST_SUITE(SqlRegExpTest);

// End SqlRegExpTest.cpp


text:
/* ---------------------------------------------------------------------
 *
 * Copyright (C) 1999 - 2021 by the deal.II authors
 *
 * This file is part of the deal.II library.
 *
 * The deal.II library is free software; you can use it, redistribute
 * it, and/or modify it under the terms of the GNU Lesser General
 * Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * The full text of the license can be found in the file LICENSE.md at
 * the top level directory of deal.II.
 *
 * ---------------------------------------------------------------------
 *
 * Author: Wolfgang Bangerth, University of Heidelberg, 1999
 */

// @sect3{Include files}

// 前面几个（很多）include文件已经在前面的例子中使用过了，所以我们在这里不再解释它们的含义。

#include <deal.II/grid/tria.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/function.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/sparse_matrix.h>
#include <deal.II/lac/dynamic_sparsity_pattern.h>
#include <deal.II/lac/solver_cg.h>
#include <deal.II/lac/precondition.h>

#include <deal.II/numerics/data_out.h>
#include <fstream>
#include <iostream>

// 这是新的，但是：在前面的例子中，我们从线性求解器得到了一些不需要的输出。如果我们想抑制它，我们必须包括这个文件，并在程序的某个地方添加一行字（见下面的main()函数）。

#include <deal.II/base/logstream.h>

// 最后一步，和以前的程序一样，是将所有deal.II的类和函数名导入全局命名空间中。

using namespace dealii;
// @sect3{The Step4 class template}

// 这又是前面例子中的 Step4 类。唯一不同的是，我们现在把它声明为一个带有模板参数的类，而模板参数当然是我们要解决拉普拉斯方程的空间维度。当然，几个成员变量也取决于这个维度，特别是Triangulation类，它必须分别表示四边形或六面体。除此以外，一切都和以前一样。

template <int dim>
class Step4
{
public:
  Step4();
  void run();

private:
  void make_grid();
  void setup_system();
  void assemble_system();
  void solve();
  void output_results() const;

  Triangulation<dim> triangulation;
  FE_Q<dim>          fe;
  DoFHandler<dim>    dof_handler;

  SparsityPattern      sparsity_pattern;
  SparseMatrix<double> system_matrix;

  Vector<double> solution;
  Vector<double> system_rhs;
};
// @sect3{Right hand side and boundary values}

// 在下文中，我们又声明了两个类，表示右手边和非均质的Dirichlet边界值。两者都是一个二维空间变量的函数，所以我们也将它们声明为模板。

// 这些类中的每一个都是从一个共同的、抽象的基类Function派生出来的，它声明了所有函数都必须遵循的共同接口。特别是，具体的类必须重载 value 函数，该函数接收二维空间中的一个点作为参数，并将该点的值作为 double 变量返回。

//  value 函数需要第二个参数，我们在这里将其命名为 component  : 这只适用于矢量值函数，你可能想访问点 p 处的矢量的某个分量。然而，我们的函数是标量的，所以我们不需要担心这个参数，在函数的实现中也不会使用它。在库的头文件中，Function基类对 value 函数的声明中，分量的默认值为0，所以我们在访问右侧的 value 函数时，只需要一个参数，即我们要评估函数的点。然后，对于标量函数，可以简单地省略分量的值。

// 函数对象在库中很多地方都有使用（例如，在 step-3 中我们使用了一个 Functions::ZeroFunction 实例作为 VectorTools::interpolate_boundary_values) 的参数，这是我们定义一个继承自Function的新类的第一个教程。由于我们只调用 Function::value(), ，我们可以只用一个普通的函数（这就是 step-5 中的做法），但由于这是一个教程，为了举例说明，我们继承了Function。

template <int dim>
class RightHandSide : public Function<dim>
{
public:
  virtual double value(const Point<dim> & p,
                       const unsigned int component = 0) const override;
};

template <int dim>
class BoundaryValues : public Function<dim>
{
public:
  virtual double value(const Point<dim> & p,
                       const unsigned int component = 0) const override;
};

// 如果你不熟悉上述函数声明中的关键字 "virtual "和 "override "是什么意思，你可能会想看看你最喜欢的C++书籍或在线教程，如http:www.cplusplus.com/doc/tutorial/polymorphism/ 。从本质上讲，这里发生的事情是Function<dim>是一个 "抽象 "基类，它声明了某种 "接口"--一组可以在这类对象上调用的函数。但它实际上并没有*实现*这些函数：它只是说 "Function对象是这样的"，但它实际上是什么样的函数，则留给实现了`value()`函数的派生类。

// 从另一个类中派生出一个类，通常称为 "is-a "关系函数。在这里，`RightHandSide`类 "是一个 "函数类，因为它实现了Function基类所描述的接口。("value() "函数的实际实现在下面的代码块中)。那么`virtual`关键字意味着 "是的，这里的函数可以被派生类覆盖"，而`override`关键字意味着 "是的，这实际上是一个我们知道已经被声明为基类一部分的函数"。覆盖 "关键字不是严格必要的，但它是防止打字错误的一个保险。如果我们把函数的名字或一个参数的类型弄错了，编译器会警告我们说："你说这个函数覆盖了基类中的一个函数，但实际上我不知道有任何这样的函数有这个名字和这些参数。"

// 但回到这里的具体案例。在本教程中，我们选择2D中的函数 $4(x^4+y^4)$ ，或者3D中的 $4(x^4+y^4+z^4)$ 作为右手边。我们可以用空间维度上的if语句来写这个区别，但这里有一个简单的方法，通过使用一个短循环，也允许我们在一维（或四维，如果你想这样做）中使用相同的函数。 幸运的是，编译器在编译时就知道循环的大小（记住，在你定义模板时，编译器不知道 dim 的值，但当它后来遇到语句或声明 RightHandSide@<2@> 时，它将采取模板，用2替换所有出现的dim，并编译出结果函数）。 换句话说，在编译这个函数的时候，主体将被执行的次数是已知的，编译器可以将循环所需的开销降到最低；结果将和我们马上使用上面的公式一样快。

// 最后要注意的是， Point@<dim@> 表示二维空间中的一个点，它的各个组成部分（即 $x$ 、 $y$ 、...坐标）可以像C和C++中一样用（）运算符访问（事实上，[]运算符也同样有效），索引从0开始。

template <int dim>
double RightHandSide<dim>::value(const Point<dim> &p,
                                 const unsigned int /*component*/) const
{
  double return_value = 0.0;
  for (unsigned int i = 0; i < dim; ++i)
    return_value += 4.0 * std::pow(p(i), 4.0);

  return return_value;
}

// 作为边界值，我们选择二维的 $x^2+y^2$ ，三维的 $x^2+y^2+z^2$ 。这恰好等于从原点到我们想评估函数的点的矢量的平方，而不考虑维度。所以这就是我们的返回值。

template <int dim>
double BoundaryValues<dim>::value(const Point<dim> &p,
                                  const unsigned int /*component*/) const
{
  return p.square();
}

//  @sect3{Implementation of the Step4 class}

// 接下来是利用上述函数的类模板的实现。和以前一样，我们将把所有东西写成模板，这些模板有一个形式参数 dim ，在我们定义模板函数时，我们假设这个参数是未知的。只有在以后，编译器才会发现 Step4@<2@> (in the main 函数的声明，实际上），并在编译整个类时将 dim 替换成2，这个过程被称为 "模板的实例化"。这样做的时候，它也会用 RightHandSide@<dim@> 的实例替换 RightHandSide@<2@> ，并从类模板中实例化后一个类。

// 事实上，编译器也会在 main() 中找到一个 Step4@<3@> 声明。这将导致它再次回到一般的 Step4@<dim@> 模板，替换所有出现的 dim ，这次是3，并第二次编译这个类。注意这两个实例  Step4@<2@>  和  Step4@<3@>  是完全独立的类；它们唯一的共同特征是它们都是从同一个通用模板中实例化出来的，但是它们不能相互转换，例如，它们没有共享代码（两个实例都是完全独立编译的）。

//  @sect4{Step4::Step4}

// 在这个介绍之后，这里是  Step4  类的构造函数。它指定了所需的有限元素的多项式程度，并将DoFHandler与三角形关联起来，就像在前面的例子程序中一样，  step-3  。

template <int dim>
Step4<dim>::Step4()
  : fe(1)
  , dof_handler(triangulation)
{}
// @sect4{Step4::make_grid}

// 网格的创建在本质上是与维度有关的东西。然而，只要领域在二维或三维中足够相似，库就可以为你抽象。在我们的例子中，我们想再次在二维的正方形 $[-1,1]\times [-1,1]$ 上求解，或者在三维的立方体 $[-1,1] \times [-1,1] \times [-1,1]$ 上求解；两者都可以被称为 GridGenerator::hyper_cube(), ，因此我们可以在任何维度上使用同一个函数。当然，在二维和三维中创建超立方体的函数有很大的不同，但这是你不需要关心的事情。让库来处理这些困难的事情。

template <int dim>
void Step4<dim>::make_grid()
{
  GridGenerator::hyper_cube(triangulation, -1, 1);
  triangulation.refine_global(4);

  std::cout << "   Number of active cells: " << triangulation.n_active_cells()
            << std::endl
            << "   Total number of cells: " << triangulation.n_cells()
            << std::endl;
}
// @sect4{Step4::setup_system}

// 这个函数看起来和前面的例子完全一样，尽管它执行的动作在细节上有很大的不同，如果 dim 刚好是3。从用户的角度来看，唯一显著的区别是所产生的单元格数量，在三个空间维度中比两个空间维度中要高得多

template <int dim>
void Step4<dim>::setup_system()
{
  dof_handler.distribute_dofs(fe);

  std::cout << "   Number of degrees of freedom: " << dof_handler.n_dofs()
            << std::endl;

  DynamicSparsityPattern dsp(dof_handler.n_dofs());
  DoFTools::make_sparsity_pattern(dof_handler, dsp);
  sparsity_pattern.copy_from(dsp);

  system_matrix.reinit(sparsity_pattern);

  solution.reinit(dof_handler.n_dofs());
  system_rhs.reinit(dof_handler.n_dofs());
}
// @sect4{Step4::assemble_system}

// 与前面的例子不同，我们现在想使用一个非恒定的右侧函数和非零边界值。这两个任务都是很容易实现的，只需在矩阵和右手边的组合中增加几行代码即可。

// 更有趣的是，我们将矩阵和右手边的向量维度独立组装起来的方式：与二维的情况根本没有区别。由于这个函数中使用的重要对象（正交公式、FEValues）也通过模板参数的方式依赖于维度，它们可以为这个函数所编译的维度正确设置一切。通过使用模板参数声明所有可能依赖于维度的类，库可以为你完成几乎所有的工作，你不需要关心大多数事情。

template <int dim>
void Step4<dim>::assemble_system()
{
  QGauss<dim> quadrature_formula(fe.degree + 1);

// 我们希望有一个非恒定的右手，所以我们使用上面声明的类的一个对象来生成必要的数据。由于这个右侧对象只在本函数中局部使用，所以我们在这里把它声明为一个局部变量。

  RightHandSide<dim> right_hand_side;

// 与之前的例子相比，为了评估非恒定右手函数，我们现在还需要我们目前所在单元上的正交点（之前，我们只需要FEValues对象中的形状函数的值和梯度，以及正交权重， FEValues::JxW() ）。我们可以通过给FEValues对象添加#update_quadrature_points标志来让它为我们做事。

  FEValues<dim> fe_values(fe,
                          quadrature_formula,
                          update_values | update_gradients |
                            update_quadrature_points | update_JxW_values);

// 然后我们再次定义与前面程序中相同的缩写。这个变量的值当然取决于我们现在使用的维度，但是FiniteElement类为你做了所有必要的工作，你不需要关心与维度有关的部分。

  const unsigned int dofs_per_cell = fe.n_dofs_per_cell();

  FullMatrix<double> cell_matrix(dofs_per_cell, dofs_per_cell);
  Vector<double>     cell_rhs(dofs_per_cell);

  std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);

// 接下来，我们又要在所有的单元格上进行循环，并汇集局部贡献。 请注意，一个单元在两个空间维度上是一个四边形，但在三维上是一个六面体。事实上， active_cell_iterator 的数据类型是不同的，这取决于我们所处的维度，但对外界来说，它们看起来是一样的，你可能永远不会看到区别。在任何情况下，真正的类型是通过使用`auto`来隐藏的。

  for (const auto &cell : dof_handler.active_cell_iterators())
    {
      fe_values.reinit(cell);
      cell_matrix = 0;
      cell_rhs    = 0;

// 现在我们要把本地矩阵和右手边组合起来。这个过程和前面的例子完全一样，但是现在我们重新调整循环的顺序（我们可以安全地这样做，因为它们是相互独立的），并尽可能地合并本地矩阵和本地向量的循环，使事情变得更快。

// 组装右手边与我们在 step-3 中的做法有唯一的区别：我们没有使用值为1的常数右手边，而是使用代表右手边的对象并在正交点对其进行评估。

      for (const unsigned int q_index : fe_values.quadrature_point_indices())
        for (const unsigned int i : fe_values.dof_indices())
          {
            for (const unsigned int j : fe_values.dof_indices())
              cell_matrix(i, j) +=
                (fe_values.shape_grad(i, q_index) * // grad phi_i(x_q)
                 fe_values.shape_grad(j, q_index) * // grad phi_j(x_q)
                 fe_values.JxW(q_index));           // dx

            const auto &x_q = fe_values.quadrature_point(q_index);
            cell_rhs(i) += (fe_values.shape_value(i, q_index) * // phi_i(x_q)
                            right_hand_side.value(x_q) *        // f(x_q)
                            fe_values.JxW(q_index));            // dx
          }

// 作为对这些循环的最后说明：当我们将局部贡献集合到 cell_matrix(i,j) 时，我们必须将形状函数 $i$ 和 $j$ 在点号q_index的梯度相乘并与标量权重JxW相乘。这就是实际发生的情况。  fe_values.shape_grad(i,q_index) 返回一个 dim 维向量，由 Tensor@<1,dim@> 对象表示，将其与 fe_values.shape_grad(j,q_index) 的结果相乘的运算器*确保两个向量的 dim 分量被适当收缩，结果是一个标量浮点数，然后与权重相乘。在内部，这个操作符*确保对向量的所有 dim 分量都能正确发生，无论 dim 是2、3还是其他空间维度；从用户的角度来看，这并不值得费心，然而，如果想独立编写代码维度，事情就会简单很多。

// 随着本地系统的组装，转移到全局矩阵和右手边的工作与之前完全一样，但在这里我们再次合并了一些循环以提高效率。

      cell->get_dof_indices(local_dof_indices);
      for (const unsigned int i : fe_values.dof_indices())
        {
          for (const unsigned int j : fe_values.dof_indices())
            system_matrix.add(local_dof_indices[i],
                              local_dof_indices[j],
                              cell_matrix(i, j));

          system_rhs(local_dof_indices[i]) += cell_rhs(i);
        }
    }

// 作为这个函数的最后一步，我们希望在这个例子中拥有非均质的边界值，与之前的例子不同。这是一个简单的任务，我们只需要用一个描述我们想使用的边界值的类的对象（即上面声明的 BoundaryValues 类）来替换那里使用的 Functions::ZeroFunction 。

// 函数 VectorTools::interpolate_boundary_values() 只对标有边界指标0的面起作用（因为我们在下面的第二个参数中说该函数应该对其起作用）。如果有的面的边界指标不是0，那么函数interpolate_boundary_values将对这些面不起作用。对于拉普拉斯方程来说，什么都不做相当于假设在边界的这些部分，零诺伊曼边界条件成立。

  std::map<types::global_dof_index, double> boundary_values;
  VectorTools::interpolate_boundary_values(dof_handler,
                                           0,
                                           BoundaryValues<dim>(),
                                           boundary_values);
  MatrixTools::apply_boundary_values(boundary_values,
                                     system_matrix,
                                     solution,
                                     system_rhs);
}
// @sect4{Step4::solve}

// 解决线性方程组是在大多数程序中看起来几乎相同的事情。特别是，它与维度无关，所以这个函数是从前面的例子中逐字复制的。

template <int dim>
void Step4<dim>::solve()
{
  SolverControl            solver_control(1000, 1e-12);
  SolverCG<Vector<double>> solver(solver_control);
  solver.solve(system_matrix, solution, system_rhs, PreconditionIdentity());

// 不过我们做了一个补充：由于我们抑制了线性求解器的输出，我们必须手工打印迭代次数。

  std::cout << "   " << solver_control.last_step()
            << " CG iterations needed to obtain convergence." << std::endl;
}
// @sect4{Step4::output_results}

// 这个函数也做了  step-3  中各自的工作。这里也没有改变维度的独立性。

// 由于程序将同时运行拉普拉斯求解器的2D和3D版本，我们使用文件名中的维度为每次运行生成不同的文件名（在一个更好的程序中，我们将检查 dim 是否可以有2或3以外的其他值，但为了简洁起见，我们在这里忽略了这一点）。

template <int dim>
void Step4<dim>::output_results() const
{
  DataOut<dim> data_out;

  data_out.attach_dof_handler(dof_handler);
  data_out.add_data_vector(solution, "solution");

  data_out.build_patches();

  std::ofstream output(dim == 2 ? "solution-2d.vtk" : "solution-3d.vtk");
  data_out.write_vtk(output);
}

//  @sect4{Step4::run}

// 这是一个对所有事情都有最高级别控制的函数。除了一行额外的输出外，它与前面的例子相同。

template <int dim>
void Step4<dim>::run()
{
  std::cout << "Solving problem in " << dim << " space dimensions."
            << std::endl;

  make_grid();
  setup_system();
  assemble_system();
  solve();
  output_results();
}
// @sect3{The main function}

// 这是主函数。它看起来也大多像 step-3 中的内容，但如果你看下面的代码，注意我们是如何首先创建一个 Step4@<2@> 类型的变量（迫使编译器用 dim replaced by 2 编译类模板）并运行一个2d模拟，然后我们用3d做整个事情。

// 在实践中，这可能不是你经常做的事情（你可能要么想解决一个2D的问题，要么想解决一个3D的问题，但不会同时解决这两个问题）。然而，它展示了一种机制，我们可以在一个地方简单地改变我们想要的维度，从而迫使编译器为我们要求的维度重新编译独立的类模板。这里的重点在于，我们只需要改变一个地方。这使得在计算速度较快的2D环境下调试程序变得非常简单，然后将一个地方切换到3，在3D环境下运行计算量大得多的程序，进行 "真实 "的计算。

// 这两个区块中的每一个都用大括号括起来，以确保 laplace_problem_2d 这个变量在我们继续为3D情况分配内存之前就已经超出了范围（并释放了它所持有的内存）。如果没有额外的大括号， laplace_problem_2d 变量只会在函数结束时被销毁，也就是在运行完3d问题后被销毁，而且会在3d运行时不必要地占用内存，而实际使用它。

int main()
{
  {
    Step4<2> laplace_problem_2d;
    laplace_problem_2d.run();
  }

  {
    Step4<3> laplace_problem_3d;
    laplace_problem_3d.run();
  }

  return 0;
}