text:
/**
 * @file io/cxx/ImageGifFile.cc
 * @date Fri Nov 23 16:53:00 2012 +0200
 * @author Laurent El Shafey <laurent.el-shafey@idiap.ch>
 * @author Manuel Gunther <siebenkopf@googlemail.com>
 *
 * @brief Implements an image format reader/writer using giflib.
 *
 * Copyright (C) 2011-2013 Idiap Research Institute, Martigny, Switzerland
 * Copyright (c) 2016, Regents of the University of Colorado on behalf of the University of Colorado Colorado Springs.
 */

#ifdef HAVE_GIFLIB

#include <boost/filesystem.hpp>
#include <boost/shared_array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <string>

#include <bob.io.image/gif.h>

extern "C" {
#include <gif_lib.h>

#if GIFLIB_MAJOR > 5 || GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 2 || GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 1 && GIFLIB_RELEASE >= 9
//see https://sourceforge.net/p/giflib/bugs/132/
//and https://sourceforge.net/p/giflib/bugs/142/
#include <quantize.h>
#endif

}

// QuantizeBuffer function definition that was inlined (only) in giflib 4.2
#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR < 5

#define ABS(x)    ((x) > 0 ? (x) : (-(x)))
#define COLOR_ARRAY_SIZE 32768
#define BITS_PER_PRIM_COLOR 5
#define MAX_PRIM_COLOR 0x1f

static int SortRGBAxis;

typedef struct QuantizedColorType {
  GifByteType RGB[3];
  GifByteType NewColorIndex;
  long Count;
  struct QuantizedColorType *Pnext;
} QuantizedColorType;

typedef struct NewColorMapType {
  GifByteType RGBMin[3], RGBWidth[3];
  unsigned int NumEntries; /* # of QuantizedColorType in linked list below */
  unsigned long Count; /* Total number of pixels in all the entries */
  QuantizedColorType *QuantizedColors;
} NewColorMapType;

// Routine called by qsort to compare two entries.
static int
SortCmpRtn(const void *Entry1, const void *Entry2)
{
  return (*((QuantizedColorType **) Entry1))->RGB[SortRGBAxis] -
    (*((QuantizedColorType **) Entry2))->RGB[SortRGBAxis];
}

// Routine to subdivide the RGB space recursively using median cut in each
// axes alternatingly until ColorMapSize different cubes exists.
// The biggest cube in one dimension is subdivide unless it has only one entry.
// Returns GIF_ERROR if failed, otherwise GIF_OK.
static int
SubdivColorMap(NewColorMapType * NewColorSubdiv,
    unsigned int ColorMapSize,
    unsigned int *NewColorMapSize) {
  int MaxSize;
  unsigned int i, j, Index = 0, NumEntries, MinColor, MaxColor;
  long Sum, Count;
  QuantizedColorType *QuantizedColor, **SortArray;
  while (ColorMapSize > *NewColorMapSize) {
    // Find candidate for subdivision:
    MaxSize = -1;
    for (i = 0; i < *NewColorMapSize; i++) {
      for (j = 0; j < 3; j++) {
        if ((((int)NewColorSubdiv[i].RGBWidth[j]) > MaxSize) &&
            (NewColorSubdiv[i].NumEntries > 1)) {
          MaxSize = NewColorSubdiv[i].RGBWidth[j];
          Index = i;
          SortRGBAxis = j;
        }
      }
    }
    if (MaxSize == -1)
      return GIF_OK;
    // Split the entry Index into two along the axis SortRGBAxis:
    // Sort all elements in that entry along the given axis and split at
    // the median.
    SortArray = (QuantizedColorType **)malloc(
        sizeof(QuantizedColorType *) *
        NewColorSubdiv[Index].NumEntries);
    if (SortArray == NULL)
      return GIF_ERROR;
    for (j = 0, QuantizedColor = NewColorSubdiv[Index].QuantizedColors;
        j < NewColorSubdiv[Index].NumEntries && QuantizedColor != NULL;
        j++, QuantizedColor = QuantizedColor->Pnext)
      SortArray[j] = QuantizedColor;
    qsort(SortArray, NewColorSubdiv[Index].NumEntries,
        sizeof(QuantizedColorType *), SortCmpRtn);
    // Relink the sorted list into one:
    for (j = 0; j < NewColorSubdiv[Index].NumEntries - 1; j++)
      SortArray[j]->Pnext = SortArray[j + 1];
    SortArray[NewColorSubdiv[Index].NumEntries - 1]->Pnext = NULL;
    NewColorSubdiv[Index].QuantizedColors = QuantizedColor = SortArray[0];
    free((char *)SortArray);
    // Now simply add the Counts until we have half of the Count:
    Sum = NewColorSubdiv[Index].Count / 2 - QuantizedColor->Count;
    NumEntries = 1;
    Count = QuantizedColor->Count;
    while (QuantizedColor->Pnext != NULL &&
        (Sum -= QuantizedColor->Pnext->Count) >= 0 &&
        QuantizedColor->Pnext->Pnext != NULL) {
      QuantizedColor = QuantizedColor->Pnext;
      NumEntries++;
      Count += QuantizedColor->Count;
    }
    // Save the values of the last color of the first half, and first
    // of the second half so we can update the Bounding Boxes later.
    // Also as the colors are quantized and the BBoxes are full 0..255,
    // they need to be rescaled.
    MaxColor = QuantizedColor->RGB[SortRGBAxis]; // Max. of first half
    // coverity[var_deref_op]
    MinColor = QuantizedColor->Pnext->RGB[SortRGBAxis]; // of second
    MaxColor <<= (8 - BITS_PER_PRIM_COLOR);
    MinColor <<= (8 - BITS_PER_PRIM_COLOR);
    // Partition right here:
    NewColorSubdiv[*NewColorMapSize].QuantizedColors =
      QuantizedColor->Pnext;
    QuantizedColor->Pnext = NULL;
    NewColorSubdiv[*NewColorMapSize].Count = Count;
    NewColorSubdiv[Index].Count -= Count;
    NewColorSubdiv[*NewColorMapSize].NumEntries =
      NewColorSubdiv[Index].NumEntries - NumEntries;
    NewColorSubdiv[Index].NumEntries = NumEntries;
    for (j = 0; j < 3; j++) {
      NewColorSubdiv[*NewColorMapSize].RGBMin[j] =
        NewColorSubdiv[Index].RGBMin[j];
      NewColorSubdiv[*NewColorMapSize].RGBWidth[j] =
        NewColorSubdiv[Index].RGBWidth[j];
    }
    NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] =
      NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] +
      NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] - MinColor;
    NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] = MinColor;
    NewColorSubdiv[Index].RGBWidth[SortRGBAxis] =
      MaxColor - NewColorSubdiv[Index].RGBMin[SortRGBAxis];
    (*NewColorMapSize)++;
  }
  return GIF_OK;
}

// Quantize high resolution image into lower one. Input image consists of a
// 2D array for each of the RGB colors with size Width by Height. There is no
// Color map for the input. Output is a quantized image with 2D array of
// indexes into the output color map.
// Note input image can be 24 bits at the most (8 for red/green/blue) and
// the output has 256 colors at the most (256 entries in the color map.).
// ColorMapSize specifies size of color map up to 256 and will be updated to
// real size before returning.
// Also non of the parameter are allocated by this routine.
// This function returns GIF_OK if succesfull, GIF_ERROR otherwise.
static int
QuantizeBuffer(unsigned int Width, unsigned int Height, int *ColorMapSize,
  GifByteType * RedInput, GifByteType * GreenInput, GifByteType * BlueInput,
  GifByteType * OutputBuffer, GifColorType * OutputColorMap)
{
  unsigned int Index, NumOfEntries;
  int i, j, MaxRGBError[3];
  unsigned int NewColorMapSize;
  long Red, Green, Blue;
  NewColorMapType NewColorSubdiv[256];
  QuantizedColorType *ColorArrayEntries, *QuantizedColor;
  ColorArrayEntries = (QuantizedColorType *)malloc(
      sizeof(QuantizedColorType) * COLOR_ARRAY_SIZE);
  if (ColorArrayEntries == NULL) {
    return GIF_ERROR;
  }
  for (i = 0; i < COLOR_ARRAY_SIZE; i++) {
    ColorArrayEntries[i].RGB[0] = i >> (2 * BITS_PER_PRIM_COLOR);
    ColorArrayEntries[i].RGB[1] = (i >> BITS_PER_PRIM_COLOR) &
      MAX_PRIM_COLOR;
    ColorArrayEntries[i].RGB[2] = i & MAX_PRIM_COLOR;
    ColorArrayEntries[i].Count = 0;
  }
  // Sample the colors and their distribution:
  for (i = 0; i < (int)(Width * Height); i++) {
    Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
        (2 * BITS_PER_PRIM_COLOR)) +
      ((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
       BITS_PER_PRIM_COLOR) +
      (BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR));
    ColorArrayEntries[Index].Count++;
  }
  // Put all the colors in the first entry of the color map, and call the
  // recursive subdivision process.
  for (i = 0; i < 256; i++) {
    NewColorSubdiv[i].QuantizedColors = NULL;
    NewColorSubdiv[i].Count = NewColorSubdiv[i].NumEntries = 0;
    for (j = 0; j < 3; j++) {
      NewColorSubdiv[i].RGBMin[j] = 0;
      NewColorSubdiv[i].RGBWidth[j] = 255;
    }
  }
  // Find the non empty entries in the color table and chain them:
  for (i = 0; i < COLOR_ARRAY_SIZE; i++)
    if (ColorArrayEntries[i].Count > 0)
      break;
  QuantizedColor = NewColorSubdiv[0].QuantizedColors = &ColorArrayEntries[i];
  NumOfEntries = 1;
  while (++i < COLOR_ARRAY_SIZE)
    if (ColorArrayEntries[i].Count > 0) {
      QuantizedColor->Pnext = &ColorArrayEntries[i];
      QuantizedColor = &ColorArrayEntries[i];
      NumOfEntries++;
    }
  QuantizedColor->Pnext = NULL;
  NewColorSubdiv[0].NumEntries = NumOfEntries; // Different sampled colors
  NewColorSubdiv[0].Count = ((long)Width) * Height; // Pixels
  NewColorMapSize = 1;
  if (SubdivColorMap(NewColorSubdiv, *ColorMapSize, &NewColorMapSize) !=
      GIF_OK) {
    free((char *)ColorArrayEntries);
    return GIF_ERROR;
  }
  if (NewColorMapSize < *ColorMapSize) {
    // And clear rest of color map:
    for (i = NewColorMapSize; i < *ColorMapSize; i++)
      OutputColorMap[i].Red = OutputColorMap[i].Green =
        OutputColorMap[i].Blue = 0;
  }
  // Average the colors in each entry to be the color to be used in the
  // output color map, and plug it into the output color map itself.
  for (i = 0; i < NewColorMapSize; i++) {
    if ((j = NewColorSubdiv[i].NumEntries) > 0) {
      QuantizedColor = NewColorSubdiv[i].QuantizedColors;
      Red = Green = Blue = 0;
      while (QuantizedColor) {
        QuantizedColor->NewColorIndex = i;
        Red += QuantizedColor->RGB[0];
        Green += QuantizedColor->RGB[1];
        Blue += QuantizedColor->RGB[2];
        QuantizedColor = QuantizedColor->Pnext;
      }
      OutputColorMap[i].Red = (Red << (8 - BITS_PER_PRIM_COLOR)) / j;
      OutputColorMap[i].Green = (Green << (8 - BITS_PER_PRIM_COLOR)) / j;
      OutputColorMap[i].Blue = (Blue << (8 - BITS_PER_PRIM_COLOR)) / j;
    } else
      fprintf(stderr,
          "\n: Null entry in quantized color map - that's weird.\n");
  }
  // Finally scan the input buffer again and put the mapped index in the
  // output buffer.
  MaxRGBError[0] = MaxRGBError[1] = MaxRGBError[2] = 0;
  for (i = 0; i < (int)(Width * Height); i++) {
    Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
        (2 * BITS_PER_PRIM_COLOR)) +
      ((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
       BITS_PER_PRIM_COLOR) +
      (BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR));
    Index = ColorArrayEntries[Index].NewColorIndex;
    OutputBuffer[i] = Index;
    if (MaxRGBError[0] < ABS(OutputColorMap[Index].Red - RedInput[i]))
      MaxRGBError[0] = ABS(OutputColorMap[Index].Red - RedInput[i]);
    if (MaxRGBError[1] < ABS(OutputColorMap[Index].Green - GreenInput[i]))
      MaxRGBError[1] = ABS(OutputColorMap[Index].Green - GreenInput[i]);
    if (MaxRGBError[2] < ABS(OutputColorMap[Index].Blue - BlueInput[i]))
      MaxRGBError[2] = ABS(OutputColorMap[Index].Blue - BlueInput[i]);
  }
  free((char *)ColorArrayEntries);
  *ColorMapSize = NewColorMapSize;
  return GIF_OK;
}

