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

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <list>
#include <string>
#include <utility>

#include "../fpdfsdk/include/fpdf_dataavail.h"
#include "../fpdfsdk/include/fpdf_ext.h"
#include "../fpdfsdk/include/fpdfformfill.h"
#include "../fpdfsdk/include/fpdftext.h"
#include "../fpdfsdk/include/fpdfview.h"
#include "../core/include/fxcrt/fx_system.h"
#include "v8/include/v8.h"

#ifdef _WIN32
  #define snprintf _snprintf
#endif

enum OutputFormat {
  OUTPUT_NONE,
  OUTPUT_PPM,
#ifdef _WIN32
  OUTPUT_BMP,
  OUTPUT_EMF,
#endif
};

static void WritePpm(const char* pdf_name, int num, const void* buffer_void,
                     int stride, int width, int height) {
  const char* buffer = reinterpret_cast<const char*>(buffer_void);

  if (stride < 0 || width < 0 || height < 0)
    return;
  if (height > 0 && width > INT_MAX / height)
    return;
  int out_len = width * height;
  if (out_len > INT_MAX / 3)
    return;
  out_len *= 3;

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.ppm", pdf_name, num);
  FILE* fp = fopen(filename, "wb");
  if (!fp)
    return;
  fprintf(fp, "P6\n# PDF test render\n%d %d\n255\n", width, height);
  // Source data is B, G, R, unused.
  // Dest data is R, G, B.
  char* result = new char[out_len];
  if (result) {
    for (int h = 0; h < height; ++h) {
      const char* src_line = buffer + (stride * h);
      char* dest_line = result + (width * h * 3);
      for (int w = 0; w < width; ++w) {
        // R
        dest_line[w * 3] = src_line[(w * 4) + 2];
        // G
        dest_line[(w * 3) + 1] = src_line[(w * 4) + 1];
        // B
        dest_line[(w * 3) + 2] = src_line[w * 4];
      }
    }
    fwrite(result, out_len, 1, fp);
    delete [] result;
  }
  fclose(fp);
}

#ifdef _WIN32
static void WriteBmp(const char* pdf_name, int num, const void* buffer,
                     int stride, int width, int height) {
  if (stride < 0 || width < 0 || height < 0)
    return;
  if (height > 0 && width > INT_MAX / height)
    return;
  int out_len = stride * height;
  if (out_len > INT_MAX / 3)
    return;

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.bmp", pdf_name, num);
  FILE* fp = fopen(filename, "wb");
  if (!fp)
    return;

  BITMAPINFO bmi = {0};
  bmi.bmiHeader.biSize = sizeof(bmi) - sizeof(RGBQUAD);
  bmi.bmiHeader.biWidth = width;
  bmi.bmiHeader.biHeight = -height;  // top-down image
  bmi.bmiHeader.biPlanes = 1;
  bmi.bmiHeader.biBitCount = 32;
  bmi.bmiHeader.biCompression = BI_RGB;
  bmi.bmiHeader.biSizeImage = 0;

  BITMAPFILEHEADER file_header = {0};
  file_header.bfType = 0x4d42;
  file_header.bfSize = sizeof(file_header) + bmi.bmiHeader.biSize + out_len;
  file_header.bfOffBits = file_header.bfSize - out_len;

  fwrite(&file_header, sizeof(file_header), 1, fp);
  fwrite(&bmi, bmi.bmiHeader.biSize, 1, fp);
  fwrite(buffer, out_len, 1, fp);
  fclose(fp);
}

void WriteEmf(FPDF_PAGE page, const char* pdf_name, int num) {
  int width = static_cast<int>(FPDF_GetPageWidth(page));
  int height = static_cast<int>(FPDF_GetPageHeight(page));

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.emf", pdf_name, num);

  HDC dc = CreateEnhMetaFileA(NULL, filename, NULL, NULL);

  HRGN rgn = CreateRectRgn(0, 0, width, height);
  SelectClipRgn(dc, rgn);
  DeleteObject(rgn);

  SelectObject(dc, GetStockObject(NULL_PEN));
  SelectObject(dc, GetStockObject(WHITE_BRUSH));
  // If a PS_NULL pen is used, the dimensions of the rectangle are 1 pixel less.
  Rectangle(dc, 0, 0, width + 1, height + 1);

  FPDF_RenderPage(dc, page, 0, 0, width, height, 0,
                  FPDF_ANNOT | FPDF_PRINTING | FPDF_NO_CATCH);

  DeleteEnhMetaFile(CloseEnhMetaFile(dc));
}
#endif

int Form_Alert(IPDF_JSPLATFORM*, FPDF_WIDESTRING, FPDF_WIDESTRING, int, int) {
  printf("Form_Alert called.\n");
  return 0;
}

void Unsupported_Handler(UNSUPPORT_INFO*, int type) {
  std::string feature = "Unknown";
  switch (type) {
    case FPDF_UNSP_DOC_XFAFORM:
      feature = "XFA";
      break;
    case FPDF_UNSP_DOC_PORTABLECOLLECTION:
      feature = "Portfolios_Packages";
      break;
    case FPDF_UNSP_DOC_ATTACHMENT:
    case FPDF_UNSP_ANNOT_ATTACHMENT:
      feature = "Attachment";
      break;
    case FPDF_UNSP_DOC_SECURITY:
      feature = "Rights_Management";
      break;
    case FPDF_UNSP_DOC_SHAREDREVIEW:
      feature = "Shared_Review";
      break;
    case FPDF_UNSP_DOC_SHAREDFORM_ACROBAT:
    case FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM:
    case FPDF_UNSP_DOC_SHAREDFORM_EMAIL:
      feature = "Shared_Form";
      break;
    case FPDF_UNSP_ANNOT_3DANNOT:
      feature = "3D";
      break;
    case FPDF_UNSP_ANNOT_MOVIE:
      feature = "Movie";
      break;
    case FPDF_UNSP_ANNOT_SOUND:
      feature = "Sound";
      break;
    case FPDF_UNSP_ANNOT_SCREEN_MEDIA:
    case FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA:
      feature = "Screen";
      break;
    case FPDF_UNSP_ANNOT_SIG:
      feature = "Digital_Signature";
      break;
  }
  printf("Unsupported feature: %s.\n", feature.c_str());
}

bool ParseCommandLine(int argc, const char* argv[], OutputFormat* output_format,
                      std::list<const char*>* files) {
  *output_format = OUTPUT_NONE;
  files->clear();

  int cur_arg = 1;
  for (; cur_arg < argc; ++cur_arg) {
    if (strcmp(argv[cur_arg], "--ppm") == 0)
      *output_format = OUTPUT_PPM;
#ifdef _WIN32
    else if (strcmp(argv[cur_arg], "--emf") == 0)
      *output_format = OUTPUT_EMF;
    else if (strcmp(argv[cur_arg], "--bmp") == 0)
      *output_format = OUTPUT_BMP;
#endif
    else
      break;
  }

  if (cur_arg > 2)  // Multiple options.
    return false;

  if (cur_arg >= argc)  // No input files.
    return false;

  for (int i = cur_arg; i < argc; i++)
    files->push_back(argv[i]);

  return true;
}

class TestLoader {
 public:
  TestLoader(const char* pBuf, size_t len);

  const char* m_pBuf;
  size_t m_Len;
};

TestLoader::TestLoader(const char* pBuf, size_t len)
    : m_pBuf(pBuf), m_Len(len) {
}

int Get_Block(void* param, unsigned long pos, unsigned char* pBuf,
              unsigned long size) {
  TestLoader* pLoader = (TestLoader*) param;
  if (pos + size < pos || pos + size > pLoader->m_Len) return 0;
  memcpy(pBuf, pLoader->m_pBuf + pos, size);
  return 1;
}

bool Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
  return true;
}

void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {
}

void RenderPdf(const char* name, const char* pBuf, size_t len,
               OutputFormat format) {
  printf("Rendering PDF file %s.\n", name);

  IPDF_JSPLATFORM platform_callbacks;
  memset(&platform_callbacks, '\0', sizeof(platform_callbacks));
  platform_callbacks.version = 1;
  platform_callbacks.app_alert = Form_Alert;

  FPDF_FORMFILLINFO form_callbacks;
  memset(&form_callbacks, '\0', sizeof(form_callbacks));
  form_callbacks.version = 2;
  form_callbacks.m_pJsPlatform = &platform_callbacks;

  TestLoader loader(pBuf, len);

  FPDF_FILEACCESS file_access;
  memset(&file_access, '\0', sizeof(file_access));
  file_access.m_FileLen = static_cast<unsigned long>(len);
  file_access.m_GetBlock = Get_Block;
  file_access.m_Param = &loader;

  FX_FILEAVAIL file_avail;
  memset(&file_avail, '\0', sizeof(file_avail));
  file_avail.version = 1;
  file_avail.IsDataAvail = Is_Data_Avail;

  FX_DOWNLOADHINTS hints;
  memset(&hints, '\0', sizeof(hints));
  hints.version = 1;
  hints.AddSegment = Add_Segment;

  FPDF_DOCUMENT doc;
  FPDF_AVAIL pdf_avail = FPDFAvail_Create(&file_avail, &file_access);

  (void) FPDFAvail_IsDocAvail(pdf_avail, &hints);

  if (!FPDFAvail_IsLinearized(pdf_avail)) {
    printf("Non-linearized path...\n");
    doc = FPDF_LoadCustomDocument(&file_access, NULL);
  } else {
    printf("Linearized path...\n");
    doc = FPDFAvail_GetDocument(pdf_avail, NULL);
  }

  (void) FPDF_GetDocPermissions(doc);
  (void) FPDFAvail_IsFormAvail(pdf_avail, &hints);

  FPDF_FORMHANDLE form = FPDFDOC_InitFormFillEnvironment(doc, &form_callbacks);
  FPDF_LoadXFA(doc);
  FPDF_SetFormFieldHighlightColor(form, 0, 0xFFE4DD);
  FPDF_SetFormFieldHighlightAlpha(form, 100);

  int first_page = FPDFAvail_GetFirstPageNum(doc);
  (void) FPDFAvail_IsPageAvail(pdf_avail, first_page, &hints);

  int page_count = FPDF_GetPageCount(doc);
  for (int i = 0; i < page_count; ++i) {
    (void) FPDFAvail_IsPageAvail(pdf_avail, i, &hints);
  }

  FORM_DoDocumentJSAction(form);
  FORM_DoDocumentOpenAction(form);

  size_t rendered_pages = 0;
  size_t bad_pages = 0;
  for (int i = 0; i < page_count; ++i) {
    FPDF_PAGE page = FPDF_LoadPage(doc, i);
    if (!page) {
        bad_pages ++;
        continue;
    }
    FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
    FORM_OnAfterLoadPage(page, form);
    FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_OPEN);

    int width = static_cast<int>(FPDF_GetPageWidth(page));
    int height = static_cast<int>(FPDF_GetPageHeight(page));
    FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, 0);
    FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);

    FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);
    rendered_pages ++;

    FPDF_FFLDraw(form, bitmap, page, 0, 0, width, height, 0, 0);
    int stride = FPDFBitmap_GetStride(bitmap);
    const char* buffer =
        reinterpret_cast<const char*>(FPDFBitmap_GetBuffer(bitmap));

    switch (format) {
#ifdef _WIN32
      case OUTPUT_BMP:
        WriteBmp(name, i, buffer, stride, width, height);
        break;

      case OUTPUT_EMF:
        WriteEmf(page, name, i);
        break;
#endif
      case OUTPUT_PPM:
        WritePpm(name, i, buffer, stride, width, height);
        break;
      default:
        break;
    }

    FPDFBitmap_Destroy(bitmap);

    FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_CLOSE);
    FORM_OnBeforeClosePage(page, form);
    FPDFText_ClosePage(text_page);
    FPDF_ClosePage(page);
  }

  FORM_DoDocumentAAction(form, FPDFDOC_AACTION_WC);
  FPDF_CloseDocument(doc);
  FPDFDOC_ExitFormFillEnvironment(form);
  FPDFAvail_Destroy(pdf_avail);

  printf("Loaded, parsed and rendered %" PRIuS " pages.\n", rendered_pages);
  printf("Skipped %" PRIuS " bad pages.\n", bad_pages);
}

int main(int argc, const char* argv[]) {
  v8::V8::InitializeICU();
  OutputFormat format = OUTPUT_NONE;
  std::list<const char*> files;
  if (!ParseCommandLine(argc, argv, &format, &files)) {
    printf("Usage: pdfium_test [OPTION] [FILE]...\n");
    printf("--ppm    write page images <pdf-name>.<page-number>.ppm\n");
#ifdef _WIN32
    printf("--bmp    write page images <pdf-name>.<page-number>.bmp\n");
    printf("--emf    write page meta files <pdf-name>.<page-number>.emf\n");
#endif
    return 1;
  }

  FPDF_InitLibrary(NULL);

  UNSUPPORT_INFO unsuppored_info;
  memset(&unsuppored_info, '\0', sizeof(unsuppored_info));
  unsuppored_info.version = 1;
  unsuppored_info.FSDK_UnSupport_Handler = Unsupported_Handler;

  FSDK_SetUnSpObjProcessHandler(&unsuppored_info);

  while (!files.empty()) {
    const char* filename = files.front();
    files.pop_front();
    FILE* file = fopen(filename, "rb");
    if (!file) {
      fprintf(stderr, "Failed to open: %s\n", filename);
      continue;
    }
    (void) fseek(file, 0, SEEK_END);
    size_t len = ftell(file);
    (void) fseek(file, 0, SEEK_SET);
    char* pBuf = (char*) malloc(len);
    size_t ret = fread(pBuf, 1, len, file);
    (void) fclose(file);
    if (ret != len) {
      fprintf(stderr, "Failed to read: %s\n", filename);
    } else {
      RenderPdf(filename, pBuf, len, format);
    }
    free(pBuf);
  }

  FPDF_DestroyLibrary();

  return 0;
}
<commit_msg>Log message when XFA load fails<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <list>
#include <string>
#include <utility>

#include "../fpdfsdk/include/fpdf_dataavail.h"
#include "../fpdfsdk/include/fpdf_ext.h"
#include "../fpdfsdk/include/fpdfformfill.h"
#include "../fpdfsdk/include/fpdftext.h"
#include "../fpdfsdk/include/fpdfview.h"
#include "../core/include/fxcrt/fx_system.h"
#include "v8/include/v8.h"

#ifdef _WIN32
  #define snprintf _snprintf
#endif

enum OutputFormat {
  OUTPUT_NONE,
  OUTPUT_PPM,
#ifdef _WIN32
  OUTPUT_BMP,
  OUTPUT_EMF,
#endif
};

static void WritePpm(const char* pdf_name, int num, const void* buffer_void,
                     int stride, int width, int height) {
  const char* buffer = reinterpret_cast<const char*>(buffer_void);

  if (stride < 0 || width < 0 || height < 0)
    return;
  if (height > 0 && width > INT_MAX / height)
    return;
  int out_len = width * height;
  if (out_len > INT_MAX / 3)
    return;
  out_len *= 3;

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.ppm", pdf_name, num);
  FILE* fp = fopen(filename, "wb");
  if (!fp)
    return;
  fprintf(fp, "P6\n# PDF test render\n%d %d\n255\n", width, height);
  // Source data is B, G, R, unused.
  // Dest data is R, G, B.
  char* result = new char[out_len];
  if (result) {
    for (int h = 0; h < height; ++h) {
      const char* src_line = buffer + (stride * h);
      char* dest_line = result + (width * h * 3);
      for (int w = 0; w < width; ++w) {
        // R
        dest_line[w * 3] = src_line[(w * 4) + 2];
        // G
        dest_line[(w * 3) + 1] = src_line[(w * 4) + 1];
        // B
        dest_line[(w * 3) + 2] = src_line[w * 4];
      }
    }
    fwrite(result, out_len, 1, fp);
    delete [] result;
  }
  fclose(fp);
}

#ifdef _WIN32
static void WriteBmp(const char* pdf_name, int num, const void* buffer,
                     int stride, int width, int height) {
  if (stride < 0 || width < 0 || height < 0)
    return;
  if (height > 0 && width > INT_MAX / height)
    return;
  int out_len = stride * height;
  if (out_len > INT_MAX / 3)
    return;

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.bmp", pdf_name, num);
  FILE* fp = fopen(filename, "wb");
  if (!fp)
    return;

  BITMAPINFO bmi = {0};
  bmi.bmiHeader.biSize = sizeof(bmi) - sizeof(RGBQUAD);
  bmi.bmiHeader.biWidth = width;
  bmi.bmiHeader.biHeight = -height;  // top-down image
  bmi.bmiHeader.biPlanes = 1;
  bmi.bmiHeader.biBitCount = 32;
  bmi.bmiHeader.biCompression = BI_RGB;
  bmi.bmiHeader.biSizeImage = 0;

  BITMAPFILEHEADER file_header = {0};
  file_header.bfType = 0x4d42;
  file_header.bfSize = sizeof(file_header) + bmi.bmiHeader.biSize + out_len;
  file_header.bfOffBits = file_header.bfSize - out_len;

  fwrite(&file_header, sizeof(file_header), 1, fp);
  fwrite(&bmi, bmi.bmiHeader.biSize, 1, fp);
  fwrite(buffer, out_len, 1, fp);
  fclose(fp);
}

void WriteEmf(FPDF_PAGE page, const char* pdf_name, int num) {
  int width = static_cast<int>(FPDF_GetPageWidth(page));
  int height = static_cast<int>(FPDF_GetPageHeight(page));

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.emf", pdf_name, num);

  HDC dc = CreateEnhMetaFileA(NULL, filename, NULL, NULL);

  HRGN rgn = CreateRectRgn(0, 0, width, height);
  SelectClipRgn(dc, rgn);
  DeleteObject(rgn);

  SelectObject(dc, GetStockObject(NULL_PEN));
  SelectObject(dc, GetStockObject(WHITE_BRUSH));
  // If a PS_NULL pen is used, the dimensions of the rectangle are 1 pixel less.
  Rectangle(dc, 0, 0, width + 1, height + 1);

  FPDF_RenderPage(dc, page, 0, 0, width, height, 0,
                  FPDF_ANNOT | FPDF_PRINTING | FPDF_NO_CATCH);

  DeleteEnhMetaFile(CloseEnhMetaFile(dc));
}
#endif

int Form_Alert(IPDF_JSPLATFORM*, FPDF_WIDESTRING, FPDF_WIDESTRING, int, int) {
  printf("Form_Alert called.\n");
  return 0;
}

void Unsupported_Handler(UNSUPPORT_INFO*, int type) {
  std::string feature = "Unknown";
  switch (type) {
    case FPDF_UNSP_DOC_XFAFORM:
      feature = "XFA";
      break;
    case FPDF_UNSP_DOC_PORTABLECOLLECTION:
      feature = "Portfolios_Packages";
      break;
    case FPDF_UNSP_DOC_ATTACHMENT:
    case FPDF_UNSP_ANNOT_ATTACHMENT:
      feature = "Attachment";
      break;
    case FPDF_UNSP_DOC_SECURITY:
      feature = "Rights_Management";
      break;
    case FPDF_UNSP_DOC_SHAREDREVIEW:
      feature = "Shared_Review";
      break;
    case FPDF_UNSP_DOC_SHAREDFORM_ACROBAT:
    case FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM:
    case FPDF_UNSP_DOC_SHAREDFORM_EMAIL:
      feature = "Shared_Form";
      break;
    case FPDF_UNSP_ANNOT_3DANNOT:
      feature = "3D";
      break;
    case FPDF_UNSP_ANNOT_MOVIE:
      feature = "Movie";
      break;
    case FPDF_UNSP_ANNOT_SOUND:
      feature = "Sound";
      break;
    case FPDF_UNSP_ANNOT_SCREEN_MEDIA:
    case FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA:
      feature = "Screen";
      break;
    case FPDF_UNSP_ANNOT_SIG:
      feature = "Digital_Signature";
      break;
  }
  printf("Unsupported feature: %s.\n", feature.c_str());
}

bool ParseCommandLine(int argc, const char* argv[], OutputFormat* output_format,
                      std::list<const char*>* files) {
  *output_format = OUTPUT_NONE;
  files->clear();

  int cur_arg = 1;
  for (; cur_arg < argc; ++cur_arg) {
    if (strcmp(argv[cur_arg], "--ppm") == 0)
      *output_format = OUTPUT_PPM;
#ifdef _WIN32
    else if (strcmp(argv[cur_arg], "--emf") == 0)
      *output_format = OUTPUT_EMF;
    else if (strcmp(argv[cur_arg], "--bmp") == 0)
      *output_format = OUTPUT_BMP;
#endif
    else
      break;
  }

  if (cur_arg > 2)  // Multiple options.
    return false;

  if (cur_arg >= argc)  // No input files.
    return false;

  for (int i = cur_arg; i < argc; i++)
    files->push_back(argv[i]);

  return true;
}

class TestLoader {
 public:
  TestLoader(const char* pBuf, size_t len);

  const char* m_pBuf;
  size_t m_Len;
};

TestLoader::TestLoader(const char* pBuf, size_t len)
    : m_pBuf(pBuf), m_Len(len) {
}

int Get_Block(void* param, unsigned long pos, unsigned char* pBuf,
              unsigned long size) {
  TestLoader* pLoader = (TestLoader*) param;
  if (pos + size < pos || pos + size > pLoader->m_Len) return 0;
  memcpy(pBuf, pLoader->m_pBuf + pos, size);
  return 1;
}

bool Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
  return true;
}

void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {
}

void RenderPdf(const char* name, const char* pBuf, size_t len,
               OutputFormat format) {
  printf("Rendering PDF file %s.\n", name);

  IPDF_JSPLATFORM platform_callbacks;
  memset(&platform_callbacks, '\0', sizeof(platform_callbacks));
  platform_callbacks.version = 1;
  platform_callbacks.app_alert = Form_Alert;

  FPDF_FORMFILLINFO form_callbacks;
  memset(&form_callbacks, '\0', sizeof(form_callbacks));
  form_callbacks.version = 2;
  form_callbacks.m_pJsPlatform = &platform_callbacks;

  TestLoader loader(pBuf, len);

  FPDF_FILEACCESS file_access;
  memset(&file_access, '\0', sizeof(file_access));
  file_access.m_FileLen = static_cast<unsigned long>(len);
  file_access.m_GetBlock = Get_Block;
  file_access.m_Param = &loader;

  FX_FILEAVAIL file_avail;
  memset(&file_avail, '\0', sizeof(file_avail));
  file_avail.version = 1;
  file_avail.IsDataAvail = Is_Data_Avail;

  FX_DOWNLOADHINTS hints;
  memset(&hints, '\0', sizeof(hints));
  hints.version = 1;
  hints.AddSegment = Add_Segment;

  FPDF_DOCUMENT doc;
  FPDF_AVAIL pdf_avail = FPDFAvail_Create(&file_avail, &file_access);

  (void) FPDFAvail_IsDocAvail(pdf_avail, &hints);

  if (!FPDFAvail_IsLinearized(pdf_avail)) {
    printf("Non-linearized path...\n");
    doc = FPDF_LoadCustomDocument(&file_access, NULL);
  } else {
    printf("Linearized path...\n");
    doc = FPDFAvail_GetDocument(pdf_avail, NULL);
  }

  (void) FPDF_GetDocPermissions(doc);
  (void) FPDFAvail_IsFormAvail(pdf_avail, &hints);

  FPDF_FORMHANDLE form = FPDFDOC_InitFormFillEnvironment(doc, &form_callbacks);
  if (!FPDF_LoadXFA(doc)) {
    printf("LoadXFA unsuccessful, continuing anyway.\n");
  }
  FPDF_SetFormFieldHighlightColor(form, 0, 0xFFE4DD);
  FPDF_SetFormFieldHighlightAlpha(form, 100);

  int first_page = FPDFAvail_GetFirstPageNum(doc);
  (void) FPDFAvail_IsPageAvail(pdf_avail, first_page, &hints);

  int page_count = FPDF_GetPageCount(doc);
  for (int i = 0; i < page_count; ++i) {
    (void) FPDFAvail_IsPageAvail(pdf_avail, i, &hints);
  }

  FORM_DoDocumentJSAction(form);
  FORM_DoDocumentOpenAction(form);

  size_t rendered_pages = 0;
  size_t bad_pages = 0;
  for (int i = 0; i < page_count; ++i) {
    FPDF_PAGE page = FPDF_LoadPage(doc, i);
    if (!page) {
        bad_pages ++;
        continue;
    }
    FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
    FORM_OnAfterLoadPage(page, form);
    FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_OPEN);

    int width = static_cast<int>(FPDF_GetPageWidth(page));
    int height = static_cast<int>(FPDF_GetPageHeight(page));
    FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, 0);
    FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);

    FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);
    rendered_pages ++;

    FPDF_FFLDraw(form, bitmap, page, 0, 0, width, height, 0, 0);
    int stride = FPDFBitmap_GetStride(bitmap);
    const char* buffer =
        reinterpret_cast<const char*>(FPDFBitmap_GetBuffer(bitmap));

    switch (format) {
#ifdef _WIN32
      case OUTPUT_BMP:
        WriteBmp(name, i, buffer, stride, width, height);
        break;

      case OUTPUT_EMF:
        WriteEmf(page, name, i);
        break;
#endif
      case OUTPUT_PPM:
        WritePpm(name, i, buffer, stride, width, height);
        break;
      default:
        break;
    }

    FPDFBitmap_Destroy(bitmap);

    FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_CLOSE);
    FORM_OnBeforeClosePage(page, form);
    FPDFText_ClosePage(text_page);
    FPDF_ClosePage(page);
  }

  FORM_DoDocumentAAction(form, FPDFDOC_AACTION_WC);
  FPDF_CloseDocument(doc);
  FPDFDOC_ExitFormFillEnvironment(form);
  FPDFAvail_Destroy(pdf_avail);

  printf("Loaded, parsed and rendered %" PRIuS " pages.\n", rendered_pages);
  printf("Skipped %" PRIuS " bad pages.\n", bad_pages);
}

int main(int argc, const char* argv[]) {
  v8::V8::InitializeICU();
  OutputFormat format = OUTPUT_NONE;
  std::list<const char*> files;
  if (!ParseCommandLine(argc, argv, &format, &files)) {
    printf("Usage: pdfium_test [OPTION] [FILE]...\n");
    printf("--ppm    write page images <pdf-name>.<page-number>.ppm\n");
#ifdef _WIN32
    printf("--bmp    write page images <pdf-name>.<page-number>.bmp\n");
    printf("--emf    write page meta files <pdf-name>.<page-number>.emf\n");
#endif
    return 1;
  }

  FPDF_InitLibrary(NULL);

  UNSUPPORT_INFO unsuppored_info;
  memset(&unsuppored_info, '\0', sizeof(unsuppored_info));
  unsuppored_info.version = 1;
  unsuppored_info.FSDK_UnSupport_Handler = Unsupported_Handler;

  FSDK_SetUnSpObjProcessHandler(&unsuppored_info);

  while (!files.empty()) {
    const char* filename = files.front();
    files.pop_front();
    FILE* file = fopen(filename, "rb");
    if (!file) {
      fprintf(stderr, "Failed to open: %s\n", filename);
      continue;
    }
    (void) fseek(file, 0, SEEK_END);
    size_t len = ftell(file);
    (void) fseek(file, 0, SEEK_SET);
    char* pBuf = (char*) malloc(len);
    size_t ret = fread(pBuf, 1, len, file);
    (void) fclose(file);
    if (ret != len) {
      fprintf(stderr, "Failed to read: %s\n", filename);
    } else {
      RenderPdf(filename, pBuf, len, format);
    }
    free(pBuf);
  }

  FPDF_DestroyLibrary();

  return 0;
}
<|endoftext|>