#undef ABS
#undef COLOR_ARRAY_SIZE
#undef BITS_PER_PRIM_COLOR
#undef MAX_PRIM_COLOR
#endif // End of ugly QuantizeBuffer definition for giflib 4.2

static void GifErrorHandler(const char* fname, int error) {
#if defined(GIF_LIB_VERSION) || (GIFLIB_MAJOR < 5)
  const char* error_string = "unknown error (giflib < 5)";
#else
  const char* error_string = GifErrorString(error);
#endif
  boost::format m("GIF: error in %s(): (%d) %s");
  m % fname % error;
  if (error_string) m % error_string;
  else m % "unknown error";
  throw std::runtime_error(m.str());
}

static int DGifDeleter (GifFileType* ptr) {
#if defined(GIF_LIB_VERSION) || (GIFLIB_MAJOR < 5) || (GIFLIB_MAJOR == 5) && (GIFLIB_MINOR < 1)
  return DGifCloseFile(ptr);
#else
  int error = GIF_OK;
  int retval = DGifCloseFile(ptr, &error);
  if (retval == GIF_ERROR) {
    //do not call GifErrorHandler here, or the interpreter will crash
    const char* error_string = GifErrorString(retval);
    boost::format m("In DGifCloseFile(): (%d) %s");
    m % error;
    if (error_string) m % error_string;
    else m % "unknown error";
    std::cerr << "ERROR: " << m.str() << std::endl;
  }
  return retval;
#endif
}

static boost::shared_ptr<GifFileType> make_dfile(const char *filename)
{
#if defined(GIF_LIB_VERSION) || (GIFLIB_MAJOR < 5)
  GifFileType* fp = DGifOpenFileName(filename);
  if (!fp) {
    boost::format m("cannot open file `%s'");
    m % filename;
    throw std::runtime_error(m.str());
  }
#else
  int error = GIF_OK;
  GifFileType* fp = DGifOpenFileName(filename, &error);
  if (!fp) GifErrorHandler("DGifOpenFileName", error);
#endif
  return boost::shared_ptr<GifFileType>(fp, DGifDeleter);
}

static int EGifDeleter (GifFileType* ptr) {
#if defined(GIF_LIB_VERSION) || (GIFLIB_MAJOR < 5) || (GIFLIB_MAJOR == 5) && (GIFLIB_MINOR < 1)
  return EGifCloseFile(ptr);
#else
  int error = GIF_OK;
  int retval = EGifCloseFile(ptr, &error);
  if (retval == GIF_ERROR) {
    //do not call GifErrorHandler here, or the interpreter will crash
    const char* error_string = GifErrorString(error);
    boost::format m("In EGifCloseFile(): (%d) %s");
    m % error;
    if (error_string) m % error_string;
    else m % "unknown error";
    std::cerr << "ERROR: " << m.str() << std::endl;
  }
  return retval;
#endif
}

static boost::shared_ptr<GifFileType> make_efile(const char *filename)
{
#if defined(GIF_LIB_VERSION) || (GIFLIB_MAJOR < 5)
  GifFileType* fp = EGifOpenFileName(filename, false);
  if (!fp) {
    boost::format m("cannot open file `%s'");
    m % filename;
    throw std::runtime_error(m.str());
  }
#else
  int error = GIF_OK;
  GifFileType* fp = EGifOpenFileName(filename, false, &error);
  if (!fp) GifErrorHandler("EGifOpenFileName", error);
#endif
  return boost::shared_ptr<GifFileType>(fp, EGifDeleter);
}

/**
 * LOADING
 */
static void im_peek(const std::string& path, bob::io::base::array::typeinfo& info)
{
  // 1. GIF file opening
  boost::shared_ptr<GifFileType> in_file = make_dfile(path.c_str());

  // 2. Set typeinfo variables
  info.dtype = bob::io::base::array::t_uint8;
  info.nd = 3;
  info.shape[0] = 3;
  info.shape[1] = in_file->SHeight;
  info.shape[2] = in_file->SWidth;
  info.update_strides();
}

static void im_load_color(boost::shared_ptr<GifFileType> in_file, bob::io::base::array::interface& b)
{
  const bob::io::base::array::typeinfo& info = b.type();
  const size_t height0 = info.shape[1];
  const size_t width0 = info.shape[2];
  const size_t frame_size = height0*width0;

  // The following piece of code is based on the giflib utility called gif2rgb
  // Allocate the screen as vector of column of rows. Note this
  // screen is device independent - it's the screen defined by the
  // GIF file parameters.
  std::vector<boost::shared_array<GifPixelType> > screen_buffer;
  // The second buffer is just used if the image has already been read
  boost::shared_array<GifPixelType> temp_buffer(new GifPixelType[in_file->SWidth]);

  // Size in bytes one row.
  int size = in_file->SWidth*sizeof(GifPixelType);
  // First row
  screen_buffer.push_back(boost::shared_array<GifPixelType>(new GifPixelType[in_file->SWidth]));

  // Set its color to BackGround
  for(int i=0; i<in_file->SWidth; ++i)
    screen_buffer[0][i] = in_file->SBackGroundColor;
  for(int i=1; i<in_file->SHeight; ++i) {
    // Allocate the other rows, and set their color to background too:
    screen_buffer.push_back(boost::shared_array<GifPixelType>(new GifPixelType[in_file->SWidth]));
    memcpy(screen_buffer[i].get(), screen_buffer[0].get(), size);
  }

  // Scan the content of the GIF file and load the image(s) in:
  GifRecordType record_type;
  GifByteType *extension;
  int InterlacedOffset[] = { 0, 4, 2, 1 }; // The way Interlaced image should.
  int InterlacedJumps[] = { 8, 8, 4, 2 }; // be read - offsets and jumps...
  int row, col, width, height, ext_code;
  bool terminated = false;
  bool image_found = false;
  do{
    int error = DGifGetRecordType(in_file.get(), &record_type);
    if(error == GIF_ERROR)
      GifErrorHandler("DGifGetRecordType", in_file->Error);
    switch(record_type) {
      case IMAGE_DESC_RECORD_TYPE:
        error = DGifGetImageDesc(in_file.get());
        if (error == GIF_ERROR) GifErrorHandler("DGifGetImageDesc", in_file->Error);
        row = in_file->Image.Top; // Image Position relative to Screen.
        col = in_file->Image.Left;
        width = in_file->Image.Width;
        height = in_file->Image.Height;
        if(in_file->Image.Left + in_file->Image.Width > in_file->SWidth ||
          in_file->Image.Top + in_file->Image.Height > in_file->SHeight)
        {
          throw std::runtime_error("GIF: the dimensions of image larger than the dimensions of the canvas.");
        }
        if(in_file->Image.Interlace) {
          // Need to perform 4 passes on the images:
          for(int i=0; i<4; ++i)
            for(int j=row+InterlacedOffset[i]; j<row+height; j+=InterlacedJumps[i]) {
              if (image_found)
                // image buffer already filled; read in into junk buffer
                error = DGifGetLine(in_file.get(), &temp_buffer[col], width);
              else
                // read into image buffer
                error = DGifGetLine(in_file.get(), &screen_buffer[j][col], width);
              if(error == GIF_ERROR) GifErrorHandler("DGifGetLine", in_file->Error);
            }
        }
        else {
          for(int i=0; i<height; ++i) {
            if (image_found)
              // image buffer already filled; read in into junk buffer
              error = DGifGetLine(in_file.get(), &temp_buffer[col], width);
            else
              // read into image buffer
              error = DGifGetLine(in_file.get(), &screen_buffer[row++][col], width);
            if(error == GIF_ERROR) GifErrorHandler("DGifGetLine", in_file->Error);
          }
        }
        image_found = true;
        break;
      case EXTENSION_RECORD_TYPE:
        // Skip any extension blocks in file:
        error = DGifGetExtension(in_file.get(), &ext_code, &extension);
        if (error == GIF_ERROR) GifErrorHandler("DGifGetExtension", in_file->Error);
        while(extension != NULL) {
          error = DGifGetExtensionNext(in_file.get(), &extension);
          if(error == GIF_ERROR) GifErrorHandler("DGifGetExtensionNext", in_file->Error);
        }
        break;
      case TERMINATE_RECORD_TYPE:
        terminated = true;
        break;
      default: // Should be trapped by DGifGetRecordType.
        break;
    }
  } while (!terminated);

  if (!image_found){
    throw std::runtime_error("GIF: image does not contain an image section");
  }

  // Lets dump it - set the global variables required and do it:
  ColorMapObject *ColorMap = (in_file->Image.ColorMap ? in_file->Image.ColorMap : in_file->SColorMap);
  if(ColorMap == 0)
    throw std::runtime_error("GIF: image does not have a colormap");

  // Put data into C-style buffer
  uint8_t *element_r = reinterpret_cast<uint8_t*>(b.ptr());
  uint8_t *element_g = element_r + frame_size;
  uint8_t *element_b = element_g + frame_size;
  GifRowType gif_row;
  GifColorType *ColorMapEntry;
  for(int i=0; i<in_file->SHeight; ++i) {
    gif_row = screen_buffer[i].get();
    for(int j=0; j<in_file->SWidth; ++j) {
      ColorMapEntry = &ColorMap->Colors[gif_row[j]];
      *element_r++ = ColorMapEntry->Red;
      *element_g++ = ColorMapEntry->Green;
      *element_b++ = ColorMapEntry->Blue;
    }
  }
}

static void im_load(const std::string& filename, bob::io::base::array::interface& b)
{
  // 1. GIF file opening
  boost::shared_ptr<GifFileType> in_file = make_dfile(filename.c_str());

  // 2. Read content
  const bob::io::base::array::typeinfo& info = b.type();
  if (info.dtype == bob::io::base::array::t_uint8) {
    if (info.nd == 3) im_load_color(in_file, b);
    else {
      boost::format m("GIF: cannot read object of type `%s' from file `%s'");
      m % info.str() % filename;
      throw std::runtime_error(m.str());
    }
  }
  else {
    boost::format m("GIF: cannot read object of type `%s' from file `%s'");
    m % info.str() % filename;
    throw std::runtime_error(m.str());
  }
}

/**
 * SAVING
 */