<commit_before>/*
    $Id$

     Requires the Qt and KDE widget libraries, available at no cost at
     http://www.trolltech.com and http://www.kde.org respectively

     Copyright (C) 2001 Cornelius Schumacher <schumacher@kde.org>

     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

     -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

     This file implements a class for displaying a dialog box for
     adding or editing calendar filters.
*/

#include <qlayout.h>
#include <qpushbutton.h>
#include <qcombobox.h>
#include <qinputdialog.h>
#include <qcheckbox.h>

#include <kdebug.h>
#include <klocale.h>

#include "koprefs.h"
#include "filteredit_base.h"

#include "filtereditdialog.h"
#include "filtereditdialog.moc"

FilterEditDialog::FilterEditDialog(QList<CalFilter> *filters,QWidget *parent,
                                   const char *name) :
  KDialogBase(parent,name,false,i18n("Edit Calendar Filters"),
              Ok|Apply|Cancel)
{
  mFilters = filters;

  QWidget *mainWidget = new QWidget(this);
  setMainWidget(mainWidget);

  mSelectionCombo = new QComboBox(mainWidget);
  connect(mSelectionCombo,SIGNAL(activated(int)),SLOT(filterSelected()));

  QPushButton *addButton = new QPushButton(i18n("Add Filter"),mainWidget);
  connect(addButton,SIGNAL(clicked()),SLOT(slotAdd()));

  mEditor = new FilterEdit_base(mainWidget);

  QGridLayout *topLayout = new QGridLayout(mainWidget,2,2);
  topLayout->setSpacing(spacingHint());
  topLayout->addWidget(mSelectionCombo,0,0);
  topLayout->addWidget(addButton,0,1);
  topLayout->addMultiCellWidget(mEditor,1,1,0,1);

  // Clicking cancel exits the dialog without saving
  connect(this,SIGNAL(cancelClicked()),SLOT(reject()));

  updateFilterList();
}

FilterEditDialog::~FilterEditDialog()
{
}

void FilterEditDialog::updateFilterList()
{
  mSelectionCombo->clear();

  CalFilter *filter = mFilters->first();
  while(filter) {
    mSelectionCombo->insertItem(filter->name());
    filter = mFilters->next();
  }

  CalFilter *f = mFilters->at(mSelectionCombo->currentItem());
  readFilter(f);
}

void FilterEditDialog::slotDefault()
{
}

void FilterEditDialog::slotApply()
{
  CalFilter *f = mFilters->at(mSelectionCombo->currentItem());
  writeFilter(f);
  emit filterChanged();
}

void FilterEditDialog::slotOk()
{
  CalFilter *f = mFilters->at(mSelectionCombo->currentItem());
  writeFilter(f);
  emit filterChanged();
  accept();
}

void FilterEditDialog::slotAdd()
{
  QString filterName = QInputDialog::getText(i18n("Add Filter"), i18n("Enter Filter Name"));
  if (!filterName.isEmpty()) {
    mFilters->append(new CalFilter(filterName));
    updateFilterList();
  }
}

void FilterEditDialog::filterSelected()
{
  CalFilter *f = mFilters->at(mSelectionCombo->currentItem());
  kdDebug() << "Selected filter " << f->name() << endl;
  readFilter(f);
}

void FilterEditDialog::readFilter(CalFilter *filter)
{
  int in = filter->inclusionCriteria();

  mEditor->mInRecurringCheck->setChecked(in & CalFilter::Recurring);
  mEditor->mInFloatingCheck->setChecked(in & CalFilter::Floating);

  int ex = filter->exclusionCriteria();

  mEditor->mExRecurringCheck->setChecked(ex & CalFilter::Recurring);
  mEditor->mExFloatingCheck->setChecked(ex & CalFilter::Floating);
}

void FilterEditDialog::writeFilter(CalFilter *filter)
{
  int in = 0;
  if (mEditor->mInRecurringCheck->isChecked()) in |= CalFilter::Recurring;
  if (mEditor->mInFloatingCheck->isChecked()) in |= CalFilter::Floating;
  filter->setInclusionCriteria(in);

  int ex = 0;
  if (mEditor->mExRecurringCheck->isChecked()) ex |= CalFilter::Recurring;
  if (mEditor->mExFloatingCheck->isChecked()) ex |= CalFilter::Floating;
  filter->setExclusionCriteria(ex);
}
<commit_msg>Fixed crash.<commit_after>/*
    $Id$

     Requires the Qt and KDE widget libraries, available at no cost at
     http://www.trolltech.com and http://www.kde.org respectively

     Copyright (C) 2001 Cornelius Schumacher <schumacher@kde.org>

     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

     -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

     This file implements a class for displaying a dialog box for
     adding or editing calendar filters.
*/

#include <qlayout.h>
#include <qpushbutton.h>
#include <qcombobox.h>
#include <qinputdialog.h>
#include <qcheckbox.h>

#include <kdebug.h>
#include <klocale.h>

#include "koprefs.h"
#include "filteredit_base.h"

#include "filtereditdialog.h"
#include "filtereditdialog.moc"

FilterEditDialog::FilterEditDialog(QList<CalFilter> *filters,QWidget *parent,
                                   const char *name) :
  KDialogBase(parent,name,false,i18n("Edit Calendar Filters"),
              Ok|Apply|Cancel)
{
  mFilters = filters;

  QWidget *mainWidget = new QWidget(this);
  setMainWidget(mainWidget);

  mSelectionCombo = new QComboBox(mainWidget);
  connect(mSelectionCombo,SIGNAL(activated(int)),SLOT(filterSelected()));

  QPushButton *addButton = new QPushButton(i18n("Add Filter"),mainWidget);
  connect(addButton,SIGNAL(clicked()),SLOT(slotAdd()));

  mEditor = new FilterEdit_base(mainWidget);

  QGridLayout *topLayout = new QGridLayout(mainWidget,2,2);
  topLayout->setSpacing(spacingHint());
  topLayout->addWidget(mSelectionCombo,0,0);
  topLayout->addWidget(addButton,0,1);
  topLayout->addMultiCellWidget(mEditor,1,1,0,1);

  // Clicking cancel exits the dialog without saving
  connect(this,SIGNAL(cancelClicked()),SLOT(reject()));

  updateFilterList();
}

FilterEditDialog::~FilterEditDialog()
{
}

void FilterEditDialog::updateFilterList()
{
  mSelectionCombo->clear();

  CalFilter *filter = mFilters->first();
  while(filter) {
    mSelectionCombo->insertItem(filter->name());
    filter = mFilters->next();
  }

  CalFilter *f = mFilters->at(mSelectionCombo->currentItem());
  if (f) readFilter(f);
}

void FilterEditDialog::slotDefault()
{
}

void FilterEditDialog::slotApply()
{
  CalFilter *f = mFilters->at(mSelectionCombo->currentItem());
  writeFilter(f);
  emit filterChanged();
}

void FilterEditDialog::slotOk()
{
  CalFilter *f = mFilters->at(mSelectionCombo->currentItem());
  writeFilter(f);
  emit filterChanged();
  accept();
}

void FilterEditDialog::slotAdd()
{
  QString filterName = QInputDialog::getText(i18n("Add Filter"), i18n("Enter Filter Name"));
  if (!filterName.isEmpty()) {
    mFilters->append(new CalFilter(filterName));
    updateFilterList();
  }
}

void FilterEditDialog::filterSelected()
{
  CalFilter *f = mFilters->at(mSelectionCombo->currentItem());
  kdDebug() << "Selected filter " << f->name() << endl;
  if (f) readFilter(f);
}

void FilterEditDialog::readFilter(CalFilter *filter)
{
  int in = filter->inclusionCriteria();

  mEditor->mInRecurringCheck->setChecked(in & CalFilter::Recurring);
  mEditor->mInFloatingCheck->setChecked(in & CalFilter::Floating);

  int ex = filter->exclusionCriteria();

  mEditor->mExRecurringCheck->setChecked(ex & CalFilter::Recurring);
  mEditor->mExFloatingCheck->setChecked(ex & CalFilter::Floating);
}

void FilterEditDialog::writeFilter(CalFilter *filter)
{
  int in = 0;
  if (mEditor->mInRecurringCheck->isChecked()) in |= CalFilter::Recurring;
  if (mEditor->mInFloatingCheck->isChecked()) in |= CalFilter::Floating;
  filter->setInclusionCriteria(in);

  int ex = 0;
  if (mEditor->mExRecurringCheck->isChecked()) ex |= CalFilter::Recurring;
  if (mEditor->mExFloatingCheck->isChecked()) ex |= CalFilter::Floating;
  filter->setExclusionCriteria(ex);
}
<|endoftext|>


<commit_before>
#pragma once

#include <list>

#include "gmock/gmock.h"
#include "ksp_plugin/vessel.hpp"

namespace principia {
namespace ksp_plugin {
namespace internal_vessel {

class MockVessel : public Vessel {
 public:
  MockVessel() : Vessel() {}

  MOCK_CONST_METHOD0(body, not_null<MasslessBody const*>());

  MOCK_CONST_METHOD0(parent, not_null<Celestial const*>());
  MOCK_METHOD1(set_parent, void(not_null<Celestial const*> parent));

  MOCK_CONST_METHOD0(prediction, DiscreteTrajectory<Barycentric> const&());

  MOCK_CONST_METHOD0(flight_plan, FlightPlan&());
  MOCK_CONST_METHOD0(has_flight_plan, bool());

  MOCK_METHOD1(ForgetBefore, void(Instant const& time));

  MOCK_METHOD3(CreateFlightPlan,
               void(Instant const& final_time,
                    Mass const& initial_mass,
                    Ephemeris<Barycentric>::AdaptiveStepParameters const&
                        adaptive_parameters));

  MOCK_METHOD0(DeleteFlightPlan, void());

  MOCK_METHOD1(UpdatePrediction, void(Instant const& last_time));

  MOCK_CONST_METHOD0(psychohistory, DiscreteTrajectory<Barycentric> const&());
  MOCK_CONST_METHOD0(psychohistory_is_authoritative, bool());

  MOCK_CONST_METHOD1(WriteToMessage,
                     void(not_null<serialization::Vessel*> message));
};

}  // namespace internal_vessel

using internal_vessel::MockVessel;

}  // namespace ksp_plugin
}  // namespace principia
<commit_msg>Proper mocking.<commit_after>
#pragma once

#include <list>

#include "gmock/gmock.h"
#include "ksp_plugin/vessel.hpp"

namespace principia {
namespace ksp_plugin {
namespace internal_vessel {

class MockVessel : public Vessel {
 public:
  MockVessel() : Vessel() {}

  MOCK_CONST_METHOD0(body, not_null<MasslessBody const*>());

  MOCK_CONST_METHOD0(parent, not_null<Celestial const*>());
  MOCK_METHOD1(set_parent, void(not_null<Celestial const*> parent));

  MOCK_CONST_METHOD0(prediction, DiscreteTrajectory<Barycentric> const&());

  MOCK_CONST_METHOD0(flight_plan, FlightPlan&());
  MOCK_CONST_METHOD0(has_flight_plan, bool());

  MOCK_METHOD1(ForgetBefore, void(Instant const& time));

  MOCK_METHOD3(CreateFlightPlan,
               void(Instant const& final_time,
                    Mass const& initial_mass,
                    Ephemeris<Barycentric>::AdaptiveStepParameters const&
                        adaptive_parameters));

  MOCK_METHOD0(DeleteFlightPlan, void());

  MOCK_METHOD1(FlowPrediction, void(Instant const& last_time));

  MOCK_CONST_METHOD0(psychohistory, DiscreteTrajectory<Barycentric> const&());
  MOCK_CONST_METHOD0(psychohistory_is_authoritative, bool());

  MOCK_CONST_METHOD1(WriteToMessage,
                     void(not_null<serialization::Vessel*> message));
};

}  // namespace internal_vessel

using internal_vessel::MockVessel;

}  // namespace ksp_plugin
}  // namespace principia
<|endoftext|>


<commit_before>///
/// @file  generate.cpp
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <generate.hpp>
#include <imath.hpp>

#include <stdint.h>
#include <algorithm>
#include <limits>
#include <vector>

using namespace std;