static void im_save_color(const bob::io::base::array::interface& b, boost::shared_ptr<GifFileType> out_file)
{
  const bob::io::base::array::typeinfo& info = b.type();
  const int height = info.shape[1];
  const int width = info.shape[2];
  const size_t frame_size = height * width;

  // pointer to a single row (tiff_bytep is a typedef to unsigned char or char)
  const uint8_t *element_r = static_cast<const uint8_t*>(b.ptr());
  const uint8_t *element_g = element_r + frame_size;
  const uint8_t *element_b = element_g + frame_size;

  GifByteType *red_buffer = const_cast<GifByteType*>(reinterpret_cast<const GifByteType*>(element_r));
  GifByteType *green_buffer = const_cast<GifByteType*>(reinterpret_cast<const GifByteType*>(element_g));
  GifByteType *blue_buffer = const_cast<GifByteType*>(reinterpret_cast<const GifByteType*>(element_b));
  boost::shared_array<GifByteType> output_buffer(new GifByteType[width*height]);

  // The following piece of code is based on the giflib utility called gif2rgb
  const int ExpNumOfColors = 8;
  int ColorMapSize = 1 << ExpNumOfColors;
  ColorMapObject *OutputColorMap = 0;

#if defined(GIF_LIB_VERSION) || (GIFLIB_MAJOR < 5)
  if((OutputColorMap = MakeMapObject(ColorMapSize, NULL)) == 0)
#else
  if((OutputColorMap = GifMakeMapObject(ColorMapSize, NULL)) == 0)
#endif
    throw std::runtime_error("GIF: error in GifMakeMapObject().");

  int error;
#if defined(GIF_LIB_VERSION) || (GIFLIB_MAJOR < 5)
  error = QuantizeBuffer(width, height, &ColorMapSize,
      red_buffer, green_buffer, blue_buffer, output_buffer.get(),
      OutputColorMap->Colors);
#else
  error = GifQuantizeBuffer(width, height, &ColorMapSize,
      red_buffer, green_buffer, blue_buffer, output_buffer.get(),
      OutputColorMap->Colors);
#endif
  if (error == GIF_ERROR) GifErrorHandler("GifQuantizeBuffer", error);

  error = EGifPutScreenDesc(out_file.get(), width, height, ExpNumOfColors, 0,
      OutputColorMap);
  if (error == GIF_ERROR) GifErrorHandler("EGifPutScreenDesc", out_file->Error);

  error = EGifPutImageDesc(out_file.get(), 0, 0, width, height, false, NULL);
  if (error == GIF_ERROR) GifErrorHandler("EGifPutImageDesc", out_file->Error);

  GifByteType *ptr = output_buffer.get();
  for(int i=0; i<height; ++i) {
    error = EGifPutLine(out_file.get(), ptr, width);
    if (error == GIF_ERROR) GifErrorHandler("EGifPutImageDesc", out_file->Error);
    ptr += width;
  }

  // Free map object
#if defined(GIF_LIB_VERSION) || (GIFLIB_MAJOR < 5)
  FreeMapObject(OutputColorMap);
#else
  GifFreeMapObject(OutputColorMap);
#endif
}

static void im_save(const std::string& filename, const bob::io::base::array::interface& array)
{
  // 1. GIF file opening
  boost::shared_ptr<GifFileType> out_file = make_efile(filename.c_str());

  // 2. Set the image information here:
  const bob::io::base::array::typeinfo& info = array.type();

  // 3. Writes content
  if(info.dtype == bob::io::base::array::t_uint8) {
    if(info.nd == 3) {
      if(info.shape[0] != 3)
        throw std::runtime_error("color image does not have 3 planes on 1st. dimension");
      im_save_color(array, out_file);
    }
    else {
      boost::format m("GIF: cannot save object of type `%s' to file `%s'");
      m % info.str() % filename;
      throw std::runtime_error(m.str());
    }
  }
  else {
    boost::format m("GIF: cannot save object of type `%s' to file `%s'");
    m % info.str() % filename;
    throw std::runtime_error(m.str());
  }
}

/**
 * GIF class
*/
bob::io::image::GIFFile::GIFFile(const char* path, char mode)
: m_filename(path),
  m_newfile(true) {

  //checks if file exists
  if (mode == 'r' && !boost::filesystem::exists(path)) {
    boost::format m("file '%s' is not readable");
    m % path;
    throw std::runtime_error(m.str());
  }

  if (mode == 'r' || (mode == 'a' && boost::filesystem::exists(path))) {
    im_peek(path, m_type);
    m_length = 1;
    m_newfile = false;
  }
  else {
    m_length = 0;
    m_newfile = true;
  }
}

void bob::io::image::GIFFile::read(bob::io::base::array::interface& buffer, size_t index) {
  if (m_newfile)
    throw std::runtime_error("uninitialized image file cannot be read");

  if (!buffer.type().is_compatible(m_type)) buffer.set(m_type);

  if (index != 0)
    throw std::runtime_error("cannot read image with index > 0 -- there is only one image in an image file");

  if(!buffer.type().is_compatible(m_type)) buffer.set(m_type);
  im_load(m_filename, buffer);
}

size_t bob::io::image::GIFFile::append(const bob::io::base::array::interface& buffer) {
  if (m_newfile) {
    im_save(m_filename, buffer);
    m_type = buffer.type();
    m_newfile = false;
    m_length = 1;
    return 0;
  }

  throw std::runtime_error("image files only accept a single array");
}

void bob::io::image::GIFFile::write (const bob::io::base::array::interface& buffer) {
  //overwriting position 0 should always work
  if (m_newfile) {
    append(buffer);
    return;
  }

  throw std::runtime_error("image files only accept a single array");
}

std::string bob::io::image::GIFFile::s_codecname = "bob.image_gif";

boost::shared_ptr<bob::io::base::File> make_gif_file (const char* path, char mode) {
  return boost::make_shared<bob::io::image::GIFFile>(path, mode);
}

#endif // HAVE_GIFLIB


text:
#include <iostream>
#include <vector>
#include <boost/polygon/voronoi.hpp>
#include <boost/polygon/polygon.hpp>

typedef boost::polygon::point_data<int> Point;
typedef boost::polygon::segment_data<int> Segment;

int main(int argc, char** argv)
{
    std::vector<Point> points;
    std::vector<Segment> segments;
    points.push_back(Point(0, 0));
    points.push_back(Point(1, 6));
    segments.push_back(Segment(Point(-4, 5), Point(5, -1)));
    segments.push_back(Segment(Point(3, -11), Point(13, -1)));
    boost::polygon::voronoi_diagram<double> vd;
    boost::polygon::construct_voronoi(
        points.begin(),
        points.end(),
        segments.begin(),
        segments.end(),
        &vd);
    return 0;
}

ext: cpp

max_stars_repo_name: daniel-s-ingram/CppRobotics

max_issues_repo_name: daniel-s-ingram/CppRobotics

max_forks_repo_name: daniel-s-ingram/CppRobotics


text:
#define BOOST_TEST_MODULE WayOut2Section4Tests

#include <boost/test/unit_test.hpp>
#include "test_common.h"

BOOST_AUTO_TEST_CASE(Section4Level01)
{
    const char * indata = 1 + R"(
__._____
_.Xn____
__nn.___
.._XXv__
Xh.XhNH_
_.N._v..
__.v._._
___X.___
)";
    const char * outdata = 1 + R"(
__._____
_.12____
__3..___
.._.45__
.6.7..8_
_.9._...
__.A._._
___..___
)";
    test(indata, {outdata});
}

BOOST_AUTO_TEST_CASE(Section4Level02)
{
    const char * indata = 1 + R"(
X._____
X.X____
_.._v._
__Vh.N.
N.h.h.h
HV.nn__
_.H_.._
____XXX
_____XX
)";
    const char * outdata = 1 + R"(
1._____
..2____
_.._3._
__45.6.
7.89A.B
.C.DE__
_F._.._
____.G.
_____..
)";
    test(indata, {outdata});
}

BOOST_AUTO_TEST_CASE(Section4Level04)
{
    const char * indata = 1 + R"(
____XX____
____X.X___
__XXXXn___
__XXX__XX_
XhXXp__p.P
.pv__....X
_..__vX.__
___n.Ph.__
___X..____
____XX____
)";
    const char * outdata = 1 + R"(
____..____
____.1.___
__.2..3___
__...__.._
.45..__.6.
..7__.89..
_..__.AB__
___C.D..__
___.E.____
____..____
)";
    test(indata, {outdata});
}

BOOST_AUTO_TEST_CASE(Section4Level05)
{
    const char * indata = 1 + R"(
__XXX_____
____..____
.XXX_n.___
_.VXX_.n__
_X__n._.X_
___v_X_Xn.
___XN___X.
____.X.V__
_____Vnh__
)";
    const char * outdata = 1 + R"(
__.1._____
____..____
.234_5.___
_6..7_89__
_.__.A_.._
___B_._.C.
___.D___E.
____...F__
_____GHI__
)";
    test(indata, {outdata});
}

BOOST_AUTO_TEST_CASE(Section4Level06)
{
    const char * indata = 1 + R"(
.H.vX_____
V__nHn____
N_.___.___
..hnh.Hn__
vV___N_.X_
_n_H._._vn
__N._NV_X.
___v._._hn
____N_.n_n
_____.H.Hv
)";
    const char * outdata = 1 + R"(
.1..._____
2__345____
._6___.___
..789.AB__
.C___D_.._
_._E._._..
__F._GH_..
___.._._IJ
____K_.._L
_____.M.NO
)";
    test(indata, {outdata});
}

BOOST_AUTO_TEST_CASE(Section4Level07)
{
    const char * indata = 1 + R"(
X...H____
.____X___
VNX.oXn__
n.v____X_
......._v
_XOXXO_X.
__....__X
___XX.nv.
____XoXXX
)";
    const char * outdata = 1 + R"(
.12.3____
.____.___
45...6.__
7.8____9_
.....A._B
_.C..D_E.
__....__.
___F..GH.
____...I.
)";
    test(indata, {outdata});
}

BOOST_AUTO_TEST_CASE(Section4Level08)
{
    const char * indata = 1 + R"(
..XXH_____
V__N_.____
._XHX_V___
.NX_VX.X__
X_X_X_X_N_
_._._._X_X
__N_Xv_HXX
___Xh.XX_V
____.__n_X
_____XhXX.
)";
    const char * outdata = 1 + R"(
....1_____
.__2_.____
3_.4._5___
6.._7...__
._8_._9_A_
_._._._._.
__._B._C..
___D..E._F
____.__._.
_____G.H..
)";
    test(indata, {outdata});
}

BOOST_AUTO_TEST_CASE(Section4Level09)
{
    const char * indata = 1 + R"(
___vP__________
___XXXvO_______
__X.____v______
HXvN._o_V______
.__X_____._____
_vP._nVXH.n____
_O__n.n_PH.h.__
_._.._XO.__._._
__Xv__h__VHh_O_
____N.OX_._pNN_
_____X_Nnhv__..
______v_n.__.ON
______X__._hV__
_______hO.VH___
__________Np___
)";
    const char * outdata = 1 + R"(
___1.__________
___..2.3_______
__..____4______
5.6.._._.______
.__7_____._____
_.8._.9....____
_A__..._.B.CD__
_E_.._.F.__._._
__..__G__.H._I_
____..J._._.K._
_____L_....__..
______._..__MN.
______O__._..__
_______.P..Q___
__________R.___
)";
    test(indata, {outdata});
}

BOOST_AUTO_TEST_CASE(Section4Level10)
{
    const char * indata = 1 + R"(
...o.X_____
XX.X..O____
.O...O..___
X..X____X__
X.X_Xhn_PX_
X.O_hXN_X.X
_X._VV._...
__X____X..p
___X.PXX.P.
____X...X.X
_____X.p.P.
)";
    const char * outdata = 1 + R"(
......_____
......1____
.2..34..___
5..6____7__
..._.89_.._
..A_.B._...
_C._D.._..E
__.____F...
___......GH
____I.J...K
_____...L..
)";
    test(indata, {outdata});
}


text:
/* vim: set sw=4 sts=4 et foldmethod=syntax : */

#include <boost/program_options.hpp>

#include <cstdlib>
#include <exception>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <vector>

namespace po = boost::program_options;

using std::cerr;
using std::cout;
using std::endl;
using std::exception;
using std::ifstream;
using std::make_unique;
using std::map;
using std::ofstream;
using std::string;
using std::stringstream;
using std::unique_ptr;
using std::vector;