namespace primecount {

/// Generate a vector with Möbius function values.
/// This implementation is based on code by Rick Sladkey:
/// https://mathoverflow.net/q/99545
///
vector<int32_t> generate_moebius(int64_t max)
{
  vector<int32_t> mu(max + 1, 1);

  for (int32_t i = 2; i * i <= max; i++)
  {
    if (mu[i] == 1)
    {
      for (int32_t j = i; j <= max; j += i)
        mu[j] *= -i;
      for (int32_t j = i * i; j <= max; j += i * i)
        mu[j] = 0;
    }
  }

  for (int32_t i = 2; i <= max; i++)
  {
    if (mu[i] == i)
      mu[i] = 1;
    else if (mu[i] == -i)
      mu[i] = -1;
    else if (mu[i] < 0)
      mu[i] = 1;
    else if (mu[i] > 0)
      mu[i] = -1;
  }

  return mu;
}

/// Generate a vector with the least prime factors
/// of the integers <= max
///
vector<int32_t> generate_lpf(int64_t max)
{
  vector<int32_t> lpf(max + 1, 1);

  // phi(x / 1, c) contributes to the sum in the
  // Lagarias-Miller-Odlyzko prime counting algorithm,
  // thus set lpf[1] = MAX (normally lpf[1] = 1)
  if (lpf.size() > 1)
    lpf[1] = numeric_limits<int32_t>::max();

  for (int32_t i = 2; i * i <= max; i++)
    if (lpf[i] == 1)
      for (int32_t j = i * 2; j <= max; j += i)
        if (lpf[j] == 1)
          lpf[j] = i;

  for (int32_t i = 2; i <= max; i++)
    if (lpf[i] == 1)
      lpf[i] = i;

  return lpf;
}

/// Generate a vector with the prime counts <= max
/// using the sieve of Eratosthenes
///
vector<int32_t> generate_pi(int64_t max)
{
  int64_t size = max + 1;
  vector<char> sieve(size, 1);

  for (int64_t i = 2; i * i <= max; i++)
    if (sieve[i])
      for (int64_t j = i * i; j <= max; j += i)
        sieve[j] = 0;

  vector<int32_t> pi(size, 0);
  int32_t pix = 0;

  for (int64_t x = 2; x <= max; x++)
  {
    pix += sieve[x];
    pi[x] = pix;
  }

  return pi;
}

} // namespace
<commit_msg>Remove unused headers<commit_after>///
/// @file  generate.cpp
///
/// Copyright (C) 2018 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <generate.hpp>

#include <stdint.h>
#include <limits>
#include <vector>

using namespace std;

namespace primecount {

/// Generate a vector with Möbius function values.
/// This implementation is based on code by Rick Sladkey:
/// https://mathoverflow.net/q/99545
///
vector<int32_t> generate_moebius(int64_t max)
{
  vector<int32_t> mu(max + 1, 1);

  for (int32_t i = 2; i * i <= max; i++)
  {
    if (mu[i] == 1)
    {
      for (int32_t j = i; j <= max; j += i)
        mu[j] *= -i;
      for (int32_t j = i * i; j <= max; j += i * i)
        mu[j] = 0;
    }
  }

  for (int32_t i = 2; i <= max; i++)
  {
    if (mu[i] == i)
      mu[i] = 1;
    else if (mu[i] == -i)
      mu[i] = -1;
    else if (mu[i] < 0)
      mu[i] = 1;
    else if (mu[i] > 0)
      mu[i] = -1;
  }

  return mu;
}

/// Generate a vector with the least prime factors
/// of the integers <= max
///
vector<int32_t> generate_lpf(int64_t max)
{
  vector<int32_t> lpf(max + 1, 1);

  // phi(x / 1, c) contributes to the sum in the
  // Lagarias-Miller-Odlyzko prime counting algorithm,
  // thus set lpf[1] = MAX (normally lpf[1] = 1)
  if (lpf.size() > 1)
    lpf[1] = numeric_limits<int32_t>::max();

  for (int32_t i = 2; i * i <= max; i++)
    if (lpf[i] == 1)
      for (int32_t j = i * 2; j <= max; j += i)
        if (lpf[j] == 1)
          lpf[j] = i;

  for (int32_t i = 2; i <= max; i++)
    if (lpf[i] == 1)
      lpf[i] = i;

  return lpf;
}

/// Generate a vector with the prime counts <= max
/// using the sieve of Eratosthenes
///
vector<int32_t> generate_pi(int64_t max)
{
  int64_t size = max + 1;
  vector<char> sieve(size, 1);

  for (int64_t i = 2; i * i <= max; i++)
    if (sieve[i])
      for (int64_t j = i * i; j <= max; j += i)
        sieve[j] = 0;

  vector<int32_t> pi(size, 0);
  int32_t pix = 0;

  for (int64_t x = 2; x <= max; x++)
  {
    pix += sieve[x];
    pi[x] = pix;
  }

  return pi;
}

} // namespace
<|endoftext|>


<commit_before>
#include "ksp_plugin/vessel.hpp"

#include <limits>

#include "astronomy/epoch.hpp"
#include "base/not_null.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ksp_plugin/celestial.hpp"
#include "physics/massive_body.hpp"
#include "physics/mock_ephemeris.hpp"
#include "quantities/si.hpp"
#include "testing_utilities/almost_equals.hpp"
#include "testing_utilities/componentwise.hpp"

namespace principia {
namespace ksp_plugin {
namespace internal_vessel {

using base::make_not_null_unique;
using geometry::Displacement;
using geometry::Position;
using geometry::Velocity;
using physics::MassiveBody;
using physics::MockEphemeris;
using quantities::si::Kilogram;
using quantities::si::Metre;
using quantities::si::Second;
using testing_utilities::AlmostEquals;
using testing_utilities::Componentwise;
using ::testing::DoAll;
using ::testing::ElementsAre;
using ::testing::Return;
using ::testing::_;

class VesselTest : public testing::Test {
 protected:
  VesselTest()
      : body_(MassiveBody::Parameters(1 * Kilogram)),
        celestial_(&body_),
        vessel_(&celestial_, &ephemeris_, DefaultPredictionParameters()) {
    auto p1 = make_not_null_unique<Part>(part_id1_,
                                         mass1_,
                                         p1_dof_,
                                         /*deletion_callback=*/nullptr);
    auto p2 = make_not_null_unique<Part>(part_id2_,
                                         mass2_,
                                         p2_dof_,
                                         /*deletion_callback=*/nullptr);
    p1_ = p1.get();
    p2_ = p2.get();
    vessel_.AddPart(std::move(p1));
    vessel_.AddPart(std::move(p2));
  }

  MockEphemeris<Barycentric> ephemeris_;
  MassiveBody const body_;
  Celestial const celestial_;
  PartId const part_id1_ = 111;
  PartId const part_id2_ = 222;
  Mass const mass1_ = 1 * Kilogram;
  Mass const mass2_ = 2 * Kilogram;

  // Centre of mass of |p1_| and |p2_| in |Barycentric|, in SI units:
  //   {13 / 3, 4, 11 / 3} {130 / 3, 40, 110 / 3}
  DegreesOfFreedom<Barycentric> const p1_dof_ = DegreesOfFreedom<Barycentric>(
      Barycentric::origin +
          Displacement<Barycentric>({1 * Metre, 2 * Metre, 3 * Metre}),
      Velocity<Barycentric>(
          {10 * Metre / Second, 20 * Metre / Second, 30 * Metre / Second}));
  DegreesOfFreedom<Barycentric> const p2_dof_ = DegreesOfFreedom<Barycentric>(
      Barycentric::origin +
          Displacement<Barycentric>({6 * Metre, 5 * Metre, 4 * Metre}),
      Velocity<Barycentric>(
          {60 * Metre / Second, 50 * Metre / Second, 40 * Metre / Second}));

  Part* p1_;
  Part* p2_;
  Vessel vessel_;
};

TEST_F(VesselTest, Parent) {
  Celestial other_celestial(&body_);
  EXPECT_EQ(celestial_, vessel_.parent());
  vessel_.set_parent(&other_celestial);
  EXPECT_EQ(&other_celestial, vessel_.parent());
}

TEST_F(VesselTest, KeepAndFreeParts) {
  std::set<PartId> remaining_part_ids;
  vessel_.ForAllParts([&remaining_part_ids](Part const& part) {
    remaining_part_ids.insert(part.part_id());
  });
  EXPECT_THAT(remaining_part_ids, ElementsAre(part_id1_, part_id2_));
  EXPECT_EQ(part_id1_, vessel_.part(part_id1_));
  EXPECT_EQ(part_id2_, vessel_.part(part_id2_));

  vessel_.KeepPart(part_id2_);
  vessel_.FreeParts();
  vessel_.ForAllParts([&remaining_part_ids](Part const& part) {
    remaining_part_ids.insert(part.part_id());
  });
  EXPECT_THAT(remaining_part_ids, ElementsAre(part_id1_));
  EXPECT_EQ(part_id1_, vessel_.part(part_id1_));
}

TEST_F(VesselTest, PreparePsychohistory) {
  EXPECT_TRUE(vessel_.psychohistory().Empty());
  vessel_.PreparePsychohistory(astronomy::J2000 + 1 * Second);
  EXPECT_EQ(1, vessel_.psychohistory().Size());
  EXPECT_EQ(astronomy::J2000 + 1 * Second,
            vessel_.psychohistory().End().time());
  EXPECT_THAT(
      vessel_.psychohistory().last().degrees_of_freedom(),
      Componentwise(AlmostEquals(Barycentric::origin +
                                      Displacement<Barycentric>(
                                          {13.0 / 3.0 * Metre,
                                          4.0 * Metre,
                                          11.0 / 3.0 * Metre}), 0),
                    AlmostEquals(Velocity<Barycentric>(
                                      {130.0 / 3.0 * Metre / Second,
                                      40.0 * Metre / Second,
                                      110.0 / 3.0 * Metre / Second}), 0)));
}

TEST_F(VesselTest, AdvanceTime) {
  vessel_.PreparePsychohistory(astronomy::J2000);

  p1_->tail().Append(
      astronomy::J2000 + 0.5 * Second,
      DegreesOfFreedom<Barycentric>(
          Barycentric::origin + Displacement<Barycentric>(
                                    {1.1 * Metre, 2.1 * Metre, 3.1 * Metre}),
          Velocity<Barycentric>({10.1 * Metre / Second,
                                 20.1 * Metre / Second,
                                 30.1 * Metre / Second})));
  p1_->tail().Append(
      astronomy::J2000 + 1.0 * Second,
      DegreesOfFreedom<Barycentric>(
          Barycentric::origin + Displacement<Barycentric>(
                                    {1.2 * Metre, 2.2 * Metre, 3.2 * Metre}),
          Velocity<Barycentric>({10.2 * Metre / Second,
                                 20.2 * Metre / Second,
                                 30.2 * Metre / Second})));
  p2_->tail().Append(
      astronomy::J2000 + 0.5 * Second,
      DegreesOfFreedom<Barycentric>(
          Barycentric::origin + Displacement<Barycentric>(
                                    {6.1 * Metre, 5.1 * Metre, 4.1 * Metre}),
          Velocity<Barycentric>({60.1 * Metre / Second,
                                 50.1 * Metre / Second,
                                 40.1 * Metre / Second})));
  p2_->tail().Append(
      astronomy::J2000 + 1.0 * Second,
      DegreesOfFreedom<Barycentric>(
          Barycentric::origin + Displacement<Barycentric>(
                                    {6.2 * Metre, 5.2 * Metre, 4.2 * Metre}),
          Velocity<Barycentric>({60.2 * Metre / Second,
                                 50.2 * Metre / Second,
                                 40.2 * Metre / Second})));

  vessel_.AdvanceTime();

  EXPECT_EQ(3, vessel_.psychohistory().Size());
  auto it = vessel_.psychohistory().Begin();
  ++it;
  EXPECT_EQ(astronomy::J2000 + 0.5 * Second, it.time());
  EXPECT_THAT(it.degrees_of_freedom(),
              Componentwise(AlmostEquals(Barycentric::origin +
                                      Displacement<Barycentric>(
                                          {13.3 / 3.0 * Metre,
                                          4.1 * Metre,
                                          11.3 / 3.0 * Metre}), 0),
                    AlmostEquals(Velocity<Barycentric>(
                                      {130.3 / 3.0 * Metre / Second,
                                      40.1 * Metre / Second,
                                      110.3 / 3.0 * Metre / Second}), 0)));
  ++it;
  EXPECT_EQ(astronomy::J2000 + 1.0 * Second, it.time());
  EXPECT_THAT(it.degrees_of_freedom(),
              Componentwise(AlmostEquals(Barycentric::origin +
                                      Displacement<Barycentric>(
                                          {13.6 / 3.0 * Metre,
                                          4.2 * Metre,
                                          11.6 / 3.0 * Metre}), 0),
                    AlmostEquals(Velocity<Barycentric>(
                                      {130.6 / 3.0 * Metre / Second,
                                      40.2 * Metre / Second,
                                      110.6 / 3.0 * Metre / Second}), 0)));
}

TEST_F(VesselTest, Prediction) {
  vessel_.PreparePsychohistory(astronomy::J2000);

  EXPECT_CALL(ephemeris_, FlowWithAdaptiveStep(_, _, _, _, _, _))
      .WillOnce(
          DoAll(AppendToDiscreteTrajectory(
                    astronomy::J2000 + 1.0 * Second,
                    DegreesOfFreedom<Barycentric>(
                        Barycentric::origin +
                            Displacement<Barycentric>({14.0 / 3.0 * Metre,
                                                       5.0 * Metre,
                                                       4.0 * Metre}),
                        Velocity<Barycentric>({140.0 / 3.0 * Metre / Second,
                                               50.0 * Metre / Second,
                                               40.0 * Metre / Second}))),
                Return(true)));
  vessel_.UpdatePrediction(astronomy::J2000 + 1 * Second);

  EXPECT_EQ(2, vessel_.prediction().Size());
  auto it = vessel_.prediction().Begin();
  ++it;
  EXPECT_EQ(astronomy::J2000, it.time());
  EXPECT_THAT(
      it.degrees_of_freedom(),
      Componentwise(AlmostEquals(Barycentric::origin +
                                      Displacement<Barycentric>(
                                          {13.0 / 3.0 * Metre,
                                           4.0 * Metre,
                                           11.0 / 3.0 * Metre}), 0),
                    AlmostEquals(Velocity<Barycentric>(
                                      {130.0 / 3.0 * Metre / Second,
                                       40.0 * Metre / Second,
                                       110.0 / 3.0 * Metre / Second}), 0)));
  ++it;
  EXPECT_EQ(astronomy::J2000 + 1.0 * Second, it.time());
  EXPECT_THAT(
      it.degrees_of_freedom(),
      Componentwise(AlmostEquals(Barycentric::origin +
                                      Displacement<Barycentric>(
                                          {14.0 / 3.0 * Metre,
                                           5.0 * Metre,
                                           4.0 * Metre}), 0),
                    AlmostEquals(Velocity<Barycentric>(
                                      {140.0 / 3.0 * Metre / Second,
                                       50.0 * Metre / Second,
                                       40.0 * Metre / Second}), 0)));
}

TEST_F(VesselTest, FlightPlan) {
  vessel_.CreateHistoryAndForkProlongation(t1_, d1_);
  vessel_.AdvanceTimeNotInBubble(t2_);
  EXPECT_FALSE(vessel_.has_flight_plan());
  vessel_.CreateFlightPlan(t3_, 10 * Kilogram, adaptive_parameters_);
  EXPECT_TRUE(vessel_.has_flight_plan());
  EXPECT_EQ(0, vessel_.flight_plan().number_of_manœuvres());
  EXPECT_EQ(1, vessel_.flight_plan().number_of_segments());
  vessel_.DeleteFlightPlan();
  EXPECT_FALSE(vessel_.has_flight_plan());
}

TEST_F(VesselDeathTest, SerializationError) {
  EXPECT_DEATH({
    serialization::Vessel message;
    vessel_.WriteToMessage(&message);
  }, "is_initialized");
  EXPECT_DEATH({
    serialization::Vessel message;
    Vessel::ReadFromMessage(message, ephemeris_.get(), earth_.get());
  }, "message.has_history");
}

TEST_F(VesselTest, SerializationSuccess) {
  serialization::Vessel message;
  vessel_.CreateHistoryAndForkProlongation(t2_, d2_);
  vessel_.AdvanceTimeNotInBubble(t2_);
  vessel_.UpdatePrediction(t3_);
  vessel_.CreateFlightPlan(t3_, 10 * Kilogram, adaptive_parameters_);

  vessel_.WriteToMessage(&message);
  EXPECT_TRUE(message.has_history());
  EXPECT_TRUE(message.has_prediction_fork_time());
  EXPECT_TRUE(message.has_prediction_last_time());
  EXPECT_TRUE(message.has_flight_plan());
  vessel_ = Vessel::ReadFromMessage(message, ephemeris_.get(), earth_.get());
  EXPECT_TRUE(vessel_.is_initialized());
  EXPECT_TRUE(vessel_.has_flight_plan());
}

TEST_F(VesselTest, PredictBeyondTheInfinite) {
  vessel_.CreateHistoryAndForkProlongation(t1_, d1_);
  vessel_.AdvanceTimeNotInBubble(t2_);
  vessel_.set_prediction_adaptive_step_parameters(
      Ephemeris<Barycentric>::AdaptiveStepParameters(
          DormandElMikkawyPrince1986RKN434FM<Position<Barycentric>>(),
          /*max_steps=*/5,
          /*length_integration_tolerance=*/1 * Metre,
          /*speed_integration_tolerance=*/1 * Metre / Second));
  Instant previous_t_max = ephemeris_->t_max();
  for (int i = 0; i < 10; ++i) {
    vessel_.UpdatePrediction(astronomy::InfiniteFuture);
  }
  // We stop prolonging when the ephemeris gets long enough (in this case, a
  // single prolongation suffices).
  EXPECT_THAT(ephemeris_->t_max() - previous_t_max,
              Le(FlightPlan::max_ephemeris_steps_per_frame *
                 ephemeris_fixed_parameters_.step()));
  EXPECT_THAT(vessel_.prediction().last().time(), Lt(ephemeris_->t_max()));

  vessel_.set_prediction_adaptive_step_parameters(
      Ephemeris<Barycentric>::AdaptiveStepParameters(
          DormandElMikkawyPrince1986RKN434FM<Position<Barycentric>>(),
          /*max_steps=*/1000,
          /*length_integration_tolerance=*/1 * Metre,
          /*speed_integration_tolerance=*/1 * Metre / Second));
  previous_t_max = ephemeris_->t_max();
  for (int i = 0; i < 10; ++i) {
    vessel_.UpdatePrediction(astronomy::InfiniteFuture);
  }
  // Here the ephemeris isn't long enough yet; we have prolonged every time.
  EXPECT_THAT((ephemeris_->t_max() - previous_t_max) /
                  (FlightPlan::max_ephemeris_steps_per_frame *
                   ephemeris_fixed_parameters_.step()),
              AllOf(Gt(9), Le(10)));
  EXPECT_THAT(vessel_.prediction().last().time(), Eq(ephemeris_->t_max()));
}

}  // namespace internal_vessel
}  // namespace ksp_plugin
}  // namespace principia
<commit_msg>Something that compiles.<commit_after>
#include "ksp_plugin/vessel.hpp"

#include <limits>

#include "astronomy/epoch.hpp"
#include "base/not_null.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ksp_plugin/celestial.hpp"
#include "physics/massive_body.hpp"
#include "physics/mock_ephemeris.hpp"
#include "quantities/si.hpp"
#include "testing_utilities/almost_equals.hpp"
#include "testing_utilities/componentwise.hpp"

namespace principia {
namespace ksp_plugin {
namespace internal_vessel {

using base::make_not_null_unique;
using geometry::Displacement;
using geometry::Position;
using geometry::Velocity;
using physics::MassiveBody;
using physics::MockEphemeris;
using quantities::si::Kilogram;
using quantities::si::Metre;
using quantities::si::Second;
using testing_utilities::AlmostEquals;
using testing_utilities::Componentwise;
using ::testing::DoAll;
using ::testing::ElementsAre;
using ::testing::Return;
using ::testing::_;

class VesselTest : public testing::Test {
 protected:
  VesselTest()
      : body_(MassiveBody::Parameters(1 * Kilogram)),
        celestial_(&body_),
        vessel_(&celestial_, &ephemeris_, DefaultPredictionParameters()) {
    auto p1 = make_not_null_unique<Part>(part_id1_,
                                         mass1_,
                                         p1_dof_,
                                         /*deletion_callback=*/nullptr);
    auto p2 = make_not_null_unique<Part>(part_id2_,
                                         mass2_,
                                         p2_dof_,
                                         /*deletion_callback=*/nullptr);
    p1_ = p1.get();
    p2_ = p2.get();
    vessel_.AddPart(std::move(p1));
    vessel_.AddPart(std::move(p2));
  }

  MockEphemeris<Barycentric> ephemeris_;
  MassiveBody const body_;
  Celestial const celestial_;
  PartId const part_id1_ = 111;
  PartId const part_id2_ = 222;
  Mass const mass1_ = 1 * Kilogram;
  Mass const mass2_ = 2 * Kilogram;

  // Centre of mass of |p1_| and |p2_| in |Barycentric|, in SI units:
  //   {13 / 3, 4, 11 / 3} {130 / 3, 40, 110 / 3}
  DegreesOfFreedom<Barycentric> const p1_dof_ = DegreesOfFreedom<Barycentric>(
      Barycentric::origin +
          Displacement<Barycentric>({1 * Metre, 2 * Metre, 3 * Metre}),
      Velocity<Barycentric>(
          {10 * Metre / Second, 20 * Metre / Second, 30 * Metre / Second}));
  DegreesOfFreedom<Barycentric> const p2_dof_ = DegreesOfFreedom<Barycentric>(
      Barycentric::origin +
          Displacement<Barycentric>({6 * Metre, 5 * Metre, 4 * Metre}),
      Velocity<Barycentric>(
          {60 * Metre / Second, 50 * Metre / Second, 40 * Metre / Second}));