auto main(int argc, char * argv[]) -> int
{
    try {
        po::options_description display_options{ "Program options" };
        display_options.add_options()
            ("help",                                         "Display help information");

        po::options_description all_options{ "All options" };
        all_options.add_options()
            ("instances-file",    po::value<string>(),          "Specify the instances file (first column specifies output name)")
            ("results-directory", po::value<vector<string> >(), "Directories which contain results")
            ;

        all_options.add(display_options);

        po::positional_options_description positional_options;
        positional_options
            .add("instances-file", 1)
            .add("results-directory", -1)
            ;

        po::variables_map options_vars;
        po::store(po::command_line_parser(argc, argv)
                .options(all_options)
                .positional(positional_options)
                .run(), options_vars);
        po::notify(options_vars);

        /* --help? Show a message, and exit. */
        if (options_vars.count("help")) {
            cout << "Usage: " << argv[0] << " [options] instances-file results-directory..." << endl;
            cout << endl;
            cout << display_options << endl;
            return EXIT_SUCCESS;
        }

        /* No algorithm or no input file specified? Show a message and exit. */
        if (! options_vars.count("instances-file") || ! options_vars.count("results-directory")) {
            cout << "Usage: " << argv[0] << " [options] instances-file results-directory..." << endl;
            return EXIT_FAILURE;
        }

        auto results_dirs = options_vars["results-directory"].as<vector<string> >();

        ifstream instances{ options_vars["instances-file"].as<string>() };
        if (! instances) {
            cerr << "Error reading instances file" << endl;
            return EXIT_FAILURE;
        }

        map<string, unique_ptr<ofstream> > output_files;
        output_files.emplace("runtime", make_unique<ofstream>("runtimes.data"));
        output_files.emplace("nodes", make_unique<ofstream>("nodes.data"));
        output_files.emplace("status", make_unique<ofstream>("statuses.data"));

        for (auto & [ _, f ] : output_files) {
            *f << "instance";
            for (auto & d : results_dirs)
                *f << " " << d;
            *f << endl;

            if (! *f) {
                cerr << "Error writing output file" << endl;
                return EXIT_FAILURE;
            }
        }

        string instances_line;
        while (getline(instances, instances_line)) {
            stringstream instances_line_s{ instances_line };
            string instance_name;
            if (! (instances_line_s >> instance_name))
                continue;

            for (auto & [ _, f ] : output_files)
                *f << instance_name;

            for (auto & d : results_dirs) {
                string instance_result_file_name{ d + "/" + instance_name + ".out" };
                ifstream result_file{ instance_result_file_name };
                if (! result_file) {
                    cerr << "Error reading " << instance_result_file_name << endl;
                    return EXIT_FAILURE;
                }

                map<string, string> keys;
                bool aborted = false;
                string key_line;
                while (getline(result_file, key_line)) {
                    auto pos = key_line.find('=');
                    if (string::npos == pos) {
                        cerr << "Couldn't parse '" << key_line << "' in " << instance_result_file_name << endl;
                        return EXIT_FAILURE;
                    }

                    auto k = key_line.substr(0, pos);
                    k.erase(k.find_last_not_of(" ") + 1, k.length());
                    auto v = key_line.substr(pos + 1);
                    v.erase(0, v.find_first_not_of(" "));
                    keys.emplace(k, v);

                    if (k == "status") {
                        if (v == "true") {
                        }
                        else if (v == "false") {
                        }
                        else if (v == "aborted") {
                            aborted = true;
                        }
                        else {
                            cerr << "Couldn't parse status value '" << v << " in " << instance_result_file_name << endl;
                            return EXIT_FAILURE;
                        }
                    }
                }

                for (auto & [ k, f ] : output_files) {
                    if (! keys.count(k)) {
                        cerr << "Missing key " << k << " in " << instance_result_file_name << endl;
                        return EXIT_FAILURE;
                    }

                    if (aborted && (k == "runtime" || k == "nodes"))
                        *f << " " << "NaN";
                    else
                        *f << " " << keys.find(k)->second;
                }
            }

            for (auto & [ _, f ] : output_files)
                *f << endl;
        }

        return EXIT_SUCCESS;
    }
    catch (const po::error & e) {
        cerr << "Error: " << e.what() << endl;
        cerr << "Try " << argv[0] << " --help" << endl;
        return EXIT_FAILURE;
    }
    catch (const exception & e) {
        cerr << "Error: " << e.what() << endl;
        return EXIT_FAILURE;
    }
}

ext: cc

max_stars_repo_name: jdmoorman/subgraph-matching

max_issues_repo_name: jdmoorman/subgraph-matching

max_forks_repo_name: jdmoorman/subgraph-matching


text:
// -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
// vi: set ts=2 noet:
//
// (c) Copyright Rosetta Commons Member Institutions.
// (c) This file is part of the Rosetta software suite and is made available under license.
// (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
// (c) For more information, see http://wsic_dockosettacommons.org. Questions about this casic_dock
// (c) addressed to University of Waprotocolsgton UW TechTransfer, email: license@u.washington.eprotocols

#ifndef INCLUDED_riflib_UnsatManager_hh
#define INCLUDED_riflib_UnsatManager_hh

#include <riflib/types.hh>
#include <riflib/rifdock_typedefs.hh>

#include <scheme/search/HackPack.hh>
#include <riflib/BurialManager.hh>

#include <core/pose/Pose.hh>

#include <string>
#include <vector>

#include <boost/any.hpp>

namespace devel {
namespace scheme {

namespace hbond {

enum AType {
    Hydroxyl,
    TyrHydroxyl,
    HydroxylH,
    TyrHydroxylH,
    BBAmide,
    BBCarbonyl,
    Amide,
    AmideCarbonyl,
    ArgNH,
    ArgNE,
    LysN,
    Carboxylate,
    TrypN,
    HisN,
    HisH,
    Unknown
};

const std::vector<int> NumOrbitals {
    2,  // "Hydroxyl",
    2,  // "TyrHydroxyl",
    1,  // "HydroxylH",
    1,  // "TyrHydroxylH",
    1,  // "BBAmide",
    2,  // "BBCarbonyl",
    2,  // "Amide",
    2,  // "AmideCarbonyl",
    2,  // "ArgNH",
    1,  // "ArgNE",
    3,  // "LysN",
    2,  // "Carboxylate",
    1,  // "TrypN",
    1,  // "HisN",
    1,  // "HisH",
    0  // "Unknown"
};

const std::vector<std::string> ATypeNames {
    "Hydroxyl",
    "TyrHydroxyl",
    "HydroxylH",
    "TyrHydroxylH",
    "BBAmide",
    "BBCarbonyl",
    "Amide",
    "AmideCarbonyl",
    "ArgNH",
    "ArgNE",
    "LysN",
    "Carboxylate",
    "TrypN",
    "HisN",
    "HisH",
    "Unknown"
};

// This is really arbitrary - brian
// Loosely based on this http://www.biochem.ucl.ac.uk/bsm/atlas/index.html
// See UnsatManager::prepare_packer for an explanation of why the scores are formatted like this

// penalty__first_atom = DefaultUnsatPenalties[X][0]
// penalty_second_atom = DefaultUnsatPenalties[X][0] * DefaultUnsatPenalties[X][1]
// penalty__third_atom = DefaultUnsatPenalties[X][0] * ( 1  - 2*( 1 - DefaultUnsatPenalties[X][1] ) )

// first number is penalty for last unsat
// second number is ratio of that for second one
//    the third one is 1 - ( 2*(1 - ratio ) )
const std::vector<std::vector<float>> DefaultUnsatPenalties {
    std::vector<float> {0, 0},    // "Hydroxyl",
    std::vector<float> {0, 0},    // "TyrHydroxyl",
    std::vector<float> {4, 0},    // "HydroxylH",
    std::vector<float> {4, 0},    // "TyrHydroxylH",
    std::vector<float> {4, 0},    // "BBAmide",
    std::vector<float> {4, 0},    // "BBCarbonyl",
    std::vector<float> {4, 0.5},    // "Amide",
    std::vector<float> {4, 0},    // "AmideCarbonyl",
    std::vector<float> {3, 1},    // "ArgNH",
    std::vector<float> {3, 0},    // "ArgNE",
    std::vector<float> {4, 1},    // "LysN",
    std::vector<float> {3, 1},    // "Carboxylate",
    std::vector<float> {4, 0},    // "TrypN",
    std::vector<float> {0, 0},    // "HisN",
    std::vector<float> {4, 0},    // "HisH"
    std::vector<float> {0, 0}    // "Unknown"
};
const std::vector<std::vector<float>> ScottUnsatPenalties {
    std::vector<float> {0, 0},    // "Hydroxyl",
    std::vector<float> {0, 0},    // "TyrHydroxyl",
    std::vector<float> {4, 0},    // "HydroxylH",
    std::vector<float> {4, 0},    // "TyrHydroxylH",
    std::vector<float> {4, 0},    // "BBAmide",
    std::vector<float> {4, 0},    // "BBCarbonyl",
    std::vector<float> {4, 0},    // "Amide",
    std::vector<float> {4, 0},    // "AmideCarbonyl",
    std::vector<float> {4, 0},    // "ArgNH",
    std::vector<float> {4, 0},    // "ArgNE",
    std::vector<float> {4, 0.5},    // "LysN",  // making this 0 is glitchy
    std::vector<float> {4, 0},    // "Carboxylate",
    std::vector<float> {4, 0},    // "TrypN",
    std::vector<float> {0, 0},    // "HisN",
    std::vector<float> {4, 0},    // "HisH"
    std::vector<float> {0, 0}    // "Unknown"
};

// std::vector<std::vector<float>> DefaultUnsatPenalties {
//     std::vector<float> {6, 2, 0, 0},
//     std::vector<float> {6, 2, 0, 0},
//     std::vector<float> {6, 2, 0, 0},
//     std::vector<float> {6, 2, 0, 0},
//     std::vector<float> {4, 0},
//     std::vector<float> {6, 2, 0},
//     std::vector<float> {6, 2, 0},
//     std::vector<float> {6, 2, 0},
//     std::vector<float> {8, 4, 0},
//     std::vector<float> {4, 0},
//     std::vector<float> {12, 8, 4, 0},
//     std::vector<float> {8, 4, 0},
//     std::vector<float> {4, 0},
//     std::vector<float> {4, 0}
// };

struct HeavyAtom {
    int AType = 0;
    int resid = 0;
    std::vector<int> sat_groups;
    std::string name = "";
    Eigen::Vector3f xyz;
};

AType
identify_donor( std::string const & dname, std::string & heavy_atom_name );

AType
identify_acceptor( std::string const & aname, char one_letter, std::string & heavy_atom_name );

enum Patch {
    NONE,
    NOT_BURIED,
    ACTUALLY_HBONDING
};

}

struct ToPackRot {
    int ires;
    int irot;
    float score;
    int sat1;
    int sat2;
    ToPackRot( int _ires, int _irot, float _score, int _sat1, int _sat2 ) :
        ires(_ires), irot(_irot), score(_score), sat1(_sat1), sat2(_sat2) {}
};

struct UnsatManager {

    UnsatManager() {} // used by clone()

    UnsatManager(
        std::vector<std::vector<float>> const & unsat_penalties,
        shared_ptr< RotamerIndex > rot_index_p,
        int require_burial,
        float score_offset,
        bool debug,
        bool store_common_unsats
    );

    shared_ptr<UnsatManager>
    clone() const;

    void
    reset();

    void
    set_target_donors_acceptors(
        core::pose::Pose const & target,
        std::vector<HBondRay> const & target_donors,
        std::vector<HBondRay> const & target_acceptors,
        std::vector<std::pair<int,std::string>> const & donor_anames,
        std::vector<std::pair<int,std::string>> const & acceptor_anames );

    void
    find_target_presatisfied(
        core::pose::Pose const & target
    );

    void
    dump_presatisfied();

    std::vector<float>
    get_initial_unsats( std::vector<float> const & burial_weights ) const;

    std::vector<float>
    get_buried_unsats(
        std::vector<float> const & burial_weights,
        std::vector< std::pair<intRot,intRot> > const & rotamers,
        std::vector< EigenXform > const & bb_positions,
        RifScoreRotamerVsTarget const & rot_tgt_scorer
    ) const;

    void
    print_buried_unsats( std::vector<float> const & unsat_penalties) const;

    void
    print_unsats_help( std::vector<float> const & unsat_penalties) const;

    std::vector<Eigen::Vector3f>
    get_heavy_atom_xyzs();

    std::vector<bool> const &
    get_presatisfied() { return target_presatisfied_; }

    float
    calculate_nonpack_score(
        std::vector<float> const & burial_weights,
        std::vector<bool> const & is_satisfied
    );