  Part* p1_;
  Part* p2_;
  Vessel vessel_;
};

TEST_F(VesselTest, Parent) {
  Celestial other_celestial(&body_);
  EXPECT_EQ(&celestial_, vessel_.parent());
  vessel_.set_parent(&other_celestial);
  EXPECT_EQ(&other_celestial, vessel_.parent());
}

TEST_F(VesselTest, KeepAndFreeParts) {
  std::set<PartId> remaining_part_ids;
  vessel_.ForAllParts([&remaining_part_ids](Part const& part) {
    remaining_part_ids.insert(part.part_id());
  });
  EXPECT_THAT(remaining_part_ids, ElementsAre(part_id1_, part_id2_));
  EXPECT_EQ(part_id1_, vessel_.part(part_id1_)->part_id());
  EXPECT_EQ(part_id2_, vessel_.part(part_id2_)->part_id());

  vessel_.KeepPart(part_id2_);
  vessel_.FreeParts();
  vessel_.ForAllParts([&remaining_part_ids](Part const& part) {
    remaining_part_ids.insert(part.part_id());
  });
  EXPECT_THAT(remaining_part_ids, ElementsAre(part_id1_));
  EXPECT_EQ(part_id1_, vessel_.part(part_id1_)->part_id());
}

TEST_F(VesselTest, PreparePsychohistory) {
  EXPECT_TRUE(vessel_.psychohistory().Empty());
  vessel_.PreparePsychohistory(astronomy::J2000 + 1 * Second);
  EXPECT_EQ(1, vessel_.psychohistory().Size());
  EXPECT_EQ(astronomy::J2000 + 1 * Second,
            vessel_.psychohistory().End().time());
  EXPECT_THAT(
      vessel_.psychohistory().last().degrees_of_freedom(),
      Componentwise(AlmostEquals(Barycentric::origin +
                                      Displacement<Barycentric>(
                                          {13.0 / 3.0 * Metre,
                                          4.0 * Metre,
                                          11.0 / 3.0 * Metre}), 0),
                    AlmostEquals(Velocity<Barycentric>(
                                      {130.0 / 3.0 * Metre / Second,
                                      40.0 * Metre / Second,
                                      110.0 / 3.0 * Metre / Second}), 0)));
}

TEST_F(VesselTest, AdvanceTime) {
  vessel_.PreparePsychohistory(astronomy::J2000);

  p1_->tail().Append(
      astronomy::J2000 + 0.5 * Second,
      DegreesOfFreedom<Barycentric>(
          Barycentric::origin + Displacement<Barycentric>(
                                    {1.1 * Metre, 2.1 * Metre, 3.1 * Metre}),
          Velocity<Barycentric>({10.1 * Metre / Second,
                                 20.1 * Metre / Second,
                                 30.1 * Metre / Second})));
  p1_->tail().Append(
      astronomy::J2000 + 1.0 * Second,
      DegreesOfFreedom<Barycentric>(
          Barycentric::origin + Displacement<Barycentric>(
                                    {1.2 * Metre, 2.2 * Metre, 3.2 * Metre}),
          Velocity<Barycentric>({10.2 * Metre / Second,
                                 20.2 * Metre / Second,
                                 30.2 * Metre / Second})));
  p2_->tail().Append(
      astronomy::J2000 + 0.5 * Second,
      DegreesOfFreedom<Barycentric>(
          Barycentric::origin + Displacement<Barycentric>(
                                    {6.1 * Metre, 5.1 * Metre, 4.1 * Metre}),
          Velocity<Barycentric>({60.1 * Metre / Second,
                                 50.1 * Metre / Second,
                                 40.1 * Metre / Second})));
  p2_->tail().Append(
      astronomy::J2000 + 1.0 * Second,
      DegreesOfFreedom<Barycentric>(
          Barycentric::origin + Displacement<Barycentric>(
                                    {6.2 * Metre, 5.2 * Metre, 4.2 * Metre}),
          Velocity<Barycentric>({60.2 * Metre / Second,
                                 50.2 * Metre / Second,
                                 40.2 * Metre / Second})));

  vessel_.AdvanceTime();

  EXPECT_EQ(3, vessel_.psychohistory().Size());
  auto it = vessel_.psychohistory().Begin();
  ++it;
  EXPECT_EQ(astronomy::J2000 + 0.5 * Second, it.time());
  EXPECT_THAT(it.degrees_of_freedom(),
              Componentwise(AlmostEquals(Barycentric::origin +
                                      Displacement<Barycentric>(
                                          {13.3 / 3.0 * Metre,
                                          4.1 * Metre,
                                          11.3 / 3.0 * Metre}), 0),
                    AlmostEquals(Velocity<Barycentric>(
                                      {130.3 / 3.0 * Metre / Second,
                                      40.1 * Metre / Second,
                                      110.3 / 3.0 * Metre / Second}), 0)));
  ++it;
  EXPECT_EQ(astronomy::J2000 + 1.0 * Second, it.time());
  EXPECT_THAT(it.degrees_of_freedom(),
              Componentwise(AlmostEquals(Barycentric::origin +
                                      Displacement<Barycentric>(
                                          {13.6 / 3.0 * Metre,
                                          4.2 * Metre,
                                          11.6 / 3.0 * Metre}), 0),
                    AlmostEquals(Velocity<Barycentric>(
                                      {130.6 / 3.0 * Metre / Second,
                                      40.2 * Metre / Second,
                                      110.6 / 3.0 * Metre / Second}), 0)));
}

TEST_F(VesselTest, Prediction) {
  vessel_.PreparePsychohistory(astronomy::J2000);

  EXPECT_CALL(ephemeris_, FlowWithAdaptiveStep(_, _, _, _, _, _))
      .WillOnce(
          DoAll(AppendToDiscreteTrajectory(
                    astronomy::J2000 + 1.0 * Second,
                    DegreesOfFreedom<Barycentric>(
                        Barycentric::origin +
                            Displacement<Barycentric>({14.0 / 3.0 * Metre,
                                                       5.0 * Metre,
                                                       4.0 * Metre}),
                        Velocity<Barycentric>({140.0 / 3.0 * Metre / Second,
                                               50.0 * Metre / Second,
                                               40.0 * Metre / Second}))),
                Return(true)));
  vessel_.UpdatePrediction(astronomy::J2000 + 1 * Second);

  EXPECT_EQ(2, vessel_.prediction().Size());
  auto it = vessel_.prediction().Begin();
  ++it;
  EXPECT_EQ(astronomy::J2000, it.time());
  EXPECT_THAT(
      it.degrees_of_freedom(),
      Componentwise(AlmostEquals(Barycentric::origin +
                                      Displacement<Barycentric>(
                                          {13.0 / 3.0 * Metre,
                                           4.0 * Metre,
                                           11.0 / 3.0 * Metre}), 0),
                    AlmostEquals(Velocity<Barycentric>(
                                      {130.0 / 3.0 * Metre / Second,
                                       40.0 * Metre / Second,
                                       110.0 / 3.0 * Metre / Second}), 0)));
  ++it;
  EXPECT_EQ(astronomy::J2000 + 1.0 * Second, it.time());
  EXPECT_THAT(
      it.degrees_of_freedom(),
      Componentwise(AlmostEquals(Barycentric::origin +
                                      Displacement<Barycentric>(
                                          {14.0 / 3.0 * Metre,
                                           5.0 * Metre,
                                           4.0 * Metre}), 0),
                    AlmostEquals(Velocity<Barycentric>(
                                      {140.0 / 3.0 * Metre / Second,
                                       50.0 * Metre / Second,
                                       40.0 * Metre / Second}), 0)));
}

TEST_F(VesselTest, PredictBeyondTheInfinite) {
  vessel_.PreparePsychohistory(astronomy::J2000);

  EXPECT_CALL(ephemeris_, t_max())
      .WillOnce(Return(astronomy::J2000 + 0.5 * Second));
  EXPECT_CALL(
      ephemeris_,
      FlowWithAdaptiveStep(_, _, astronomy::J2000 + 0.5 * Second, _, _, _))
      .WillOnce(
          DoAll(AppendToDiscreteTrajectory(
                    astronomy::J2000 + 0.5 * Second,
                    DegreesOfFreedom<Barycentric>(
                        Barycentric::origin +
                            Displacement<Barycentric>({14.0 / 3.0 * Metre,
                                                       5.0 * Metre,
                                                       4.0 * Metre}),
                        Velocity<Barycentric>({140.0 / 3.0 * Metre / Second,
                                               50.0 * Metre / Second,
                                               40.0 * Metre / Second}))),
                Return(true)));
  EXPECT_CALL(
      ephemeris_,
      FlowWithAdaptiveStep(_, _, astronomy::J2000 + 1.0 * Second, _, _, _))
      .WillOnce(
          DoAll(AppendToDiscreteTrajectory(
                    astronomy::J2000 + 1.0 * Second,
                    DegreesOfFreedom<Barycentric>(
                        Barycentric::origin +
                            Displacement<Barycentric>({5.0 * Metre,
                                                       6.0 * Metre,
                                                       5.0 * Metre}),
                        Velocity<Barycentric>({50.0 * Metre / Second,
                                               60.0 * Metre / Second,
                                               50.0 * Metre / Second}))),
                Return(true)));
  vessel_.UpdatePrediction(astronomy::J2000 + 1.0 * Second);

  EXPECT_EQ(3, vessel_.prediction().Size());
  auto it = vessel_.prediction().Begin();
  ++it;
  EXPECT_EQ(astronomy::J2000 + 0.5 * Second, it.time());
  ++it;
  EXPECT_EQ(astronomy::J2000 + 1.0 * Second, it.time());
  EXPECT_THAT(
      it.degrees_of_freedom(),
      Componentwise(AlmostEquals(Barycentric::origin +
                                      Displacement<Barycentric>(
                                          {5.0 * Metre,
                                           6.0 * Metre,
                                           5.0 * Metre}), 0),
                    AlmostEquals(Velocity<Barycentric>(
                                      {50.0 * Metre / Second,
                                       60.0 * Metre / Second,
                                       50.0 * Metre / Second}), 0)));
}

TEST_F(VesselTest, FlightPlan) {
  vessel_.PreparePsychohistory(astronomy::J2000);

  EXPECT_FALSE(vessel_.has_flight_plan());
  vessel_.CreateFlightPlan(astronomy::J2000 + 3.0 * Second,
                           10 * Kilogram,
                           DefaultPredictionParameters());
  EXPECT_TRUE(vessel_.has_flight_plan());
  EXPECT_EQ(0, vessel_.flight_plan().number_of_manœuvres());
  EXPECT_EQ(1, vessel_.flight_plan().number_of_segments());
  vessel_.DeleteFlightPlan();
  EXPECT_FALSE(vessel_.has_flight_plan());
}

TEST_F(VesselTest, SerializationSuccess) {
  vessel_.PreparePsychohistory(astronomy::J2000);

  serialization::Vessel message;
  vessel_.CreateFlightPlan(astronomy::J2000 + 3.0 * Second,
                           10 * Kilogram,
                           DefaultPredictionParameters());

  vessel_.WriteToMessage(&message);
  EXPECT_TRUE(message.has_psychohistory());
  EXPECT_TRUE(message.has_flight_plan());

  auto const v = Vessel::ReadFromMessage(
      message, &celestial_, &ephemeris_, /*deletion_callback=*/nullptr);
  EXPECT_TRUE(v->has_flight_plan());

  serialization::Vessel second_message;
  v->WriteToMessage(&second_message);
  EXPECT_EQ(message.SerializeAsString(), second_message.SerializeAsString());
}

}  // namespace internal_vessel
}  // namespace ksp_plugin
}  // namespace principia
<|endoftext|>


<commit_before>
#include <gtest/gtest.h>

#include <string>

#include "composition.h"
#include "material.h"
#include "test_context.h"
#include "mock_facility.h"

#include "request.h"

using std::string;
using cyclus::Composition;
using cyclus::Material;
using cyclus::Request;
using cyclus::TestContext;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST(RequestTests, GetSet) {
  TestContext tc;
  MockFacility* fac = new MockFacility(tc.get());
  string commod = "name";
  double pref = 2.4;
  cyclus::CompMap cm;
  cm[92235] = 1.0;
  Composition::Ptr comp = Composition::CreateFromMass(cm);
  double mat_qty = 1.0;
  Material::Ptr mat = Material::Create(tc.get(), mat_qty, comp);

  Request<Material> r;
  r.commodity = commod;
  r.requester = fac;
  r.target = mat.get();
  r.preference = pref;

  EXPECT_EQ(commod, r.commodity);
  EXPECT_EQ(fac, r.requester);
  EXPECT_EQ(mat.get(), r.target);
  EXPECT_EQ(pref, r.preference);

  delete fac;
}
<commit_msg>added test for generic resource<commit_after>
#include <gtest/gtest.h>

#include <string>

#include "composition.h"
#include "facility_model.h"
#include "generic_resource.h"
#include "material.h"
#include "test_context.h"
#include "mock_facility.h"

#include "request.h"

using std::string;
using cyclus::Composition;
using cyclus::GenericResource;
using cyclus::Material;
using cyclus::Request;
using cyclus::TestContext;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST(RequestTests, MaterialGetSet) {
  TestContext tc;
  MockFacility* fac = new MockFacility(tc.get());
  string commod = "name";
  double pref = 2.4;
  cyclus::CompMap cm;
  cm[92235] = 1.0;
  Composition::Ptr comp = Composition::CreateFromMass(cm);
  double qty = 1.0;
  Material::Ptr mat = Material::Create(tc.get(), qty, comp);

  Request<Material> r;
  r.commodity = commod;
  r.requester = fac;
  r.target = mat.get();
  r.preference = pref;

  EXPECT_EQ(commod, r.commodity);
  EXPECT_EQ(fac, r.requester);
  EXPECT_EQ(mat.get(), r.target);
  EXPECT_EQ(pref, r.preference);

  delete fac;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST(RequestTests, GenRsrcGetSet) {
  TestContext tc;
  MockFacility* fac = new MockFacility(tc.get());
  string commod = "name";
  double pref = 2.4;
  double qty = 1.0;
  string quality = "qual";
  string units = "units";

  GenericResource::Ptr rsrc =
      GenericResource::Create(tc.get(), qty, quality, units);

  Request<GenericResource> r;
  r.commodity = commod;
  r.requester = fac;
  r.target = rsrc.get();
  r.preference = pref;

  EXPECT_EQ(commod, r.commodity);
  EXPECT_EQ(fac, r.requester);
  EXPECT_EQ(rsrc.get(), r.target);
  EXPECT_EQ(pref, r.preference);

  delete fac;
}
<|endoftext|>


<commit_before>//===-- MipsMCTargetDesc.cpp - Mips Target Descriptions ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides Mips specific target descriptions.
//
//===----------------------------------------------------------------------===//

#include "MipsMCTargetDesc.h"
#include "MipsMCAsmInfo.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/TargetRegistry.h"

#define GET_INSTRINFO_MC_DESC
#include "MipsGenInstrInfo.inc"

#define GET_SUBTARGETINFO_MC_DESC
#include "MipsGenSubtargetInfo.inc"

#define GET_REGINFO_MC_DESC
#include "MipsGenRegisterInfo.inc"

using namespace llvm;

static MCInstrInfo *createMipsMCInstrInfo() {
  MCInstrInfo *X = new MCInstrInfo();
  InitMipsMCInstrInfo(X);
  return X;
}

static MCRegisterInfo *createMipsMCRegisterInfo(StringRef TT) {
  MCRegisterInfo *X = new MCRegisterInfo();
  InitMipsMCRegisterInfo(X, Mips::RA);
  return X;
}

static MCSubtargetInfo *createMipsMCSubtargetInfo(StringRef TT, StringRef CPU,
                                                  StringRef FS) {
  MCSubtargetInfo *X = new MCSubtargetInfo();
  InitMipsMCSubtargetInfo(X, TT, CPU, FS);
  return X;
}

static MCAsmInfo *createMipsMCAsmInfo(const Target &T, StringRef TT) {
  MCAsmInfo *MAI = new MipsMCAsmInfo(T, TT);

  MachineLocation Dst(MachineLocation::VirtualFP);
  MachineLocation Src(Mips::SP, 0);
  MAI->addInitialFrameState(0, Dst, Src);

  return MAI;
}

static MCCodeGenInfo *createMipsMCCodeGenInfo(StringRef TT, Reloc::Model RM,
                                              CodeModel::Model CM) {
  MCCodeGenInfo *X = new MCCodeGenInfo();
  if (RM == Reloc::Default)
    RM = Reloc::PIC_;
  X->InitMCCodeGenInfo(RM, CM);
  return X;
}

static MCInstPrinter *createMipsMCInstPrinter(const Target &T,
                                              unsigned SyntaxVariant,
                                              const MCAsmInfo &MAI,
                                              const MCSubtargetInfo &STI) {
  return new MipsInstPrinter(MAI);
}

extern "C" void LLVMInitializeMipsTargetMC() {
  // Register the MC asm info.
  RegisterMCAsmInfoFn X(TheMipsTarget, createMipsMCAsmInfo);
  RegisterMCAsmInfoFn Y(TheMipselTarget, createMipsMCAsmInfo);
  RegisterMCAsmInfoFn A(TheMips64Target, createMipsMCAsmInfo);
  RegisterMCAsmInfoFn B(TheMips64elTarget, createMipsMCAsmInfo);

  // Register the MC codegen info.
  TargetRegistry::RegisterMCCodeGenInfo(TheMipsTarget,
                                        createMipsMCCodeGenInfo);
  TargetRegistry::RegisterMCCodeGenInfo(TheMipselTarget,
                                        createMipsMCCodeGenInfo);
  TargetRegistry::RegisterMCCodeGenInfo(TheMips64Target,
                                        createMipsMCCodeGenInfo);
  TargetRegistry::RegisterMCCodeGenInfo(TheMips64elTarget,
                                        createMipsMCCodeGenInfo);

  // Register the MC instruction info.
  TargetRegistry::RegisterMCInstrInfo(TheMipsTarget, createMipsMCInstrInfo);
  TargetRegistry::RegisterMCInstrInfo(TheMipselTarget, createMipsMCInstrInfo);
  TargetRegistry::RegisterMCInstrInfo(TheMips64Target, createMipsMCInstrInfo);
  TargetRegistry::RegisterMCInstrInfo(TheMips64elTarget, createMipsMCInstrInfo);

  // Register the MC register info.
  TargetRegistry::RegisterMCRegInfo(TheMipsTarget, createMipsMCRegisterInfo);
  TargetRegistry::RegisterMCRegInfo(TheMipselTarget, createMipsMCRegisterInfo);
  TargetRegistry::RegisterMCRegInfo(TheMips64Target, createMipsMCRegisterInfo);
  TargetRegistry::RegisterMCRegInfo(TheMips64elTarget,
                                    createMipsMCRegisterInfo);

  // Register the MC Code Emitter
  TargetRegistry::RegisterMCCodeEmitter(TheMipsTarget, createMipsMCCodeEmitter);
  TargetRegistry::RegisterMCCodeEmitter(TheMipselTarget,
                                        createMipsMCCodeEmitter);
  TargetRegistry::RegisterMCCodeEmitter(TheMips64Target,
                                        createMipsMCCodeEmitter);
  TargetRegistry::RegisterMCCodeEmitter(TheMips64elTarget,
                                        createMipsMCCodeEmitter);

  // Register the asm backend.
  TargetRegistry::RegisterMCAsmBackend(TheMipsTarget, createMipsAsmBackend);
  TargetRegistry::RegisterMCAsmBackend(TheMipselTarget, createMipsAsmBackend);
  TargetRegistry::RegisterMCAsmBackend(TheMips64Target, createMipsAsmBackend);
  TargetRegistry::RegisterMCAsmBackend(TheMips64elTarget, createMipsAsmBackend);

  // Register the MC subtarget info.
  TargetRegistry::RegisterMCSubtargetInfo(TheMipsTarget,
                                          createMipsMCSubtargetInfo);
  TargetRegistry::RegisterMCSubtargetInfo(TheMipselTarget,
                                          createMipsMCSubtargetInfo);
  TargetRegistry::RegisterMCSubtargetInfo(TheMips64Target,
                                          createMipsMCSubtargetInfo);
  TargetRegistry::RegisterMCSubtargetInfo(TheMips64elTarget,
                                          createMipsMCSubtargetInfo);

  // Register the MCInstPrinter.
  TargetRegistry::RegisterMCInstPrinter(TheMipsTarget,
                                        createMipsMCInstPrinter);
  TargetRegistry::RegisterMCInstPrinter(TheMipselTarget,
                                        createMipsMCInstPrinter);
  TargetRegistry::RegisterMCInstPrinter(TheMips64Target,
                                        createMipsMCInstPrinter);
  TargetRegistry::RegisterMCInstPrinter(TheMips64elTarget,
                                        createMipsMCInstPrinter);
}
<commit_msg>Register the MC object streamer.<commit_after>//===-- MipsMCTargetDesc.cpp - Mips Target Descriptions ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides Mips specific target descriptions.
//
//===----------------------------------------------------------------------===//

#include "MipsMCTargetDesc.h"
#include "MipsMCAsmInfo.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/TargetRegistry.h"

#define GET_INSTRINFO_MC_DESC
#include "MipsGenInstrInfo.inc"

#define GET_SUBTARGETINFO_MC_DESC
#include "MipsGenSubtargetInfo.inc"

#define GET_REGINFO_MC_DESC
#include "MipsGenRegisterInfo.inc"

using namespace llvm;

static MCInstrInfo *createMipsMCInstrInfo() {
  MCInstrInfo *X = new MCInstrInfo();
  InitMipsMCInstrInfo(X);
  return X;
}

static MCRegisterInfo *createMipsMCRegisterInfo(StringRef TT) {
  MCRegisterInfo *X = new MCRegisterInfo();
  InitMipsMCRegisterInfo(X, Mips::RA);
  return X;
}

static MCSubtargetInfo *createMipsMCSubtargetInfo(StringRef TT, StringRef CPU,
                                                  StringRef FS) {
  MCSubtargetInfo *X = new MCSubtargetInfo();
  InitMipsMCSubtargetInfo(X, TT, CPU, FS);
  return X;
}

static MCAsmInfo *createMipsMCAsmInfo(const Target &T, StringRef TT) {
  MCAsmInfo *MAI = new MipsMCAsmInfo(T, TT);

  MachineLocation Dst(MachineLocation::VirtualFP);
  MachineLocation Src(Mips::SP, 0);
  MAI->addInitialFrameState(0, Dst, Src);

  return MAI;
}

static MCCodeGenInfo *createMipsMCCodeGenInfo(StringRef TT, Reloc::Model RM,
                                              CodeModel::Model CM) {
  MCCodeGenInfo *X = new MCCodeGenInfo();
  if (RM == Reloc::Default)
    RM = Reloc::PIC_;
  X->InitMCCodeGenInfo(RM, CM);
  return X;
}

static MCInstPrinter *createMipsMCInstPrinter(const Target &T,
                                              unsigned SyntaxVariant,
                                              const MCAsmInfo &MAI,
                                              const MCSubtargetInfo &STI) {
  return new MipsInstPrinter(MAI);
}

static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
                                    MCContext &Ctx, MCAsmBackend &MAB,
                                    raw_ostream &_OS,
                                    MCCodeEmitter *_Emitter,
                                    bool RelaxAll,
                                    bool NoExecStack) {
  Triple TheTriple(TT);

  return createELFStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll, NoExecStack);
}

extern "C" void LLVMInitializeMipsTargetMC() {
  // Register the MC asm info.
  RegisterMCAsmInfoFn X(TheMipsTarget, createMipsMCAsmInfo);
  RegisterMCAsmInfoFn Y(TheMipselTarget, createMipsMCAsmInfo);
  RegisterMCAsmInfoFn A(TheMips64Target, createMipsMCAsmInfo);
  RegisterMCAsmInfoFn B(TheMips64elTarget, createMipsMCAsmInfo);

  // Register the MC codegen info.
  TargetRegistry::RegisterMCCodeGenInfo(TheMipsTarget,
                                        createMipsMCCodeGenInfo);
  TargetRegistry::RegisterMCCodeGenInfo(TheMipselTarget,
                                        createMipsMCCodeGenInfo);
  TargetRegistry::RegisterMCCodeGenInfo(TheMips64Target,
                                        createMipsMCCodeGenInfo);
  TargetRegistry::RegisterMCCodeGenInfo(TheMips64elTarget,
                                        createMipsMCCodeGenInfo);

  // Register the MC instruction info.
  TargetRegistry::RegisterMCInstrInfo(TheMipsTarget, createMipsMCInstrInfo);
  TargetRegistry::RegisterMCInstrInfo(TheMipselTarget, createMipsMCInstrInfo);
  TargetRegistry::RegisterMCInstrInfo(TheMips64Target, createMipsMCInstrInfo);
  TargetRegistry::RegisterMCInstrInfo(TheMips64elTarget, createMipsMCInstrInfo);

  // Register the MC register info.
  TargetRegistry::RegisterMCRegInfo(TheMipsTarget, createMipsMCRegisterInfo);
  TargetRegistry::RegisterMCRegInfo(TheMipselTarget, createMipsMCRegisterInfo);
  TargetRegistry::RegisterMCRegInfo(TheMips64Target, createMipsMCRegisterInfo);
  TargetRegistry::RegisterMCRegInfo(TheMips64elTarget,
                                    createMipsMCRegisterInfo);

  // Register the MC Code Emitter
  TargetRegistry::RegisterMCCodeEmitter(TheMipsTarget, createMipsMCCodeEmitter);
  TargetRegistry::RegisterMCCodeEmitter(TheMipselTarget,
                                        createMipsMCCodeEmitter);
  TargetRegistry::RegisterMCCodeEmitter(TheMips64Target,
                                        createMipsMCCodeEmitter);
  TargetRegistry::RegisterMCCodeEmitter(TheMips64elTarget,
                                        createMipsMCCodeEmitter);

  // Register the object streamer.
  TargetRegistry::RegisterMCObjectStreamer(TheMipsTarget, createMCStreamer);
  TargetRegistry::RegisterMCObjectStreamer(TheMipselTarget, createMCStreamer);
  TargetRegistry::RegisterMCObjectStreamer(TheMips64Target, createMCStreamer);
  TargetRegistry::RegisterMCObjectStreamer(TheMips64elTarget, createMCStreamer);

  // Register the asm backend.
  TargetRegistry::RegisterMCAsmBackend(TheMipsTarget, createMipsAsmBackend);
  TargetRegistry::RegisterMCAsmBackend(TheMipselTarget, createMipsAsmBackend);
  TargetRegistry::RegisterMCAsmBackend(TheMips64Target, createMipsAsmBackend);
  TargetRegistry::RegisterMCAsmBackend(TheMips64elTarget, createMipsAsmBackend);

  // Register the MC subtarget info.
  TargetRegistry::RegisterMCSubtargetInfo(TheMipsTarget,
                                          createMipsMCSubtargetInfo);
  TargetRegistry::RegisterMCSubtargetInfo(TheMipselTarget,
                                          createMipsMCSubtargetInfo);
  TargetRegistry::RegisterMCSubtargetInfo(TheMips64Target,
                                          createMipsMCSubtargetInfo);
  TargetRegistry::RegisterMCSubtargetInfo(TheMips64elTarget,
                                          createMipsMCSubtargetInfo);

  // Register the MCInstPrinter.
  TargetRegistry::RegisterMCInstPrinter(TheMipsTarget,
                                        createMipsMCInstPrinter);
  TargetRegistry::RegisterMCInstPrinter(TheMipselTarget,
                                        createMipsMCInstPrinter);
  TargetRegistry::RegisterMCInstPrinter(TheMips64Target,
                                        createMipsMCInstPrinter);
  TargetRegistry::RegisterMCInstPrinter(TheMips64elTarget,
                                        createMipsMCInstPrinter);
}
<|endoftext|>


<commit_before>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include <cstdlib>

#ifdef CLEVER_WIN32
# include <direct.h>
# include <windows.h>
# define PATH_MAX MAX_PATH
#else
# include <dirent.h>
# include <unistd.h>
# include <sys/resource.h>
# include <sys/time.h>
#endif
#include "core/value.h"
#include "modules/std/sys/sys.h"
#include "types/native_types.h"
#include "core/modmanager.h"
#include "core/cexception.h"

#ifndef PATH_MAX
# define PATH_MAX 1024
#endif

namespace clever { namespace modules { namespace std {

namespace sys {

// system(string command)
// Calls a command and returns the exit code
static CLEVER_FUNCTION(system)
{
	if (!clever_static_check_args("s")) {
		return;
	}

	result->setInt(::system(args[0]->getStr()->c_str()));
}

// putenv(string env)
// Sets an environment variable
static CLEVER_FUNCTION(putenv)
{
	if (!clever_static_check_args("s")) {
		return;
	}

    ::putenv(const_cast<char*>(args[0]->getStr()->c_str()));
}

// getenv(string env)
// Gets an environment variable
static CLEVER_FUNCTION(getenv)
{
	if (!clever_static_check_args("s")) {
		return;
	}

	const char* ret = ::getenv(const_cast<char*>(args[0]->getStr()->c_str()));

	if (ret) {
		result->setStr(CSTRINGT(ret));
	} else {
		result->setStr(CSTRING(""));
	}
}

// getcwd()
// Gets the current working directory
static CLEVER_FUNCTION(getcwd)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	char temp[PATH_MAX];
    const char* path = ::getcwd(temp, PATH_MAX);

	result->setStr(CSTRING(path ? path : ""));
}

// argv(int n)
// Get n-th argv value
static CLEVER_FUNCTION(argv)
{
/*
	size_t i = static_cast<size_t>(CLEVER_ARG_INT(0));

	if (i >= (size_t)*g_clever_argc) {
		CLEVER_RETURN_EMPTY_STR();
	} else {
		CLEVER_RETURN_STR(CSTRINGT((*g_clever_argv)[i]));
	}
*/
}

// argc()
// Get argc value
static CLEVER_FUNCTION(argc)
{
	if (!clever_static_check_no_args()) {
		return;
	}
//	CLEVER_RETURN_INT(*g_clever_argc);
}

// sleep(int time)
// Sleep for 'time' milliseconds
static CLEVER_FUNCTION(sleep)
{
	if (!clever_static_check_args("i")) {
		return;
	}

	int time = static_cast<int>(args[0]->getInt());

#ifdef CLEVER_WIN32
	SleepEx(time, false);
#else
	usleep(time * 1000);
#endif
}

// clock()
// Returns the execution clock
static CLEVER_FUNCTION(clock)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	result->setInt(clock());
}

// getpid()
// Returns the current process id
static CLEVER_FUNCTION(getpid)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	result->setInt(::getpid());
}

// getppid()
// Returns the current process id
static CLEVER_FUNCTION(getppid)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	result->setInt(::getppid());
}

// getuid
// Returns the process user id
static CLEVER_FUNCTION(getuid)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	result->setInt(::geteuid());
}

// getsid
// Returns the process group id
static CLEVER_FUNCTION(getsid)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	result->setInt(::getsid(0));
}

} // clever::modules::std::sys

// Initializes Standard module
CLEVER_MODULE_INIT(SYSModule)
{
	addFunction(new Function("system",  &CLEVER_NS_FNAME(sys, system)));
	addFunction(new Function("putenv",  &CLEVER_NS_FNAME(sys, putenv)));
	addFunction(new Function("getenv",  &CLEVER_NS_FNAME(sys, getenv)));
	addFunction(new Function("getcwd",  &CLEVER_NS_FNAME(sys, getcwd)));
	addFunction(new Function("getpid",  &CLEVER_NS_FNAME(sys, getpid)));
	addFunction(new Function("getppid", &CLEVER_NS_FNAME(sys, getppid)));
	addFunction(new Function("getuid",  &CLEVER_NS_FNAME(sys, getuid)));
	addFunction(new Function("getsid",  &CLEVER_NS_FNAME(sys, getsid)));
	addFunction(new Function("argc",    &CLEVER_NS_FNAME(sys, argc)));
	addFunction(new Function("argv",    &CLEVER_NS_FNAME(sys, argv)));
	addFunction(new Function("sleep",   &CLEVER_NS_FNAME(sys, sleep)));
	addFunction(new Function("clock",   &CLEVER_NS_FNAME(sys, clock)));
}

}}} // clever::modules::std
<commit_msg>time function added<commit_after>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include <cstdlib>

#ifdef CLEVER_WIN32
# include <direct.h>
# include <windows.h>
# define PATH_MAX MAX_PATH
#else
# include <dirent.h>
# include <unistd.h>
# include <sys/resource.h>
# include <sys/time.h>
#endif
#include "core/value.h"
#include "modules/std/sys/sys.h"
#include "types/native_types.h"
#include "core/modmanager.h"
#include "core/cexception.h"