    float
    calculate_unsat_score( float P0, float P1, int wants, int satisfied, float weight ) const;

    void
    add_to_pack_rot(
        int ires,
        int irot,
        float score,
        int sat1,
        int sat2
    );

    float
    prepare_packer(
        ::scheme::search::HackPack & packer,
        std::vector<float> const & burial_weights
    );

    void
    insert_to_pack_rots_into_packer( ::scheme::search::HackPack & packer );

    void
    fix_packer(
        ::scheme::search::HackPack & packer,
        shared_ptr<::scheme::objective::storage::TwoBodyTable<float> const> reference_twobody
    );

    bool
    patch_heavy_atoms(
        int resid,
        std::string const & heavy_atom,
        hbond::Patch patch,
        shared_ptr<BurialManager> const & burial_manager
    );

    void
    apply_unsat_helper(
        std::string const & unsat_helper_fname,
        shared_ptr<BurialManager> const & burial_manager
    );

    void
    sum_unsat_counts( UnsatManager const & other );

    void
    print_unsat_counts() const;

// private:
    int
    find_heavy_atom(
        int resid,
        std::string const & heavy_atom_name,
        bool strict = false
    );

    void
    add_target_sat(
        int resid,
        std::string const & heavy_atom_name,
        hbond::AType heavy_atom_type,
        Eigen::Vector3f const & xyz,
        int sat
    );

    float
    handle_twobody(
        int satisfier1,
        int satisfier2,
        float penalty,
        ::scheme::search::HackPack & packer
    );

    bool
    validate_heavy_atoms();

// private:

    int num_donors_;
    std::vector<HBondRay> target_donors_acceptors_;
    std::vector<hbond::HeavyAtom> target_heavy_atoms_;
    std::vector<bool> target_presatisfied_;
    std::vector<std::vector<float>> unsat_penalties_;
    std::vector<std::vector<float>> total_first_twob_;  // total penalty, P0, P0 * (1 - P1)
    shared_ptr< RotamerIndex > rot_index_p;
    int require_burial_;
    float score_offset_;
    bool debug_;

    bool store_common_unsats_;
    std::vector<uint64_t> unsat_counts_;

// things that are resetable
    std::vector<ToPackRot> to_pack_rots_;
    std::vector<std::array<int, 4>> modified_edges_;

};

}}

#endif

ext: hh

max_stars_repo_name: willsheffler/rifdock

max_issues_repo_name: willsheffler/rifdock

max_forks_repo_name: willsheffler/rifdock


text:
/*
 *   Copyright 2016 sigalor
 *
 *   File: scratch-code-ast/include/ast/RValueValue.hpp
 *
 *   Licensed 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.
 */

#pragma once

#include <cstdlib>
#include <vector>
#include <memory>
#include <boost/variant.hpp>																						//TODO: when C++17 becomes available/more widespread, use std::variant

#include "Node.hpp"
#include "RValue.hpp"
#include "LexerTokenDefinitions.hpp"
#include "Utilities.hpp"

namespace ast
{
	class RValueValue : public RValue
	{
		public:
			static const int									uniqueId;

		private:
			Lexer::ParsedVariableType							type;
			boost::variant<bool, uint64_t, double, std::string>	value;												//may contain values for all variable types in ast::Lexer::ParsedVariableType

		protected:
			RValueValue(int newId);
			RValueValue(int newId, std::shared_ptr<Node> newParent);
			RValueValue(int newId, std::shared_ptr<Node> newParent, bool newValue);

		public:
			using ValueVariantType = decltype(value);

			RValueValue();
			RValueValue(std::shared_ptr<Node> newParent);
			RValueValue(std::shared_ptr<Node> newParent, bool newValue);
			RValueValue(std::shared_ptr<Node> newParent, uint64_t newValue);
			RValueValue(std::shared_ptr<Node> newParent, double newValue);
			RValueValue(std::shared_ptr<Node> newParent, const std::string& newValue);

			Lexer::ParsedVariableType							getType();
			ValueVariantType&									getValue();
			const std::string									getValueString() const;
			virtual Lexer::ParsedVariableType					getEffectiveType() { return type; }
			void												setValue(bool newValue);
			void												setValue(uint64_t newValue);
			void												setValue(double newValue);
			void												setValue(const std::string& newValue);
	};
}

ext: hpp

max_stars_repo_name: sigalor/scratch-code-ast

max_issues_repo_name: sigalor/scratch-code-ast

max_forks_repo_name: sigalor/scratch-code-ast


text:
///////////////////////////////////////////////////////////////////////////////
// vector_space::data::detail::cref.hpp                                      //
//                                                                           //
//  Copyright 2009 Erwann Rogard. Distributed under the Boost                //
//  Software License, Version 1.0. (See accompanying file                    //
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)         //
///////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_STATISTICS_DETAIL_VECTOR_SPACE_DATA_DETAIL_CREF_H_ER_2009
#define BOOST_STATISTICS_DETAIL_VECTOR_SPACE_DATA_DETAIL_CREF_H_ER_2009
#include <boost/mpl/not.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits.hpp>
#include <boost/range.hpp>

namespace boost{
namespace statistics{
namespace detail{
namespace vector_space{
namespace detail{

// A data structure that keeps a const reference to a range.
template<typename X>
struct cref{
    typedef is_reference<X> is_ref_x_;
    typedef is_const<X> is_const_x_;
    BOOST_MPL_ASSERT((boost::mpl::not_<is_ref_x_>));
    BOOST_MPL_ASSERT((boost::mpl::not_<is_const_x_>));

    cref(const X& x):x_(x){}
    cref(const cref& that):x_(that.x_){}
    typedef typename range_iterator<const X>::type const_iterator;

    const_iterator begin()const{ return boost::begin(x_); }
    const_iterator end()const{ return boost::end(x_); }

    const X& x_;
};

}// details
}// vector_space
}// detail
}// statistics
}// boost

#endif


text:
#include <string>

#include <ros/callback_queue.h>
#include <ros/console.h>
#include <ros/init.h>
#include <ros/node_handle.h>
#include <ros/param.h>
#include <ros/publisher.h>
#include <ros/service_server.h>
#include <ros/spinner.h>
#include <rosbag/recorder.h>
#include <std_msgs/Bool.h>
#include <std_srvs/Empty.h>

#include <boost/scoped_ptr.hpp>
#include <boost/thread/thread.hpp>

boost::scoped_ptr< rosbag::Recorder > recorder;
boost::thread run_thread;
boost::thread shutdown_thread;
ros::Publisher is_recording_publisher;

void publishIsRecording(const bool is_recording) {
  std_msgs::BoolPtr msg(new std_msgs::Bool());
  msg->data = is_recording;
  is_recording_publisher.publish(msg);
}

bool start(std_srvs::Empty::Request &, std_srvs::Empty::Response &) {
  namespace rp = ros::param;

  // do nothing if the recorder already started
  if (recorder || run_thread.joinable()) {
    ROS_ERROR("Already started");
    return false;
  }

  // read recorder options
  rosbag::RecorderOptions options;
  rp::get("~record_all", options.record_all);
  rp::get("~regex", options.regex);
  rp::get("~quiet", options.quiet);
  // note: as of kinetic, the quiet option looks ignored in rosbag::Recorder :(
  rp::get("~append_date", options.append_date);
  rp::get("~verbose", options.verbose);
  {
    std::string compression;
    if (rp::get("~compression", compression)) {
      if (compression == "uncompressed") {
        options.compression = rosbag::compression::Uncompressed;
      } else if (compression == "bz2") {
        options.compression = rosbag::compression::BZ2;
      } else if (compression == "lz4") {
        options.compression = rosbag::compression::LZ4;
      } else {
        ROS_WARN_STREAM("Unknown compression type: " << compression);
      }
    }
  }
  rp::get("~prefix", options.prefix);
  rp::get("~name", options.name);
  rp::get("~topics", options.topics);
  {
    std::string exclude_regex;
    if (rp::get("~exclude_regex", exclude_regex)) {
      options.do_exclude = true;
      options.exclude_regex = exclude_regex;
    }
  }
  {
    int buffer_size;
    if (rp::get("~buffer_size", buffer_size)) {
      options.buffer_size = buffer_size;
    }
  }
  rp::get("~node", options.node);
  // note: this node aims to enable service-triggered logging.
  //       so does not support the following options that may autonomously stop logging
  //   trigger / snapshot / chunk_size / limit / split
  //   / max_size / max_split / max_duration / min_space

  publishIsRecording(true);

  // launch rosbag-record. this thread will continue unless ros::shutdown() has been called
  ROS_INFO("Start recording");
  recorder.reset(new rosbag::Recorder(options));
  run_thread = boost::thread(&rosbag::Recorder::run, recorder.get());

  return true;
}

void sleepAndShutdown() {
  ros::Duration(0.5).sleep();
  ros::shutdown();
}

bool stop(std_srvs::Empty::Request &, std_srvs::Empty::Response &) {
  // do nothing if recording never started
  if (!recorder && !run_thread.joinable()) {
    ROS_ERROR("Never started");
    return false;
  }

  // do nothing if the shutdown already scheduled
  if (shutdown_thread.joinable()) {
    ROS_ERROR("Already stopped");
    return false;
  }

  publishIsRecording(false);

  // schedule a future call of ros::shutdown()
  // (because a direct call disconnects the current client)
  ROS_INFO("Stop recording");
  shutdown_thread = boost::thread(&sleepAndShutdown);

  return true;
}

int main(int argc, char *argv[]) {
  ros::init(argc, argv, "remote_rosbag_record");
  ros::NodeHandle nh;

  // rosbag will use the global queue.
  // to avoid confriction, use local queue for following services
  ros::CallbackQueue queue;
  nh.setCallbackQueue(&queue);

  is_recording_publisher = nh.advertise< std_msgs::Bool >("is_recording", 1, true);
  publishIsRecording(false);
  ros::ServiceServer start_server(nh.advertiseService("start", start));
  ros::ServiceServer stop_server(nh.advertiseService("stop", stop));

  // run services. this serving will continue unless ros::shutdown() has been called
  ros::SingleThreadedSpinner spinner;
  spinner.spin(&queue);

  // finalize the rosbag-record threads
  if (run_thread.joinable()) {
    run_thread.join();
  }
  if (shutdown_thread.joinable()) {
    shutdown_thread.join();
  }

  // manually free the recorder here.
  // the recorder contains a plugin loaded by class_loader so must be freed
  // before static variables in class_loader library (or get an exception).
  // these static variables will be destroyed before the gloval variable recorder
  // because they are allocated when the recorder is allocated in start().
  recorder.reset();

  return 0;
}


text:
#ifndef AWARE_BONJOUR_DETAIL_MONITOR_HPP
#define AWARE_BONJOUR_DETAIL_MONITOR_HPP

///////////////////////////////////////////////////////////////////////////////
//
// http://github.com/breese/aware
//
// Copyright (C) 2016 Bjorn Reese <breese@users.sourceforge.net>
//
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)
//
///////////////////////////////////////////////////////////////////////////////

#include <queue>
#include <set>
#include <map>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/basic_waitable_timer.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <aware/contact.hpp>
#include <aware/monitor_socket.hpp>
#include <aware/bonjour/detail/handle.hpp>
#include <aware/bonjour/detail/browser.hpp>
#include <aware/bonjour/detail/resolver.hpp>

namespace aware
{
namespace bonjour
{
namespace detail
{

// Bonjour periodically (about once per minute) reports false positives
// where announcements are reported as disappeared only to be reported
// as appeared again shortly after (a second or two.) In reality they
// have never disappeared. Consequently, action on disappear events is
// defered for a couple of seconds.
//
// When Bonjour reports false disappearances they are either reported
// on their actual network interface or on the "any" network interface.
// In the latter case, we cannot know exactly which network interface
// to ignore, so we keep track of the amount of disappearances as well
// as the re-appeared annoucements.

class monitor
    : public browser::listener,
      public resolver::listener
{
public:
    typedef typename aware::monitor_socket::async_listen_handler async_listen_handler;

    monitor(boost::asio::io_service&, detail::handle&);

    void listen(aware::contact&, async_listen_handler);

private:
    // browser::listener
    virtual void on_browser_appear(const aware::contact&, bool);
    virtual void on_browser_disappear(const aware::contact&, bool);
    virtual void on_browser_failure(const boost::system::error_code&);
    // resolver::listener
    virtual void on_resolver_done(const aware::contact&);
    virtual void on_resolver_failure(const boost::system::error_code&);

private:
    boost::asio::io_service& io;
    detail::handle& connection;
    std::string type;
    boost::optional<detail::browser> browser;
    boost::system::error_code permanent_error;

    struct request
    {
        request(aware::contact&, async_listen_handler);

        aware::contact& contact;
        async_listen_handler handler;
    };
    std::queue<request> requests;

    class scope : boost::noncopyable
    {
    public:
        typedef std::set<aware::contact> active_container;
        typedef std::set<aware::contact> addition_container;
        typedef std::multiset<aware::contact> removal_container;

        scope(boost::asio::io_service&, monitor&);
        ~scope();

        void submit_appear(const aware::contact&);
        void commit_appear();
        void submit_disappear(const aware::contact&);
        void commit_disappear();
        void resolved(const aware::contact&);

        void activate(const aware::contact&);
        void deactivate(const aware::contact&);

    private:
        void process_disappear(const boost::system::error_code&);
        void execute_appear();
        void execute_disappear();

    private:
        monitor& self;
        boost::asio::basic_waitable_timer<boost::chrono::steady_clock> timer;
        active_container active;
        addition_container additions;
        removal_container removals;
        std::size_t wildcard_count;
    };
    // Key is name (type is implicit)
    typedef std::map< std::string, boost::shared_ptr<scope> > scope_container;
    scope_container scopes;

    typedef std::set<std::string> name_container;
    name_container uncommitted_appear;
    name_container uncommitted_disappear;

    typedef std::map< aware::contact, boost::shared_ptr<detail::resolver> > resolvers_type;
    resolvers_type resolvers;
};

} // namespace detail
} // namespace bonjour
} // namespace aware

#endif // AWARE_BONJOUR_DETAIL_MONITOR_HPP

max_stars_repo_name: zpon/aware

max_issues_repo_name: zpon/aware

max_forks_repo_name: zpon/aware


text:
/*
* Copyright 2019 © Centre Interdisciplinaire de développement en Cartographie des Océans (CIDCO), Tous droits réservés
*/

 /*
 * \author Christian Bouchard
 */

#ifndef HULLOVERLAP_HPP
#define HULLOVERLAP_HPP

#include <iostream>
#include <cstdint>

#include <vector>

#include <utility>      // std::pair, std::make_pair

#include <pcl/common/common_headers.h>

#include <pcl/point_types.h>
#include <pcl/surface/concave_hull.h>

#include <pcl/PointIndices.h>

#include <pcl/ModelCoefficients.h>
#include <pcl/filters/project_inliers.h>

#include <pcl/segmentation/extract_polygonal_prism_data.h>

#include <Eigen/Dense>
#include <Eigen/Geometry> // For cross product

class HullOverlap
{

public:

	/**
	* Creates a HullOverlap
	*
	* @param line1In Point cloud for line #1
	* @param line2In Point cloud for line #2
    * @param a projection plane coefficient 'a' in ax + by + cz + d = 0
    * @param b projection plane coefficient 'b' in ax + by + cz + d = 0
    * @param c projection plane coefficient 'c' in ax + by + cz + d = 0
    * @param d projection plane coefficient 'd' in ax + by + cz + d = 0
    * @param alpha1 Concave hull computation parameter to use with line #1
    * @param alpha2 Concave hull computation parameter to use with line #2
	*/
    HullOverlap( pcl::PointCloud<pcl::PointXYZ>::ConstPtr line1In,
                    pcl::PointCloud<pcl::PointXYZ>::ConstPtr line2In,
                    double a, double b, double c, double d,
                    double alphaLine1 = 1.0, double alphaLine2 = 1.0 )
                    :   line1( line1In ), line2( line2In ),
                        a( a ), b( b ), c( c ), d( d ),
                        alphaLine1( alphaLine1 ), alphaLine2( alphaLine2 ),

                        coefficients ( new pcl::ModelCoefficients() ),

                        line1InPlane (new pcl::PointCloud<pcl::PointXYZ>),
                        line2InPlane (new pcl::PointCloud<pcl::PointXYZ>),

                        line1InPlane2D (new pcl::PointCloud<pcl::PointXYZ>),
                        line2InPlane2D (new pcl::PointCloud<pcl::PointXYZ>),

                        hull1Vertices (new pcl::PointCloud<pcl::PointXYZ>),
                        hull2Vertices (new pcl::PointCloud<pcl::PointXYZ>),

                       // Initialize to dummy values
                       vector1( 1, 0, 0 ), vector2( 0, 1, 0 ), refPoint( 0.0, 0.0, 0.0 )

    {
        coefficients->values.resize(4);
        coefficients->values[0] = a;
        coefficients->values[1] = b;
        coefficients->values[2] = c;
        coefficients->values[3] = d;
    }

	/**
	* Returns a pair with the number of points in line #1 and in line #2 that are in the overlap area of the two lines.
	* The points are place in the point clouds pointed to by line1InBothHull and line2InBothHull
    *
	* @param[out] line1InBothHull Point cloud of points in line #1 in the overlap area of the two lines
	* @param[out] line2InBothHull Point cloud of points in line #2 in the overlap area of the two lines
	*/
    std::pair< uint64_t, uint64_t > computePointsInBothHulls( pcl::PointCloud<pcl::PointXYZ>::Ptr line1InBothHull,
                                                              pcl::PointCloud<pcl::PointXYZ>::Ptr line2InBothHull )
    {
        return computeHullsAndPointsInBothHulls( line1InBothHull, line2InBothHull, true );
    }

private:

	/**
	* Returns a pair with the number of points in line #1 and in line #2 that are in the overlap area of the two lines,
	* the points are place in the point clouds pointed to by line1InBothHull and line2InBothHull
    *
	* @param[out] line1InBothHull Point cloud of points in line #1 in the overlap area of the two lines
	* @param[out] line2InBothHull Point cloud of points in line #2 in the overlap area of the two lines
    * @param[in] line2InBothHull minimalMemory bool variable, true to specify to try and minimize the memory usage
	*/
    // Was public when wanted to look at details of projection, etc
    std::pair< uint64_t, uint64_t > computeHullsAndPointsInBothHulls( pcl::PointCloud<pcl::PointXYZ>::Ptr line1InBothHull = nullptr,
                                                                        pcl::PointCloud<pcl::PointXYZ>::Ptr line2InBothHull = nullptr,
                                                                        const bool minimalMemory = false )
    {

        if ( line1InBothHull != nullptr )
            line1InBothHull->clear();

        if ( line2InBothHull != nullptr )
            line2InBothHull->clear();

        std::cout << "\nProjecting line 1 in plane\n" << std::endl;

        // Project line 1 in plane
        createCloudFromProjectionInPlane( line1, line1InPlane );

        std::cout << "line1InPlane->points.size(): " << line1InPlane->points.size() << "\n" << std::endl;

        computeTwoVectorsAndRefPoint();

        std::cout << "\nExpressing points of line 1 in the projection plane using a 2D coordinate system\n" << std::endl;

        createCloudInPlane2D( line1InPlane, line1InPlane2D );

        if ( minimalMemory )
        {
            // Delete the dynamically allocated memory
            line1InPlane.reset();
            line1InPlane = nullptr;
        }

        std::cout << "line1InPlane2D->points.size(): " << line1InPlane2D->points.size() << "\n" << std::endl;

        std::cout << "\nProjecting line 2 in plane\n" << std::endl;

        // Project line 2 in plane
        createCloudFromProjectionInPlane( line2, line2InPlane );

        std::cout << "line2InPlane->points.size(): " << line2InPlane->points.size() << "\n" << std::endl;

        std::cout << "\nExpressing points of line 2 in the projection plane using a 2D coordinate system\n" << std::endl;

        createCloudInPlane2D( line2InPlane, line2InPlane2D );

        if ( minimalMemory )
        {
            // Delete the dynamically allocated memory
            line2InPlane.reset();
            line2InPlane = nullptr;
        }

        std::cout << "line2InPlane2D->points.size(): " << line2InPlane2D->points.size() << "\n" << std::endl;

        //http://www.pointclouds.org/documentation/tutorials/hull_2d.php

        std::cout << "\nFinding Hull 1\n" << std::endl;

        // Create a Concave Hull for line 1
        computeVerticesOfConcaveHull( line1InPlane2D, alphaLine1, hull1Vertices, hull1PointIndices, ! minimalMemory );

        std::cout << "Finding Hull 2\n" << std::endl;

        // Create a Concave Hull for line 2
        computeVerticesOfConcaveHull( line2InPlane2D, alphaLine2, hull2Vertices, hull2PointIndices, ! minimalMemory );

        std::cout << "hull1Vertices->points.size(): " << hull1Vertices->points.size() << "\n"
            << "hull2Vertices->points.size(): " << hull2Vertices->points.size() << "\n" << std::endl;

        // If the hulls of the lines where found correctly, points of line 1 are within the hull of line 1.
        // So only need to check that a point of line 1 is part of hull 2 to know that it is part of both hulls.
        // Same idea for points of line 2.

        if ( line1InBothHull != nullptr && line2InBothHull != nullptr )
        {
            if ( minimalMemory )
            {
                std::cout << "Finding points of Line 1 inside Hull 2\n\n" << std::endl;

                findPointsInHullOnlyPoints( line1, line1InPlane2D, line1InBothHull, hull2Vertices );

                // Delete the dynamically allocated memory
                line1InPlane2D.reset();
                line1InPlane2D = nullptr;

                hull2Vertices.reset();
                hull2Vertices = nullptr;

                std::cout << "Finding points of Line 2 inside Hull 1\n\n" << std::endl;

                findPointsInHullOnlyPoints( line2, line2InPlane2D, line2InBothHull, hull1Vertices );

                // Delete the dynamically allocated memory
                line2InPlane2D.reset();
                line2InPlane2D = nullptr;

                hull1Vertices.reset();
                hull1Vertices = nullptr;

                std::cout << "line1InBothHull->points.size(): " << line1InBothHull->points.size() << "\n"
                    << "line2InBothHull->points.size(): " << line2InBothHull->points.size() << "\n" << std::endl;

                return std::make_pair( line1InBothHull->size(), line2InBothHull->size() );

            }
            else
            {

                std::cout << "Finding points of Line 1 inside Hull 2 (and the indices)\n\n" << std::endl;

                findPointsInHull( line1, line1InPlane2D, line1InBothHull, line1InBothHullPointIndices, hull2Vertices );

                std::cout << "Finding points of Line 2 inside Hull 1 (and the indices)\n\n" << std::endl;

                findPointsInHull( line2, line2InPlane2D, line2InBothHull, line2InBothHullPointIndices, hull1Vertices );

                std::cout << "line1InBothHull->points.size(): " << line1InBothHull->points.size() << "\n"
                    << "line2InBothHull->points.size(): " << line2InBothHull->points.size() << "\n" << std::endl;

                return std::make_pair( line1InBothHull->size(), line2InBothHull->size() );

            }

        }
        else
        {
            std::cout << "Finding indices of points of Line 1 inside Hull 2\n\n" << std::endl;

            findPointsInHullOnlyPointIndices( line1InPlane2D, line1InBothHullPointIndices, hull2Vertices );

            std::cout << "Finding indices of points of Line 2 inside Hull 1\n\n" << std::endl;

            findPointsInHullOnlyPointIndices( line2InPlane2D, line2InBothHullPointIndices, hull1Vertices );

            std::cout << "line1InBothHullPointIndices.size(): " << line1InBothHullPointIndices.size() << "\n"
                << "line2InBothHullPointIndices.size(): " << line2InBothHullPointIndices.size() << "\n" << std::endl;

            return std::make_pair( line1InBothHullPointIndices.size(), line2InBothHullPointIndices.size() );
        }

    }