#ifndef PATH_MAX
# define PATH_MAX 1024
#endif

namespace clever { namespace modules { namespace std {

namespace sys {

// system(string command)
// Calls a command and returns the exit code
static CLEVER_FUNCTION(system)
{
	if (!clever_static_check_args("s")) {
		return;
	}

	result->setInt(::system(args[0]->getStr()->c_str()));
}

// putenv(string env)
// Sets an environment variable
static CLEVER_FUNCTION(putenv)
{
	if (!clever_static_check_args("s")) {
		return;
	}

	::putenv(const_cast<char*>(args[0]->getStr()->c_str()));
}

// getenv(string env)
// Gets an environment variable
static CLEVER_FUNCTION(getenv)
{
	if (!clever_static_check_args("s")) {
		return;
	}

	const char* ret = ::getenv(const_cast<char*>(args[0]->getStr()->c_str()));

	if (ret) {
		result->setStr(CSTRINGT(ret));
	} else {
		result->setStr(CSTRING(""));
	}
}

// getcwd()
// Gets the current working directory
static CLEVER_FUNCTION(getcwd)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	char temp[PATH_MAX];
	const char* path = ::getcwd(temp, PATH_MAX);

	result->setStr(CSTRING(path ? path : ""));
}

// argv(int n)
// Get n-th argv value
static CLEVER_FUNCTION(argv)
{
/*
	size_t i = static_cast<size_t>(CLEVER_ARG_INT(0));

	if (i >= (size_t)*g_clever_argc) {
		CLEVER_RETURN_EMPTY_STR();
	} else {
		CLEVER_RETURN_STR(CSTRINGT((*g_clever_argv)[i]));
	}
*/
}

// argc()
// Get argc value
static CLEVER_FUNCTION(argc)
{
	if (!clever_static_check_no_args()) {
		return;
	}
//	CLEVER_RETURN_INT(*g_clever_argc);
}

// sleep(int time)
// Sleep for 'time' milliseconds
static CLEVER_FUNCTION(sleep)
{
	if (!clever_static_check_args("i")) {
		return;
	}

	int time = static_cast<int>(args[0]->getInt());

#ifdef CLEVER_WIN32
	SleepEx(time, false);
#else
	usleep(time * 1000);
#endif
}

// clock()
// Returns the execution clock
static CLEVER_FUNCTION(clock)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	result->setInt(clock());
}

// time()
// Returns the execution time in sec
static CLEVER_FUNCTION(time)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	result->setDouble(static_cast<double>(clock()) / CLOCKS_PER_SEC);
}

// getpid()
// Returns the current process id
static CLEVER_FUNCTION(getpid)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	result->setInt(::getpid());
}

// getppid()
// Returns the current process id
static CLEVER_FUNCTION(getppid)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	result->setInt(::getppid());
}

// getuid
// Returns the process user id
static CLEVER_FUNCTION(getuid)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	result->setInt(::geteuid());
}

// getsid
// Returns the process group id
static CLEVER_FUNCTION(getsid)
{
	if (!clever_static_check_no_args()) {
		return;
	}

	result->setInt(::getsid(0));
}

} // clever::modules::std::sys

// Initializes Standard module
CLEVER_MODULE_INIT(SYSModule)
{
	addFunction(new Function("system",  &CLEVER_NS_FNAME(sys, system)));
	addFunction(new Function("putenv",  &CLEVER_NS_FNAME(sys, putenv)));
	addFunction(new Function("getenv",  &CLEVER_NS_FNAME(sys, getenv)));
	addFunction(new Function("getcwd",  &CLEVER_NS_FNAME(sys, getcwd)));
	addFunction(new Function("getpid",  &CLEVER_NS_FNAME(sys, getpid)));
	addFunction(new Function("getppid", &CLEVER_NS_FNAME(sys, getppid)));
	addFunction(new Function("getuid",  &CLEVER_NS_FNAME(sys, getuid)));
	addFunction(new Function("getsid",  &CLEVER_NS_FNAME(sys, getsid)));
	addFunction(new Function("argc",    &CLEVER_NS_FNAME(sys, argc)));
	addFunction(new Function("argv",    &CLEVER_NS_FNAME(sys, argv)));
	addFunction(new Function("sleep",   &CLEVER_NS_FNAME(sys, sleep)));
	addFunction(new Function("clock",   &CLEVER_NS_FNAME(sys, clock)));
	addFunction(new Function("time",    &CLEVER_NS_FNAME(sys, time)));
}

}}} // clever::modules::std
<|endoftext|>


<commit_before>#include "ExternalOutput.h"
#include "../WebRtcConnection.h"
#include "../RTPSink.h"
#include <cstdio>

#include <boost/cstdint.hpp>
#include <sys/time.h>
#include <arpa/inet.h>

namespace erizo {
  ExternalOutput::ExternalOutput(std::string outputUrl){
    url = outputUrl;
    sinkfbSource_=NULL;
    unpackagedBuffer_ = NULL;
    audioSinkSSRC_ = 0;
    videoSinkSSRC_ = 0;

  }

  bool ExternalOutput::init(){
   av_register_all();
   avcodec_register_all();
   context_ = avformat_alloc_context();
   oformat_ = av_guess_format(NULL,  url.c_str(), NULL);
   if (!oformat_){
    printf("Error opening output file %s", url.c_str());
    return false;
   }
   context_->oformat = oformat_;
   url.copy(context_->filename, sizeof(context_->filename),0);
   video_st = NULL;
   audio_st = NULL;
   if (oformat_->video_codec != AV_CODEC_ID_NONE) {
     videoCodec_ = avcodec_find_encoder(oformat_->video_codec);
     printf("Found Codec %s\n", videoCodec_->name);
     if (videoCodec_==NULL){
       printf("Could not find codec\n");
       return false;
     }
     video_st = avformat_new_stream (context_, videoCodec_);
     video_st->id = 0;
     videoCodecCtx_ = video_st->codec;
     videoCodecCtx_->codec_id = oformat_->video_codec;
     videoCodecCtx_->width = 640;
     videoCodecCtx_->height = 480;
     videoCodecCtx_->time_base = (AVRational){1,24};
     videoCodecCtx_->pix_fmt = PIX_FMT_YUV420P;
     if (oformat_->flags & AVFMT_GLOBALHEADER){
       videoCodecCtx_->flags|=CODEC_FLAG_GLOBAL_HEADER;
     }
     context_->streams[0] = video_st;
     avio_open(&context_->pb, url.c_str(), AVIO_FLAG_WRITE);
     avformat_write_header(context_, NULL);
     printf("AVFORMAT CONFIGURED\n");
   }
   in = new InputProcessor();
   MediaInfo m;
//    m.processorType = RTP_ONLY;
	m.hasVideo = false;
  m.hasAudio = true;
  if (m.hasAudio) {
    m.audioCodec.sampleRate = 8000;
		m.audioCodec.bitRate = 64000;
	}
   unpackagedBuffer_ = (unsigned char*)malloc (15000);
   gotUnpackagedFrame_ = 0;
   unpackagedSize_ = 0;
   in->init(m, this);
   return true;
  }

  ExternalOutput::~ExternalOutput(){
    printf("Destructor\n");
    this->closeSink();
  }

  void ExternalOutput::closeSink() {
    printf("ExternalOutput::closeSink\n");
    if (context_!=NULL){
      av_write_trailer(context_);
      avformat_free_context(context_);
    }
    if (unpackagedBuffer_ !=NULL){
      free(unpackagedBuffer_);
    }
    return;
  }

  void ExternalOutput::receiveRawData(RawDataPacket& packet){
    printf("rawdata received\n");
    return;
  }

	int ExternalOutput::deliverAudioData(char* buf, int len){
    printf("Deliver audio to EXTERNAL\n");
    return 0;
  }
	int ExternalOutput::deliverVideoData(char* buf, int len){
    if (in!=NULL){
        int ret = in->unpackageVideo(reinterpret_cast<unsigned char*>(buf), len,
            unpackagedBuffer_, &gotUnpackagedFrame_);
        if (ret < 0)
          return 0;
        unpackagedSize_ += ret;
        unpackagedBuffer_ += ret;
        if (gotUnpackagedFrame_) {
          unpackagedBuffer_ -= unpackagedSize_;
          AVPacket avpkt;
          av_init_packet(&avpkt);
          avpkt.data = unpackagedBuffer_;
          avpkt.size = unpackagedSize_;
          avpkt.stream_index = 0;
          av_write_frame(context_, &avpkt);
          av_free_packet(&avpkt);
          gotUnpackagedFrame_ = 0;
          unpackagedSize_ = 0;
      }
    }
    return 0;
  }

  void ExternalOutput::encodeLoop() {
    while (running == true) {
      queueMutex_.lock();
      if (packetQueue_.size() > 0) {
        op_->receiveRawData(packetQueue_.front());
        packetQueue_.pop();

        queueMutex_.unlock();
      } else {
        queueMutex_.unlock();
        usleep(1000);
      }
    }
  }

}

<commit_msg>Fixed indentation<commit_after>#include "ExternalOutput.h"
#include "../WebRtcConnection.h"
#include "../RTPSink.h"
#include <cstdio>

#include <boost/cstdint.hpp>
#include <sys/time.h>
#include <arpa/inet.h>

namespace erizo {
  ExternalOutput::ExternalOutput(std::string outputUrl){
    url = outputUrl;
    sinkfbSource_=NULL;
    unpackagedBuffer_ = NULL;
    audioSinkSSRC_ = 0;
    videoSinkSSRC_ = 0;

  }

  bool ExternalOutput::init(){
    av_register_all();
    avcodec_register_all();
    context_ = avformat_alloc_context();
    oformat_ = av_guess_format(NULL,  url.c_str(), NULL);
    if (!oformat_){
      printf("Error opening output file %s", url.c_str());
      return false;
    }
    context_->oformat = oformat_;
    url.copy(context_->filename, sizeof(context_->filename),0);
    video_st = NULL;
    audio_st = NULL;
    if (oformat_->video_codec != AV_CODEC_ID_NONE) {
      videoCodec_ = avcodec_find_encoder(oformat_->video_codec);
      printf("Found Codec %s\n", videoCodec_->name);
      if (videoCodec_==NULL){
        printf("Could not find codec\n");
        return false;
      }
      video_st = avformat_new_stream (context_, videoCodec_);
      video_st->id = 0;
      videoCodecCtx_ = video_st->codec;
      videoCodecCtx_->codec_id = oformat_->video_codec;
      videoCodecCtx_->width = 640;
      videoCodecCtx_->height = 480;
      videoCodecCtx_->time_base = (AVRational){1,24};
      videoCodecCtx_->pix_fmt = PIX_FMT_YUV420P;
      if (oformat_->flags & AVFMT_GLOBALHEADER){
        videoCodecCtx_->flags|=CODEC_FLAG_GLOBAL_HEADER;
      }
      context_->streams[0] = video_st;
      avio_open(&context_->pb, url.c_str(), AVIO_FLAG_WRITE);
      avformat_write_header(context_, NULL);
      printf("AVFORMAT CONFIGURED\n");
    }
    in = new InputProcessor();
    MediaInfo m;
    //    m.processorType = RTP_ONLY;
    m.hasVideo = false;
    m.hasAudio = true;
    if (m.hasAudio) {
      m.audioCodec.sampleRate = 8000;
      m.audioCodec.bitRate = 64000;
    }
    unpackagedBuffer_ = (unsigned char*)malloc (15000);
    gotUnpackagedFrame_ = 0;
    unpackagedSize_ = 0;
    in->init(m, this);
    return true;
  }

  ExternalOutput::~ExternalOutput(){
    printf("Destructor\n");
    this->closeSink();
  }

  void ExternalOutput::closeSink() {
    printf("ExternalOutput::closeSink\n");
    if (context_!=NULL){
      av_write_trailer(context_);
      avformat_free_context(context_);
    }
    if (unpackagedBuffer_ !=NULL){
      free(unpackagedBuffer_);
    }
    return;
  }

  void ExternalOutput::receiveRawData(RawDataPacket& packet){
    printf("rawdata received\n");
    return;
  }

  int ExternalOutput::deliverAudioData(char* buf, int len){
    printf("Deliver audio to EXTERNAL\n");
    return 0;
  }
  int ExternalOutput::deliverVideoData(char* buf, int len){
    if (in!=NULL){
      int ret = in->unpackageVideo(reinterpret_cast<unsigned char*>(buf), len,
          unpackagedBuffer_, &gotUnpackagedFrame_);
      if (ret < 0)
        return 0;
      unpackagedSize_ += ret;
      unpackagedBuffer_ += ret;
      if (gotUnpackagedFrame_) {
        unpackagedBuffer_ -= unpackagedSize_;
        AVPacket avpkt;
        av_init_packet(&avpkt);
        avpkt.data = unpackagedBuffer_;
        avpkt.size = unpackagedSize_;
        avpkt.stream_index = 0;
        av_write_frame(context_, &avpkt);
        av_free_packet(&avpkt);
        gotUnpackagedFrame_ = 0;
        unpackagedSize_ = 0;
      }
    }
    return 0;
  }

  void ExternalOutput::encodeLoop() {
    while (running == true) {
      queueMutex_.lock();
      if (packetQueue_.size() > 0) {
        op_->receiveRawData(packetQueue_.front());
        packetQueue_.pop();

        queueMutex_.unlock();
      } else {
        queueMutex_.unlock();
        usleep(1000);
      }
    }
  }

}

<|endoftext|>