    // These functions were public when wanted to look at details of projection, etc
    // pcl::PointCloud<pcl::PointXYZ>::ConstPtr getConstPtrLineInPlane( const bool isLine1 )
    // {
    //     if ( isLine1 )
    //         return line1InPlane;
    //     else
    //         return line2InPlane;
    // }

    // const std::vector< int > * getConstPtrVerticesIndices( const bool isLine1 )
    // {
    //     if ( isLine1 )
    //         return & ( hull1PointIndices.indices );
    //     else
    //         return & ( hull2PointIndices.indices );
    // }

    // const std::vector< uint64_t > * getConstPtrlineInBothHullPointIndices( const bool isLine1 )
    // {
    //     if ( isLine1 )
    //         return & ( line1InBothHullPointIndices );
    //     else
    //         return & ( line2InBothHullPointIndices );
    // }

	/**
	* Computes the projection of a point cloud onto a plane
    *
    * @param[in] cloudIn Point cloud to project on the plane
    * @param[out] cloudOut Point cloud resulting from the projection
	*/
    void createCloudFromProjectionInPlane( pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloudIn,
                                                pcl::PointCloud<pcl::PointXYZ>::Ptr cloudOut )
    {
        cloudOut->clear();
        cloudOut->reserve( cloudIn->points.size() );

        // Create the filtering object
        pcl::ProjectInliers<pcl::PointXYZ> proj;
        proj.setModelType( pcl::SACMODEL_PLANE );

        proj.setInputCloud( cloudIn );
        proj.setModelCoefficients( coefficients );

        proj.filter( *cloudOut );
    }

	/**
	* Computes two vectors and sets a reference point used to express point positions on the
    * projection plane using only two dimensions
	*/
    void computeTwoVectorsAndRefPoint()
    {

        // Two vectors and a reference point to span the projection plane
        // so that points in the projection plane can be expressed in
        // a coordinate system with vector1, vector2, and refPoint.

        refPoint = line1InPlane->points[ 0 ];

        // Vector #1: from first point in line to last point in line, normalized

        const uint64_t nbPointLine1 = line1InPlane->points.size();

        vector1 << line1InPlane->points[ nbPointLine1 - 1 ].x - line1InPlane->points[ 0 ].x,
                    line1InPlane->points[ nbPointLine1 - 1 ].y - line1InPlane->points[ 0 ].y,
                    line1InPlane->points[ nbPointLine1 - 1 ].z - line1InPlane->points[ 0 ].z;

        std::cout << "vector1 before normalization:\n" << vector1 << "\n\n";

        vector1 = vector1 / vector1.norm();

        std::cout << "vector1 after normalization:\n" << vector1 << "\n\n";

        Eigen::Vector3d normalToPlane;

        normalToPlane <<  a, b, c;

        // Vector #2: perpendicular to the normal to the plane and to vector #1
        vector2 = normalToPlane.cross( vector1 );

        std::cout << "vector2 before normalization:\n" << vector2 << "\n\n";

        vector2 = vector2 / vector2.norm();

        std::cout << "vector2 after normalization:\n" << vector2 << "\n\n";

        // Sanity check
        std::cout << "vector1 dot vector2: " << vector1.dot( vector2 ) << "    (should be 0)\n\n";
    }

	/**
	* Computes a 2D representation of points on the projection plane
    *
    * @param[in] cloudIn Point cloud on the projection plane expressed in 3D
    * @param[out] cloudOut Point cloud on the projection plane expressed in 2D
	*/
    void createCloudInPlane2D( pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloudIn,
                            pcl::PointCloud<pcl::PointXYZ>::Ptr cloudOut )
    {
        // Build a point cloud where points in the projection plane are expressed in
        // the coordinate system with vector1, vector2, and refPoint.

        cloudOut->clear();
        cloudOut->reserve( cloudIn->points.size() );

        for ( uint64_t count = 0; count < cloudIn->points.size(); count++ )
        {
            pcl::PointXYZ point;

            // projection along vector 1
            point.x = ( cloudIn->points[ count ].x - refPoint.x ) * vector1( 0 )
                        + ( cloudIn->points[ count ].y - refPoint.y ) * vector1( 1 )
                        + ( cloudIn->points[ count ].z - refPoint.z ) * vector1( 2 );

            // projection along vector 2
            point.y = ( cloudIn->points[ count ].x - refPoint.x ) * vector2( 0 )
                        + ( cloudIn->points[ count ].y - refPoint.y ) * vector2( 1 )
                        + ( cloudIn->points[ count ].z - refPoint.z ) * vector2( 2 );

            point.z = 0;

            cloudOut->push_back( point );

        }
    }

	/**
	* Computes the vertices of a concave hull for points on the projection plane
    *
    * @param[in] cloudIn Point cloud on the projection plane expressed in 2D
    * @param[in] alpha Concave hull computation parameter to use
    * @param[out] hullVertices Computed vertices of the concave hull
    * @param[out] hullPointIndices Indices of the points in cloudIn making up the hull
    * @param[in] keepInformation bool variable, true to specify to put the indices of the points in cloudIn in hullPointIndices
	*/
    void computeVerticesOfConcaveHull( pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloudIn,
                                        const double alpha,
                                        pcl::PointCloud<pcl::PointXYZ>::Ptr hullVertices,
                                        pcl::PointIndices & hullPointIndices, const bool keepInformation = true )
    {

        hullVertices->clear();

        pcl::ConcaveHull<pcl::PointXYZ> concaveHull;

        if ( keepInformation )
            concaveHull.setKeepInformation( true ); // To be able to use function getHullPointIndices()

        concaveHull.setInputCloud( cloudIn );
        concaveHull.setAlpha( alpha );
        concaveHull.reconstruct( * hullVertices );

        if ( keepInformation )
            // Get indices of points making the hull
            concaveHull.getHullPointIndices( hullPointIndices );
    }

	/**
	* Find points that are within a concave hull.
    * Provides the points and their indices within the original line
    *
    * @param[in] lineOriginal Point cloud of points on the line
    * @param[in] cloudIn Point cloud on the projection plane expressed in 2D
    * @param[out] cloudOut Point cloud of points on the line that are within the hull
    * @param[out] indexPointInHull Indices of the points on the line that are within the hull
    * @param[in] hullVertices Vertices of the concave hull
	*/
    void findPointsInHull( pcl::PointCloud<pcl::PointXYZ>::ConstPtr lineOriginal,
                                pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloudIn,
                                pcl::PointCloud<pcl::PointXYZ>::Ptr cloudOut,
                                std::vector< uint64_t > & indexPointInHull,
                                pcl::PointCloud<pcl::PointXYZ>::ConstPtr hullVertices )
    {
        cloudOut->clear();
        indexPointInHull.clear();

        for ( uint64_t count = 0; count < cloudIn->points.size(); count++ )
        {
            if ( pcl::isXYPointIn2DXYPolygon( cloudIn->points[ count ], *hullVertices ) )
            {
                cloudOut->push_back( lineOriginal->points[ count ] );
                indexPointInHull.push_back( count );
            }
        }

    }

	/**
	* Find indices of points that are within a concave hull.
    *
    * @param[in] cloudIn Point cloud on the projection plane expressed in 2D
    * @param[out] indexPointInHull Indices of the points on the line that are within the hull
    * @param[in] hullVertices Vertices of the concave hull
	*/
    void findPointsInHullOnlyPointIndices( pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloudIn,
                                    std::vector< uint64_t > & indexPointInHull,
                                    pcl::PointCloud<pcl::PointXYZ>::ConstPtr hullVertices )
    {
        indexPointInHull.clear();

        for ( uint64_t count = 0; count < cloudIn->points.size(); count++ )
        {
            if ( pcl::isXYPointIn2DXYPolygon( cloudIn->points[ count ], *hullVertices ) )
                indexPointInHull.push_back( count );
        }

    }

	/**
	* Find points that are within a concave hull.
    *
    * @param[in] lineOriginal Point cloud of points on the line
    * @param[in] cloudIn Point cloud on the projection plane expressed in 2D
    * @param[out] cloudOut Point cloud of points on the line that are within the hull
    * @param[in] hullVertices Vertices of the concave hull
	*/
    void findPointsInHullOnlyPoints( pcl::PointCloud<pcl::PointXYZ>::ConstPtr lineOriginal,
                                    pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloudIn,
                                    pcl::PointCloud<pcl::PointXYZ>::Ptr cloudOut,
                                    pcl::PointCloud<pcl::PointXYZ>::ConstPtr hullVertices )
    {
        cloudOut->clear();

        for ( uint64_t count = 0; count < cloudIn->points.size(); count++ )
        {
            if ( pcl::isXYPointIn2DXYPolygon( cloudIn->points[ count ], *hullVertices ) )
                cloudOut->push_back( lineOriginal->points[ count ] );
        }

    }

// ----------------------------- Variables ------------------------------------------------

    /**Point cloud for line #1*/
    const pcl::PointCloud<pcl::PointXYZ>::ConstPtr line1;

    /**Point cloud for line #2*/
    const pcl::PointCloud<pcl::PointXYZ>::ConstPtr line2;

    /**Projection plane coefficient 'a' in ax + by + cz + d = 0*/
    const double a;

    /**Projection plane coefficient 'b' in ax + by + cz + d = 0*/
    const double b;

    /**Projection plane coefficient 'c' in ax + by + cz + d = 0*/
    const double c;

    /**Projection plane coefficient 'd' in ax + by + cz + d = 0*/
    const double d;

    /**Concave hull computation parameter to use with line #1*/
    double alphaLine1; // Alpha value to compute the concave hull for line #1

    /**Concave hull computation parameter to use with line #2*/
    double alphaLine2; // Alpha value to compute the concave hull for line #2

    /**Coefficients for the plane, ax + by + cz + d = 0 */
    pcl::ModelCoefficients::Ptr coefficients;

    /**Point cloud of the projection of line #1 on the plane, expressed in 3D*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr line1InPlane;

    /**Point cloud of the projection of line #2 on the plane, expressed in 3D*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr line2InPlane;

    /**Point cloud of the projection of line #1 on the plane, expressed in 2D*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr line1InPlane2D;

    /**Point cloud of the projection of line #2 on the plane, expressed in 2D*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr line2InPlane2D;

    /**Vertices of the concave hull for line #1*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr hull1Vertices;

    /**Vertices of the concave hull for line #2*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr hull2Vertices;

    /**Indices of the points in line #1 whose projection on the plane makes up its hull*/
    pcl::PointIndices hull1PointIndices;

    /**Indices of the points in line #2 whose projection on the plane makes up its hull*/
    pcl::PointIndices hull2PointIndices;

    /**Indices of the points in line #1 that are within both hulls*/
    std::vector< uint64_t > line1InBothHullPointIndices;

    /**Indices of the points in line #2 that are within both hulls*/
    std::vector< uint64_t > line2InBothHullPointIndices;

    /**First computed orthonormal vector used to express points on the projection plane in 2D*/
    Eigen::Vector3d vector1;

    /**Second computed orthonormal vector used to express points on the projection plane in 2D*/
    Eigen::Vector3d vector2;

    /**Referenced point used to express points on the projection plane in 2D*/
    pcl::PointXYZ refPoint;

};

#endif

max_stars_repo_name: EmileGagne/MBES-lib

max_issues_repo_name: EmileGagne/MBES-lib

max_forks_repo_name: EmileGagne/MBES-lib


text:
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP
#define BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP

#include <boost/container/detail/config_begin.hpp>
#include <functional>
#include <iostream>
#include <algorithm>

namespace boost{
namespace container {
namespace test{

//Function to check if both containers are equal
template<class MyBoostCont
        ,class MyStdCont>
bool CheckEqualContainers(MyBoostCont *boostcont, MyStdCont *stdcont)
{
   if(boostcont->size() != stdcont->size())
      return false;

   typedef typename MyBoostCont::value_type value_type;

   typename MyBoostCont::iterator itboost(boostcont->begin()), itboostend(boostcont->end());
   typename MyStdCont::iterator itstd(stdcont->begin());
   typename MyStdCont::size_type dist = (typename MyStdCont::size_type)std::distance(itboost, itboostend);
   if(dist != boostcont->size()){
      return false;
   }
   std::size_t i = 0;
   for(; itboost != itboostend; ++itboost, ++itstd, ++i){
      value_type val(*itstd);
      const value_type &v = *itboost;
      if(v != val)
         return false;
   }
   return true;
}

template<class MyBoostCont
        ,class MyStdCont>
bool CheckEqualPairContainers(MyBoostCont *boostcont, MyStdCont *stdcont)
{
   if(boostcont->size() != stdcont->size())
      return false;

   typedef typename MyBoostCont::key_type      key_type;
   typedef typename MyBoostCont::mapped_type   mapped_type;

   typename MyBoostCont::iterator itboost(boostcont->begin()), itboostend(boostcont->end());
   typename MyStdCont::iterator itstd(stdcont->begin());
   for(; itboost != itboostend; ++itboost, ++itstd){
      if(itboost->first != key_type(itstd->first))
         return false;

      if(itboost->second != mapped_type(itstd->second))
         return false;
   }
   return true;
}
}  //namespace test{
}  //namespace container {
}  //namespace boost{

#include <boost/container/detail/config_end.hpp>

#endif //#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP


text:
#ifndef CANARD_ASIO_STUB_STREAM_HPP
#define CANARD_ASIO_STUB_STREAM_HPP

#include <cstddef>
#include <limits>
#include <utility>
#include <vector>
#include <type_traits>
#include <boost/asio/async_result.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/handler_type.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/system/error_code.hpp>

namespace canard_test {

  template <class CharT>
  class stub_stream
  {
  public:
    using lowest_layer_type = stub_stream;

    explicit stub_stream(
          boost::asio::io_service& io_service
        , std::size_t const max_writable_size_per_write
            = std::numeric_limits<std::size_t>::max()
        , boost::system::error_code const& ec
            = boost::system::error_code{})
      : io_service_(io_service)
      , max_writable_size_per_write_(max_writable_size_per_write)
      , ec_(ec)
      , max_writable_size_{0}
      , error_over_max_writable_size_{}
    {
    }

    auto get_io_service() noexcept
      -> boost::asio::io_service&
    {
      return io_service_;
    }

    auto lowest_layer() noexcept
      -> lowest_layer_type&
    {
      return *this;
    }

    template <
        class ConstBufferSequence, class CompletionToken
      , class WriteHandler = typename boost::asio::handler_type<
            typename std::decay<CompletionToken>::type
          , void(boost::system::error_code, std::size_t)
        >::type
    >
    auto async_write_some(
        ConstBufferSequence const& buffers, CompletionToken&& token)
      -> typename boost::asio::async_result<WriteHandler>::type
    {

      auto handler = WriteHandler(std::forward<CompletionToken>(token));
      boost::asio::async_result<WriteHandler> result{handler};

      auto bytes_transferred = std::size_t{0};
      if (!ec_) {
        auto tmp_written_data = std::vector<CharT>{};
        for (auto&& buffer : buffers) {
          auto const size = boost::asio::buffer_size(buffer);
          auto const data = boost::asio::buffer_cast<CharT const*>(buffer);
          if (size + bytes_transferred < max_writable_size_per_write_) {
            tmp_written_data.insert(tmp_written_data.end(), data, data + size);
            bytes_transferred += size;
          }
          else {
            auto const remain_size
              = max_writable_size_per_write_ - bytes_transferred;
            tmp_written_data.insert(
                tmp_written_data.end(), data, data + remain_size);
            bytes_transferred += remain_size;
          }
        }
        if (max_writable_size_ != 0) {
          if (max_writable_size_ <= bytes_transferred) {
            bytes_transferred = max_writable_size_;
            tmp_written_data.resize(bytes_transferred);
            max_writable_size_ = 0;
            ec_ = error_over_max_writable_size_;
          }
          else {
            max_writable_size_ -= bytes_transferred;
          }
        }

        written_data_.reserve(written_data_.size() + tmp_written_data.size());
        written_data_.insert(
              written_data_.end()
            , tmp_written_data.begin(), tmp_written_data.end());
      }

      io_service_.post(
          canard::detail::bind(std::move(handler), ec_, bytes_transferred));

      return result.get();
    }

    auto max_writable_size_per_write() const noexcept
      -> std::size_t
    {
      return max_writable_size_per_write_;
    }

    void max_writable_size_per_write(
        std::size_t const max_writable_size_per_write) noexcept
    {
      max_writable_size_per_write_ = max_writable_size_per_write;
    }

    auto error_code() const noexcept
      -> boost::system::error_code const&
    {
      return ec_;
    }

    void error_code(boost::system::error_code const& ec)
    {
      ec_ = ec;
    }

    void max_writable_size(
          std::size_t const max_writable_size
        , boost::system::error_code const& ec) noexcept
    {
      max_writable_size_ = max_writable_size;
      error_over_max_writable_size_ = ec;
    }

    auto written_data() const noexcept
      -> std::vector<CharT> const&
    {
      return written_data_;
    }

  private:
    boost::asio::io_service& io_service_;
    std::size_t max_writable_size_per_write_;
    boost::system::error_code ec_;
    std::size_t max_writable_size_;
    boost::system::error_code error_over_max_writable_size_;
    std::vector<CharT> written_data_;
  };

} // namespace canard_test

#endif // CANARD_ASIO_STUB_STREAM_HPP


text:
/*  Sirikata Network Utilities
 *  IOTimer.cpp
 *
 *  Copyright (c) 2009, Daniel Reiter Horn
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sirikata/core/util/Standard.hh>
#include <sirikata/core/network/IOTimer.hpp>
#include <sirikata/core/network/IOService.hpp>
#include <sirikata/core/network/IOStrandImpl.hpp>
#include <sirikata/core/util/Time.hpp>
#include <sirikata/core/network/Asio.hpp>

#include <boost/asio.hpp>
#include <boost/bind.hpp>

namespace Sirikata {
namespace Network {

class IOTimer::TimedOut {
public:
    static void timedOut(
            const boost::system::error_code &error,
            IOTimerWPtr wthis, uint64 tokenVal)
    {
        IOTimerPtr sharedThis (wthis.lock());
        if (!sharedThis) {
            return; // we've been deleted already.
        }
        if (error == boost::asio::error::operation_aborted) {
            return; // don't care if the timer was cancelled.
        }

        if (sharedThis->mStrand != NULL) sharedThis->chk.serializedEnter();
        IOTimer*st=&*sharedThis;

        //token only gets incremented if was canceled.  Therefore, if these two
        //are equal, means wasn't canceled.
        if (tokenVal == st->mCanceled)
            sharedThis->mFunc();
        if (sharedThis->mStrand != NULL) sharedThis->chk.serializedExit();
    }
};

IOTimer::IOTimer(IOService& io)
 : mTimer(new DeadlineTimer(io)),
   mStrand(NULL),
   mFunc(),
   mCanceled(0)
{
}

IOTimer::IOTimer(IOService& io, const IOCallback& cb)
 : mTimer(new DeadlineTimer(io)),
   mStrand(NULL),
   mFunc(),
   mCanceled(0)
{
    setCallback(cb);
}

IOTimer::IOTimer(IOStrand* ios)
 : mTimer(new DeadlineTimer(ios->service())),
   mStrand(ios),
   mFunc(),
   mCanceled(0)
{
}

IOTimer::IOTimer(IOStrand* ios, const IOCallback& cb)
 : mTimer(new DeadlineTimer(ios->service())),
   mStrand(ios),
   mFunc(),
   mCanceled(0)
{
    setCallback(cb);
}

IOTimerPtr IOTimer::create(IOService* io) {
    return IOTimerPtr(new IOTimer(*io));
}

IOTimerPtr IOTimer::create(IOService& io) {
    return IOTimerPtr(new IOTimer(io));
}

IOTimerPtr IOTimer::create(IOStrand* ios) {
    return IOTimerPtr(new IOTimer(ios));
}

IOTimerPtr IOTimer::create(IOStrand& ios) {
    return IOTimerPtr(new IOTimer(&ios));
}

IOTimerPtr IOTimer::create(IOService* io, const IOCallback& cb) {
    return IOTimerPtr(new IOTimer(*io, cb));
}

IOTimerPtr IOTimer::create(IOService& io, const IOCallback& cb) {
    return IOTimerPtr(new IOTimer(io, cb));
}

IOTimerPtr IOTimer::create(IOStrand* ios, const IOCallback& cb) {
    return IOTimerPtr(new IOTimer(ios, cb));
}

IOTimerPtr IOTimer::create(IOStrand& ios, const IOCallback& cb) {
    return IOTimerPtr(new IOTimer(&ios, cb));
}

IOTimer::~IOTimer() {
    if (mStrand != NULL) chk.serializedEnter();
    cancel();
    delete mTimer;
    if (mStrand != NULL) chk.serializedExit();
}

IOService IOTimer::service() const {
    return IOService(&mTimer->get_io_service());
}

void IOTimer::wait(const Duration &num_seconds) {
    mTimer->expires_from_now(boost::posix_time::microseconds(num_seconds.toMicroseconds()));
    IOTimerWPtr weakThisPtr(this->shared_from_this());
    if (mStrand == NULL) {
        mTimer->async_wait(
            boost::bind(
                &IOTimer::TimedOut::timedOut,
                boost::asio::placeholders::error,
                weakThisPtr,
                mCanceled.read()
            )
        );
    }
    else {
        mTimer->async_wait(
            mStrand->wrap(
                boost::bind(
                    &IOTimer::TimedOut::timedOut,
                    boost::asio::placeholders::error,
                    weakThisPtr,
                    mCanceled.read()
                )
            )
        );
    }
}

void IOTimer::wait(const Duration &num_seconds, const IOCallback& cb) {
    setCallback(cb);
    wait(num_seconds);
}

void IOTimer::setCallback(const IOCallback& cb) {
    mFunc = cb;
}

void IOTimer::cancel() {
    if (mStrand != NULL) chk.serializedEnter();
    mCanceled++;
    mTimer->cancel();
    if (mStrand != NULL) chk.serializedExit();
}
Duration IOTimer::expiresFromNow() {
    return Duration::microseconds(mTimer->expires_from_now().total_microseconds());
}
} // namespace Network
} // namespace Sirikata

max_stars_repo_name: pathorn/sirikata

max_issues_repo_name: pathorn/sirikata

max_forks_repo_name: pathorn/sirikata


text:
//
// Copyright RIME Developers
// Distributed under the BSD License
//
// 2011-11-02 GONG Chen <chen.sst@gmail.com>
//
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <rime/common.h>
#include <rime/resource.h>
#include <rime/service.h>
#include <rime/dict/db.h>

namespace rime {

// DbAccessor members

bool DbAccessor::MatchesPrefix(const string& key) {
  return boost::starts_with(key, prefix_);
}

// DbComponentBase

static const ResourceType kDbResourceType = {
  "db", "", ""
};

DbComponentBase::DbComponentBase()
    : db_resource_resolver_(
          Service::instance().CreateResourceResolver(kDbResourceType)) {}

DbComponentBase::~DbComponentBase() {}

string DbComponentBase::DbFilePath(const string& name,
                                   const string& extension) const {
  return db_resource_resolver_->ResolvePath(name + extension).string();
}

// Db members

Db::Db(const string& file_name, const string& name)
    : name_(name),
      file_name_(file_name) {}

bool Db::Exists() const {
  return boost::filesystem::exists(file_name());
}

bool Db::Remove() {
  if (loaded()) {
    LOG(ERROR) << "attempt to remove opened db '" << name_ << "'.";
    return false;
  }
  return boost::filesystem::remove(file_name());
}

bool Db::CreateMetadata() {
  LOG(INFO) << "creating metadata for db '" << name_ << "'.";
  return MetaUpdate("/db_name", name_) &&
      MetaUpdate("/rime_version", RIME_VERSION);
}

}  // namespace rime

max_stars_repo_name: mengzhisuoliu/librime

max_issues_repo_name: mengzhisuoliu/librime

max_forks_repo_name: mengzhisuoliu/librime