<commit_before>#include "mbed.h"
#include "Simple-LoRaWAN.h"
#include "stdio.h"
#include "Gps.h"

using namespace SimpleLoRaWAN;
uint8_t appEui[8]  = { 0x3A, 0x04, 0x00, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 }; // MSBF
uint8_t devEui[8]  = { 0x77, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }; // MSBF

uint32_t devAddr    = 0xECB5C5E5;
uint8_t nwksKey[16] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }; // LSBF
uint8_t appKey[16]  = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }; // LSBF

Serial pc(USBTX, USBRX);
Serial gps_serial(p28,p27);
Gps* gps;
Ticker gps_ticker;
Ticker send_ticker;

Node* node;

uint8_t txBuffer[9];

void build_packet(Gps* gps)
{
    uint32_t LatitudeBinary, LongitudeBinary;
    uint16_t altitudeGps;
    uint8_t hdopGps;

    LatitudeBinary = ((gps->latitude_in_degrees() + 90) / 180.0) * 16777215;
    LongitudeBinary = ((gps->longitude_in_degrees() + 180) / 360.0) * 16777215;

    txBuffer[0] = ( LatitudeBinary >> 16 ) & 0xFF;
    txBuffer[1] = ( LatitudeBinary >> 8 ) & 0xFF;
    txBuffer[2] = LatitudeBinary & 0xFF;

    txBuffer[3] = ( LongitudeBinary >> 16 ) & 0xFF;
    txBuffer[4] = ( LongitudeBinary >> 8 ) & 0xFF;
    txBuffer[5] = LongitudeBinary & 0xFF;

    altitudeGps = (int) gps->altitude;
    txBuffer[6] = ( altitudeGps >> 8 ) & 0xFF;
    txBuffer[7] = altitudeGps & 0xFF;

    hdopGps = (int)gps->HDOP*10.0;
    txBuffer[8] = hdopGps & 0xFF;

    /*
    Time: 14:52:13.0
    Date: 15/10/2016
    Fix: 1
    Quality: 2
    Location: 51.173592N, 3.217686E
    HDOP:  0.87
    Speed:  0.00 knots
    Angle: 302.56
    Altitude:  6.80
    Satellites: 10
    {0xc8, 0xc7, 0xbb, 0x82, 0x49, 0xc2, 0x00, 0x06, 0x00}
    */

}

void debug_tx_buffer()
{
    for(int i = 0; i<sizeof(txBuffer); i++)
    {
        pc.printf("0x%02x ", txBuffer[i]);
    }
    pc.printf("\r\n");
}

void show_gps_info()
{
   gps->debug(&pc);
}

void send_gps_info()
{
    if(gps->fix){
        pc.printf("Sending packet:");
        build_packet(gps);
        debug_tx_buffer();
        node->send(reinterpret_cast<char*>(txBuffer), 9);
    }
}

int main(void)
{
    pc.baud(115200);
    node = new ABP::Node(devAddr, nwksKey, appKey);
    //node = new OTAA::Node(appEui, devEui, appKey);

    gps = new Gps(&gps_serial);
    gps_ticker.attach(&show_gps_info, 2.0);
    send_ticker.attach(&send_gps_info, 10.0);

    wait(1.0);

    while(true){
        node->process();
        gps->run();
    }
}
<commit_msg>moved lorawan settings to settings.h file<commit_after>#include "mbed.h"
#include "Simple-LoRaWAN.h"
#include "stdio.h"
#include "Gps.h"
#include "settings.h"

using namespace SimpleLoRaWAN;

Serial pc(USBTX, USBRX);
Serial gps_serial(p28,p27);
Gps* gps;
Ticker gps_ticker;
Ticker send_ticker;

Node* node;

uint8_t txBuffer[9];

void build_packet(Gps* gps)
{
    uint32_t LatitudeBinary, LongitudeBinary;
    uint16_t altitudeGps;
    uint8_t hdopGps;

    LatitudeBinary = ((gps->latitude_in_degrees() + 90) / 180.0) * 16777215;
    LongitudeBinary = ((gps->longitude_in_degrees() + 180) / 360.0) * 16777215;

    txBuffer[0] = ( LatitudeBinary >> 16 ) & 0xFF;
    txBuffer[1] = ( LatitudeBinary >> 8 ) & 0xFF;
    txBuffer[2] = LatitudeBinary & 0xFF;

    txBuffer[3] = ( LongitudeBinary >> 16 ) & 0xFF;
    txBuffer[4] = ( LongitudeBinary >> 8 ) & 0xFF;
    txBuffer[5] = LongitudeBinary & 0xFF;

    altitudeGps = (int) gps->altitude;
    txBuffer[6] = ( altitudeGps >> 8 ) & 0xFF;
    txBuffer[7] = altitudeGps & 0xFF;

    hdopGps = (int)gps->HDOP*10.0;
    txBuffer[8] = hdopGps & 0xFF;

    /*
    Time: 14:52:13.0
    Date: 15/10/2016
    Fix: 1
    Quality: 2
    Location: 51.173592N, 3.217686E
    HDOP:  0.87
    Speed:  0.00 knots
    Angle: 302.56
    Altitude:  6.80
    Satellites: 10
    {0xc8, 0xc7, 0xbb, 0x82, 0x49, 0xc2, 0x00, 0x06, 0x00}
    */

}

void debug_tx_buffer()
{
    for(int i = 0; i<sizeof(txBuffer); i++)
    {
        pc.printf("0x%02x ", txBuffer[i]);
    }
    pc.printf("\r\n");
}

void show_gps_info()
{
   gps->debug(&pc);
}

void send_gps_info()
{
    if(gps->fix){
        pc.printf("Sending packet:");
        build_packet(gps);
        debug_tx_buffer();
        node->send(reinterpret_cast<char*>(txBuffer), 9);
    }
}

int main(void)
{
    pc.baud(115200);
    node = new ABP::Node(devAddr, nwksKey, appKey);
    //node = new OTAA::Node(appEui, devEui, appKey);

    gps = new Gps(&gps_serial);
    gps_ticker.attach(&show_gps_info, 2.0);
    send_ticker.attach(&send_gps_info, 10.0);

    wait(1.0);

    while(true){
        node->process();
        gps->run();
    }
}
<|endoftext|>


<commit_before>/**
 * @file Cosa/Time.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2013-2014, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef COSA_TIME_HH
#define COSA_TIME_HH

#include "Cosa/Types.h"
#include "Cosa/BCD.h"
#include "Cosa/IOStream.hh"

// NTP epoch year and weekday (Monday)
const uint16_t NTP_EPOCH_YEAR = 1900;
const uint8_t  NTP_EPOCH_WEEKDAY = 2;

// POSIX epoch year and weekday (Thursday)
const uint16_t POSIX_EPOCH_YEAR = 1970;
const uint8_t  POSIX_EPOCH_WEEKDAY = 5;

// Y2K epoch year and weekday (Saturday)
const uint16_t Y2K_EPOCH_YEAR = 2000;
const uint8_t  Y2K_EPOCH_WEEKDAY = 7;

/**
 * Number of seconds elapsed since January 1 of the Epoch Year,
 * 00:00:00 +0000 (UTC).
 */
typedef uint32_t clock_t;

const uint32_t SECONDS_PER_DAY = 86400L;
const uint16_t SECONDS_PER_HOUR = 3600;
const uint8_t SECONDS_PER_MINUTE = 60;
const uint8_t DAYS_PER_WEEK = 7;

/**
 * Common date/time structure for real-time clocks. Data on some
 * devices is stored in BCD (DS1307/DS3231), although internal
 * representation is binary. Conversion methods are provided to
 * convert to/from the BCD representation. It is up the caller to keep
 * track of the representation.  All time_t methods (except
 * /to_binary/) expect the internal representation to be binary.
 */
struct time_t {
  uint8_t seconds;		//!< 00-59 Seconds.
  uint8_t minutes;		//!< 00-59 Minutes.
  uint8_t hours;		//!< 00-23 Hours.
  uint8_t day;			//!< 01-07 Day.
  uint8_t date;			//!< 01-31 Date.
  uint8_t month;		//!< 01-12 Month.
  uint8_t year;			//!< 00-99 Year.

  /**
   * Convert time to binary representation (from BCD). Apply after
   * reading from a BCD device and before any calculation.
   */
  void to_binary()
    __attribute__((always_inline))
  {
    ::to_binary(&seconds, sizeof(time_t));
  }

  /**
   * Convert time to BCD representation (from binary). Apply after
   * setting new value and before writing to a BCD device.
   */
  void to_bcd()
    __attribute__((always_inline))
  {
    ::to_bcd(&seconds, sizeof(time_t));
  }

  /**
   * Default constructor.
   */
  time_t() {}

  /**
   * Construct time record from seconds from the Epoch.
   * @param[in] c clock.
   * @param[in] zone time (hours adjustment from UTC).
   */
  time_t(clock_t c, int8_t zone = 0);

  /**
   * Convert time to clock representation.
   * @return seconds from epoch.
   */
  operator clock_t() const;

  /**
   * Set day member from time record.
   */
  void set_day()
  {
    day = weekday_for(days());
  }

  /**
   * Convert time to days.
   * @return days from January 1 of the epoch year.
   */
  uint16_t days() const;

  /**
   * Calculate day of the current year.
   * @return days from January 1, which is day zero.
   */
  uint16_t day_of_year() const;

  /**
   * Calculate 4-digit year from internal 2-digit year member.
   * @return 4-digit year.
   */
  uint16_t full_year() const { return full_year(year); }

  /**
   * Calculate 4-digit year from a 2-digit year
   * @param[in] year (4-digit).
   * @return true if /year/ is a leap year.
   */
  static uint16_t full_year( uint8_t year )
  {
    uint16_t y = year;

    if (y < pivot_year)
      y += 100 * (epoch_year()/100 + 1);
    else
      y += 100 * (epoch_year()/100);

    return y;
  }

  /**
   * Determine whether the current year is a leap year.
   * @returns true if the two-digit /year/ member is a leap year.
   */
  bool is_leap() const
  {
    return is_leap(full_year());
  }

  /**
   * Determine whether the 4-digit /year/ is a leap year.
   * @param[in] year (4-digit).
   * @return true if /year/ is a leap year.
   */
  static bool is_leap(uint16_t year)
  {
    if (year % 4) return false;
    uint16_t y = year % 400;
    return (y == 0) || ((y != 100) && (y != 200) && (y != 300));
  }

  /**
   * Calculate how many days are in the specified year.
   * @param[in] year (4-digit).
   * @return number of days.
   */
  static uint16_t days_per(uint16_t year)
  {
    return (365 + is_leap(year));
  }

  /**
   * Determine the day of the week for the specified day number
   * @param[in] day number as counted from January 1 of the epoch year.
   * @return weekday number 1..7, as for the /day/ member.
   */
  static uint8_t weekday_for(uint16_t dayno)
  {
    return ((dayno+epoch_weekday-1) % DAYS_PER_WEEK) + 1;
  }

  /**
   * Check that all members are set to a coherent date/time.
   * @return true if valid date/time.
   */
  bool is_valid() const
  {
    return
      ((year <= 99) &&
       (1 <= month) && (month <= 12) &&
       ((1 <= date) &&
	((date <= pgm_read_byte(&days_in[month])) ||
         ((month == 2) && is_leap() && (date == 29)))) &&
       (1 <= day) && (day <= 7) &&
       (hours <= 23) &&
       (minutes <= 59) &&
       (seconds <= 59));
  }

  /**
   * Set the epoch year for all time_t operations. Note that the pivot
   * year defaults to the epoch_year % 100. Valid years will be in the
   * range epoch_year..epoch_year+99. Selecting a different pivot year
   * will slide this range to the right.
   * @param[in] y epoch year to set.
   * See also /full_year/.
   */
  static void epoch_year(uint16_t y)
  {
    s_epoch_year = y;
    epoch_offset = s_epoch_year % 100;
    pivot_year = epoch_offset;
  }

  /**
   * Get the epoch year.
   * @return year.
   */
  static uint16_t epoch_year()
  {
    return (s_epoch_year);
  }

  static uint8_t epoch_weekday;

  /**
   * The pivot year determine the range of years WRT the epoch_year
   * For example, an epoch year of 2000 and a pivot year of 80 will
   * allow years in the range 1980 to 2079. Default 0 for Y2K_EPOCH.
   */
  static uint8_t pivot_year;

  /**
   * Use the current year for the epoch year. This will result in the
   * best performance, but dates/times before January 1 of this year
   * cannot be represented.
   */
  static void use_fastest_epoch();

  /**
   * Parse a character string and fill out members.
   * @param[in] s progmem character string with format "YYYY-MM-DD HH:MM:SS".
   * @return success.
   */
  bool parse(str_P s);

  static const uint8_t days_in[] PROGMEM; // month index is 1..12, PROGMEM

protected:
  static uint16_t s_epoch_year;
  static uint8_t epoch_offset;
};

/**
 * Print the date/time to the given stream with the format "YYYY-MM-DD HH:MM:SS".
 * @param[in] outs output stream.
 * @param[in] t time structure.
 * @return iostream.
 */
IOStream& operator<<(IOStream& outs, time_t& t);
#endif
<commit_msg>Add weekday symbols and clean up epoch definitions.<commit_after>/**
 * @file Cosa/Time.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2013-2014, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef COSA_TIME_HH
#define COSA_TIME_HH

#include "Cosa/Types.h"
#include "Cosa/BCD.h"
#include "Cosa/IOStream.hh"

// Weekday numbers (1..7)
enum {
  SUNDAY = 1,
  MONDAY = 2,
  TUESDAY = 3,
  WEDNESDAY = 4,
  THURSDAY = 5,
  FRIDAY = 6,
  SATURDAY = 7
};

// NTP epoch year and weekday (Monday)
const uint16_t NTP_EPOCH_YEAR = 1900;
const uint8_t  NTP_EPOCH_WEEKDAY = MONDAY;

// POSIX epoch year and weekday (Thursday)
const uint16_t POSIX_EPOCH_YEAR = 1970;
const uint8_t  POSIX_EPOCH_WEEKDAY = THURSDAY;

// Y2K epoch year and weekday (Saturday)
const uint16_t Y2K_EPOCH_YEAR = 2000;
const uint8_t  Y2K_EPOCH_WEEKDAY = SATURDAY;

/**
 * Number of seconds elapsed since January 1 of the Epoch Year,
 * 00:00:00 +0000 (UTC).
 */
typedef uint32_t clock_t;

const uint32_t SECONDS_PER_DAY = 86400L;
const uint16_t SECONDS_PER_HOUR = 3600;
const uint8_t SECONDS_PER_MINUTE = 60;
const uint8_t DAYS_PER_WEEK = 7;

/**
 * Common date/time structure for real-time clocks. Data on some
 * devices is stored in BCD (DS1307/DS3231), although internal
 * representation is binary. Conversion methods are provided to
 * convert to/from the BCD representation. It is up the caller to keep
 * track of the representation.  All time_t methods (except
 * /to_binary/) expect the internal representation to be binary.
 */
struct time_t {
  uint8_t seconds;		//!< 00-59 Seconds.
  uint8_t minutes;		//!< 00-59 Minutes.
  uint8_t hours;		//!< 00-23 Hours.
  uint8_t day;			//!< 01-07 Day.
  uint8_t date;			//!< 01-31 Date.
  uint8_t month;		//!< 01-12 Month.
  uint8_t year;			//!< 00-99 Year.

  /**
   * Convert time to binary representation (from BCD). Apply after
   * reading from a BCD device and before any calculation.
   */
  void to_binary()
    __attribute__((always_inline))
  {
    ::to_binary(&seconds, sizeof(time_t));
  }

  /**
   * Convert time to BCD representation (from binary). Apply after
   * setting new value and before writing to a BCD device.
   */
  void to_bcd()
    __attribute__((always_inline))
  {
    ::to_bcd(&seconds, sizeof(time_t));
  }

  /**
   * Default constructor.
   */
  time_t() {}

  /**
   * Construct time record from seconds from the Epoch.
   * @param[in] c clock.
   * @param[in] zone time (hours adjustment from UTC).
   */
  time_t(clock_t c, int8_t zone = 0);

  /**
   * Convert time to clock representation.
   * @return seconds from epoch.
   */
  operator clock_t() const;

  /**
   * Set day member from time record.
   */
  void set_day()
  {
    day = weekday_for(days());
  }

  /**
   * Convert time to days.
   * @return days from January 1 of the epoch year.
   */
  uint16_t days() const;

  /**
   * Calculate day of the current year.
   * @return days from January 1, which is day zero.
   */
  uint16_t day_of_year() const;

  /**
   * Calculate 4-digit year from internal 2-digit year member.
   * @return 4-digit year.
   */
  uint16_t full_year() const
  {
    return full_year(year);
  }

  /**
   * Calculate 4-digit year from a 2-digit year
   * @param[in] year (4-digit).
   * @return true if /year/ is a leap year.
   */
  static uint16_t full_year( uint8_t year )
  {
    uint16_t y = year;

    if (y < pivot_year)
      y += 100 * (epoch_year()/100 + 1);
    else
      y += 100 * (epoch_year()/100);

    return y;
  }

  /**
   * Determine whether the current year is a leap year.
   * @returns true if the two-digit /year/ member is a leap year.
   */
  bool is_leap() const
  {
    return is_leap(full_year());
  }

  /**
   * Determine whether the 4-digit /year/ is a leap year.
   * @param[in] year (4-digit).
   * @return true if /year/ is a leap year.
   */
  static bool is_leap(uint16_t year)
  {
    if (year % 4) return false;
    uint16_t y = year % 400;
    return (y == 0) || ((y != 100) && (y != 200) && (y != 300));
  }

  /**
   * Calculate how many days are in the specified year.
   * @param[in] year (4-digit).
   * @return number of days.
   */
  static uint16_t days_per(uint16_t year)
  {
    return (365 + is_leap(year));
  }

  /**
   * Determine the day of the week for the specified day number
   * @param[in] day number as counted from January 1 of the epoch year.
   * @return weekday number 1..7, as for the /day/ member.
   */
  static uint8_t weekday_for(uint16_t dayno)
  {
    return ((dayno+epoch_weekday-1) % DAYS_PER_WEEK) + 1;
  }

  /**
   * Check that all members are set to a coherent date/time.
   * @return true if valid date/time.
   */
  bool is_valid() const
  {
    return
      ((year <= 99) &&
       (1 <= month) && (month <= 12) &&
       ((1 <= date) &&
	((date <= pgm_read_byte(&days_in[month])) ||
         ((month == 2) && is_leap() && (date == 29)))) &&
       (1 <= day) && (day <= 7) &&
       (hours <= 23) &&
       (minutes <= 59) &&
       (seconds <= 59));
  }

  /**
   * Set the epoch year for all time_t operations. Note that the pivot
   * year defaults to the epoch_year % 100. Valid years will be in the
   * range epoch_year..epoch_year+99. Selecting a different pivot year
   * will slide this range to the right.
   * @param[in] y epoch year to set.
   * See also /full_year/.
   */
  static void epoch_year(uint16_t y)
  {
    s_epoch_year = y;
    epoch_offset = s_epoch_year % 100;
    pivot_year = epoch_offset;
  }

  /**
   * Get the epoch year.
   * @return year.
   */
  static uint16_t epoch_year()
  {
    return (s_epoch_year);
  }

  static uint8_t epoch_weekday;

  /**
   * The pivot year determine the range of years WRT the epoch_year
   * For example, an epoch year of 2000 and a pivot year of 80 will
   * allow years in the range 1980 to 2079. Default 0 for Y2K_EPOCH.
   */
  static uint8_t pivot_year;

  /**
   * Use the current year for the epoch year. This will result in the
   * best performance, but dates/times before January 1 of this year
   * cannot be represented.
   */
  static void use_fastest_epoch();

  /**
   * Parse a character string and fill out members.
   * @param[in] s progmem character string with format "YYYY-MM-DD HH:MM:SS".
   * @return success.
   */
  bool parse(str_P s);

  static const uint8_t days_in[] PROGMEM; // month index is 1..12, PROGMEM

protected:
  static uint16_t s_epoch_year;
  static uint8_t epoch_offset;
};

/**
 * Print the date/time to the given stream with the format "YYYY-MM-DD HH:MM:SS".
 * @param[in] outs output stream.
 * @param[in] t time structure.
 * @return iostream.
 */
IOStream& operator<<(IOStream& outs, time_t& t);
#endif
<|endoftext|>


<commit_before>#include "BitcodeArchive.h"

extern "C" {
#include <xar/xar.h>
}

#include <cstdio>
#include <fstream>
#include <fstream>
#include <iostream>
#include <streambuf>

namespace ebc {

BitcodeArchive::BitcodeArchive(std::string name, const std::uint8_t *uuid, const char *data, std::uint32_t size)
    : _name(name), _uuid(), _data(nullptr), _size(size), _metadata(nullptr) {
  std::copy(uuid, uuid + 16, _uuid);
  _data = reinterpret_cast<char *>(std::malloc(size * sizeof(char)));
  std::copy(data, data + size, _data);
  _metadata = std::make_unique<BitcodeMetadata>(GetMetadataXml());
}

BitcodeArchive::BitcodeArchive(BitcodeArchive &&bitcodeArchive)
    : _name(bitcodeArchive._name)
    , _uuid()
    , _data(bitcodeArchive._data)
    , _size(bitcodeArchive._size)
    , _metadata(std::move(bitcodeArchive._metadata)) {
  std::copy(bitcodeArchive._uuid, bitcodeArchive._uuid + 16, _uuid);
  bitcodeArchive._data = nullptr;
}

BitcodeArchive::~BitcodeArchive() {
  delete _data;
}

std::string BitcodeArchive::GetName() const {
  return _name;
}

std::string BitcodeArchive::GetUUID() const {
  auto u = _uuid;
  char buf[256];
  sprintf(buf, "%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", u[0], u[1], u[2],
          u[3], u[4], u[5], u[6], u[7], u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15]);
  return std::string(buf);
}

std::string BitcodeArchive::WriteXarToFile(std::string fileName) const {
  if (fileName.empty()) {
    fileName = _name + ".xar";
  }

  std::ofstream outfile(fileName, std::ofstream::binary);
  outfile.write(_data, _size);
  outfile.close();
  return fileName;
}

std::vector<BitcodeFile> BitcodeArchive::GetBitcodeFiles() const {
  auto files = std::vector<BitcodeFile>();

  xar_t x;
  xar_iter_t xi;
  xar_file_t xf;
  xar_stream xs;
  char buffer[8192];

  auto archivePath = WriteXarToFile();

  x = xar_open(archivePath.c_str(), READ);
  if (!x) {
    std::cerr << "Error opening archive" << std::endl;
    return files;
  }

  xi = xar_iter_new();
  if (!xi) {
    std::cerr << "Error creating xar iterator" << std::endl;
    return files;
  }

  int i = 0;
  for (xf = xar_file_first(x, xi); xf; xf = xar_file_next(xi)) {
    char *path = xar_get_path(xf);
    const char *type;
    xar_prop_get(xf, "type", &type);

    if (!type) {
      std::cerr << "File has no type" << std::endl;
      free(path);
      continue;
    }

    if (strcmp(type, "file") != 0) {
      free(path);
      continue;
    }

    if (xar_extract_tostream_init(x, xf, &xs) != XAR_STREAM_OK) {
      std::cerr << "Error initializing stream" << std::endl;
      free(path);
      continue;
    }

    // Write bitcode to file
    auto filePath = _name + "_" + std::to_string(i++) + ".bc";
    std::FILE *output = std::fopen(filePath.c_str(), "wb");
    if (!output) {
      std::cerr << "Error opening output file" << std::endl;
      continue;
    }

    xs.avail_out = sizeof(buffer);
    xs.next_out = buffer;

    int32_t ret;
    while ((ret = xar_extract_tostream(&xs)) != XAR_STREAM_END) {
      if (ret == XAR_STREAM_ERR) {
        std::cerr << "Error extracting stream" << std::endl;
        return files;
      }
      std::fwrite(buffer, sizeof(char), sizeof(buffer) - xs.avail_out, output);

      xs.avail_out = sizeof(buffer);
      xs.next_out = buffer;
    }

    if (xar_extract_tostream_end(&xs) != XAR_STREAM_OK) {
      std::cerr << "Error ending stream" << std::endl;
    }

    std::fclose(output);

    // Create bitcode file
    auto bitcodeFile = BitcodeFile(filePath);
    auto clangCommands = _metadata->GetClangCommands(path);
    bitcodeFile.SetClangCommands(clangCommands);

    // Add to list of bitcode files
    files.push_back(bitcodeFile);

    free(path);
  }

  return files;
}

const BitcodeMetadata &BitcodeArchive::GetMetadata() const {
  return *_metadata;
}

std::string BitcodeArchive::GetMetadataXml() const {
  // Write archive to filesystem and read xar
  xar_t x;
  std::string xarFile = WriteXarToFile();
  x = xar_open(xarFile.c_str(), READ);
  std::remove(xarFile.c_str());

  // Write metadata to temporary file
  std::string metadataXmlFile = _name + "_metadata.xar";
  xar_serialize(x, metadataXmlFile.c_str());

  // Read Metadata to string and remove temporary file
  std::ifstream t(metadataXmlFile);
  std::string xml((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
  std::remove(metadataXmlFile.c_str());

  return xml;
}
}
<commit_msg>Fixed xar memory leak<commit_after>#include "BitcodeArchive.h"

extern "C" {
#include <xar/xar.h>
}

#include <cstdio>
#include <fstream>
#include <fstream>
#include <iostream>
#include <streambuf>

namespace ebc {

BitcodeArchive::BitcodeArchive(std::string name, const std::uint8_t *uuid, const char *data, std::uint32_t size)
    : _name(name), _uuid(), _data(nullptr), _size(size), _metadata(nullptr) {
  std::copy(uuid, uuid + 16, _uuid);
  _data = reinterpret_cast<char *>(std::malloc(size * sizeof(char)));
  std::copy(data, data + size, _data);
  _metadata = std::make_unique<BitcodeMetadata>(GetMetadataXml());
}

BitcodeArchive::BitcodeArchive(BitcodeArchive &&bitcodeArchive)
    : _name(bitcodeArchive._name)
    , _uuid()
    , _data(bitcodeArchive._data)
    , _size(bitcodeArchive._size)
    , _metadata(std::move(bitcodeArchive._metadata)) {
  std::copy(bitcodeArchive._uuid, bitcodeArchive._uuid + 16, _uuid);
  bitcodeArchive._data = nullptr;
}

BitcodeArchive::~BitcodeArchive() {
  delete _data;
}

std::string BitcodeArchive::GetName() const {
  return _name;
}

std::string BitcodeArchive::GetUUID() const {
  auto u = _uuid;
  char buf[256];
  sprintf(buf, "%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", u[0], u[1], u[2],
          u[3], u[4], u[5], u[6], u[7], u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15]);
  return std::string(buf);
}

std::string BitcodeArchive::WriteXarToFile(std::string fileName) const {
  if (fileName.empty()) {
    fileName = _name + ".xar";
  }

  std::ofstream outfile(fileName, std::ofstream::binary);
  outfile.write(_data, _size);
  outfile.close();
  return fileName;
}

std::vector<BitcodeFile> BitcodeArchive::GetBitcodeFiles() const {
  auto files = std::vector<BitcodeFile>();

  xar_t x;
  xar_iter_t xi;
  xar_file_t xf;
  xar_stream xs;
  char buffer[8192];

  auto archivePath = WriteXarToFile();

  x = xar_open(archivePath.c_str(), READ);
  if (!x) {
    std::cerr << "Error opening archive" << std::endl;
    return files;
  }

  xi = xar_iter_new();
  if (!xi) {
    std::cerr << "Error creating xar iterator" << std::endl;
    xar_close(x);
    return files;
  }

  int i = 0;
  for (xf = xar_file_first(x, xi); xf; xf = xar_file_next(xi)) {
    char *path = xar_get_path(xf);
    const char *type;
    xar_prop_get(xf, "type", &type);

    if (!type) {
      std::cerr << "File has no type" << std::endl;
      free(path);
      continue;
    }

    if (strcmp(type, "file") != 0) {
      free(path);
      continue;
    }

    if (xar_extract_tostream_init(x, xf, &xs) != XAR_STREAM_OK) {
      std::cerr << "Error initializing stream" << std::endl;
      free(path);
      continue;
    }

    // Write bitcode to file
    auto filePath = _name + "_" + std::to_string(i++) + ".bc";
    std::FILE *output = std::fopen(filePath.c_str(), "wb");
    if (!output) {
      std::cerr << "Error opening output file" << std::endl;
      continue;
    }

    xs.avail_out = sizeof(buffer);
    xs.next_out = buffer;

    int32_t ret;
    while ((ret = xar_extract_tostream(&xs)) != XAR_STREAM_END) {
      if (ret == XAR_STREAM_ERR) {
        std::cerr << "Error extracting stream" << std::endl;
        free(path);
        break;
      }
      std::fwrite(buffer, sizeof(char), sizeof(buffer) - xs.avail_out, output);

      xs.avail_out = sizeof(buffer);
      xs.next_out = buffer;
    }

    if (xar_extract_tostream_end(&xs) != XAR_STREAM_OK) {
      std::cerr << "Error ending stream" << std::endl;
    }

    std::fclose(output);

    // Create bitcode file
    auto bitcodeFile = BitcodeFile(filePath);
    auto clangCommands = _metadata->GetClangCommands(path);
    bitcodeFile.SetClangCommands(clangCommands);

    // Add to list of bitcode files
    files.push_back(bitcodeFile);

    free(path);
  }
  xar_iter_free(xi);
  xar_close(x);

  return files;
}

const BitcodeMetadata &BitcodeArchive::GetMetadata() const {
  return *_metadata;
}

std::string BitcodeArchive::GetMetadataXml() const {
  std::string xarFile = WriteXarToFile();
  std::string metadataXmlFile = _name + "_metadata.xar";

  // Write archive to filesystem and read xar
  xar_t x = xar_open(xarFile.c_str(), READ);
  xar_serialize(x, metadataXmlFile.c_str());
  xar_close(x);
  std::remove(xarFile.c_str());

  // Read Metadata to string and remove temporary file
  std::ifstream t(metadataXmlFile);
  std::string xml((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
  std::remove(metadataXmlFile.c_str());

  return xml;
}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <string.h>
#include <boost/tokenizer.hpp>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdio>

using namespace std;
using namespace boost;

void get_input(string usr_input)
{
	char arr[10000];//tokenize
	char* argv[10000];
	char* con_arr[10000];//stores connectors
	for(unsigned i = 0; i < 10000; i++)
	{
		arr[i] = 0;
		argv[i] = 0;
		con_arr[i] = 0;
	}
	for(unsigned i = 0; i < usr_input.size(); i++)
	{
		arr[i] = usr_input[i];
	}
	char* tok = strtok(arr, " \t");
	vector<int> cmd_arg_amt;
	int x = 0;
	while(tok != NULL)
	{
		argv[x] = tok;
		x++;
		tok = strtok(NULL, " \t");
	}
	argv[x] = '\0';

	int con_amount = 0;
	int hold_amt = 0;
	for(int i = 0; i < x; i++)
	{
		if(strcmp(argv[i], "&&") || strcmp(argv[i], "||") || strcmp(argv[i], ";"))
		{
			cmd_arg_amt.push_back(hold_amt);//push back the number of arguments for a certain command
			hold_amt = 0;
			con_amount++;
		}
		else if(strcmp(argv[i], "#"))
		{
			cmd_arg_amt.push_back(hold_amt);
			hold_amt = 0;
			con_amount++;
			break;
		}
	}
	if(hold_amt > 0)
	{
		cmd_arg_amt.push_back(hold_amt);
		hold_amt = 0;
	}
	bool com_end = false;
	int a = 0;
	int place = 0;
	int executive;
	int con_place = 0;
	vector<int> places_con;//where connectors are
	while(argv[place] != NULL)
	{
		char *sc = strstr(argv[place], ";");//semicolon
		char *as = strstr(argv[place], "&&");//ampersands
		char *pi = strstr(argv[place], "||");//pipes
		char *hs = strstr(argv[place], "#");//hash
		if(!strcmp(argv[place] , ";") || !strcmp(argv[place] , "&&") || !strcmp(argv[place] , "||") || !strcmp(argv[place] , "#"))
		{
			con_arr[con_place] = argv[place];
			con_place++;
			place++;
		}
		else if(sc != NULL)
		{
			con_arr[con_place] = sc;
			con_place++;
			places_con.push_back(place);
			place++;
		}
		else if(as != NULL)
		{
			con_arr[con_place] = as;
			con_place++;
			place++;
			places_con.push_back(place);
		}
		else if(pi != NULL)
		{
			con_arr[con_place] = pi;
			con_place++;
			place++;
			places_con.push_back(place);
		}
		else if(hs != NULL)
		{
			con_arr[con_place] = hs;
			con_place++;
			place++;
			places_con.push_back(place);
		}
		else
		{
			place++;
		}
	}
	char* aargv = strtok(arr, "#;|& ");
	int l = 0;
	while(aargv != NULL)
	{
		argv[l] = aargv;
		l++;
		aargv = strtok(NULL, "#;|& ");
	}
	l = 0;
	con_arr[con_place] = NULL;
	place = 0;
	bool exec_works = true;
	while(a <= con_place && !com_end)
	{
		exec_works = true;
		char* run[10000];
		for(unsigned i = 0; i < 10000; i++)
		{
			run[i] = 0;
		}
		int b = 0;
		b = 0;
		bool stop = false;
		while(!stop && argv[place] != NULL)
		{
			if(!strcmp(argv[place] , ";") || !strcmp(argv[place] , "&&") || !strcmp(argv[place] , "||") || !strcmp(argv[place] , "#") )
			{
				place++;
				break;
				stop = true;
			}
			else
			{
				run[b] = argv[place];
				b++;
				place++;
			}
		}
		for(int i = 0; i < b; i++)
		{
			if(!strcmp(run[i], ";") || !strcmp(run[i], "&&") || !strcmp(run[i], "||") || !strcmp(run[i], "#") )
			{
				run[i] = NULL;
			}
		}
		run[b] = NULL;
		int pid = fork();
		for(int i = 0; i < b; i++)
		{
			if(!strcmp(run[i], "exit"))
			{
				exit(0);
			}
		}
		if(pid == -1)
		{
			perror("fork");
			exit(1);
		}
		else if(pid == 0)
		{
			executive = execvp(run[0], run);
			exec_works = executive;
			if(executive == -1)
			{
				exec_works = false;
				perror("execvp");
			}
			else
			{
				exec_works = true;
			}
		}
		else if(pid > 0)
		{
			if(-1 == wait(0))
			{
				perror("wait");
			}
		}
		if(con_arr[a] == NULL)
		{
			com_end = true;
			break;
		}
		else if(!strcmp(con_arr[a], "||"))
		{
			if(exec_works)
			{
				com_end = true;
				break;
			}
		}
		else if(!strcmp(con_arr[a], "&&"))
		{
			if(!exec_works)
			{
				com_end = true;
				break;
			}
		}
		else if(!strcmp(con_arr[a], ";"))
		{
		}
		else if(!strcmp(con_arr[a], "#"))
		{
			com_end = true;
			break;
		}
		a++;
	}
}

void output()
{
	char host[255];
	string login = getlogin();
	gethostname(host, 255);
	cout << login << "@" << host << " ";
	string usr_input;
	cout << "$";
	cout << " ";
	getline(cin, usr_input);
	get_input(usr_input);
}

int main(int argc, char *argv[])
{
	while(1)
	{
		output();
	}
	return 0;
}
<commit_msg>Fixed exit<commit_after>#include <iostream>
#include <string>
#include <string.h>
#include <boost/tokenizer.hpp>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdio>

using namespace std;
using namespace boost;

void exiting(char *in)
{
	if(!strcmp(in, "exit"))
	{
		exit(0);
	}
}
void get_input(string usr_input)
{
	bool exit_now = false;
	size_t pos = usr_input.find("exit");
	//cout << "pos" << pos << endl;
	if(pos > 0 && pos < 1000)
	{
		exit(0);
	}
	char arr[10000];//tokenize
	char* argv[10000];
	char* con_arr[10000];//stores connectors
	for(unsigned i = 0; i < 10000; i++)
	{
		arr[i] = 0;
		argv[i] = 0;
		con_arr[i] = 0;
	}
	for(unsigned i = 0; i < usr_input.size(); i++)
	{
		arr[i] = usr_input[i];
	}
	char* tok = strtok(arr, " \t");
	vector<int> cmd_arg_amt;
	int x = 0;
	while(tok != NULL)
	{
		argv[x] = tok;
		x++;
		tok = strtok(NULL, " \t");
	}
	argv[x] = '\0';
	x = 0;

	int con_amount = 0;
	int hold_amt = 0;
	for(int i = 0; i < x; i++)
	{
		if(strcmp(argv[i], "&&") || strcmp(argv[i], "||") || strcmp(argv[i], ";"))
		{
			cmd_arg_amt.push_back(hold_amt);//push back the number of arguments for a certain command
			hold_amt = 0;
			con_amount++;
		}
		else if(strcmp(argv[i], "#"))
		{
			cmd_arg_amt.push_back(hold_amt);
			hold_amt = 0;
			con_amount++;
			break;
		}
		else if(strcmp(argv[i], "exit"))
		{
			exit(0);
		}
	}
	if(hold_amt > 0)
	{
		cmd_arg_amt.push_back(hold_amt);
		hold_amt = 0;
	}
	bool com_end = false;
	int a = 0;
	int place = 0;
	int executive;
	int con_place = 0;
	vector<int> places_con;//where connectors are
	while(argv[place] != NULL)
	{
		char *sc = strstr(argv[place], ";");//semicolon
		char *as = strstr(argv[place], "&&");//ampersands
		char *pi = strstr(argv[place], "||");//pipes
		char *hs = strstr(argv[place], "#");//hash
		if(!strcmp(argv[place] , ";") || !strcmp(argv[place] , "&&") || !strcmp(argv[place] , "||") || !strcmp(argv[place] , "#"))
		{
			con_arr[con_place] = argv[place];
			con_place++;
			place++;
		}
		else if(sc != NULL)
		{
			con_arr[con_place] = sc;
			con_place++;
			places_con.push_back(place);
			place++;
		}
		else if(as != NULL)
		{
			con_arr[con_place] = as;
			con_place++;
			place++;
			places_con.push_back(place);
		}
		else if(pi != NULL)
		{
			con_arr[con_place] = pi;
			con_place++;
			place++;
			places_con.push_back(place);
		}
		else if(hs != NULL)
		{
			con_arr[con_place] = hs;
			con_place++;
			place++;
			places_con.push_back(place);
		}
		else
		{
			place++;
		}
	}
	char* aargv = strtok(arr, "#;|& ");
	int l = 0;
	while(aargv != NULL)
	{
		argv[l] = aargv;
		l++;
		aargv = strtok(NULL, "#;|& ");
	}
	l = 0;
	con_arr[con_place] = NULL;
	place = 0;
	bool exec_works = true;
	while(a <= con_place && !com_end)
	{
		exec_works = true;
		char* run[10000];
		for(unsigned i = 0; i < 10000; i++)
		{
			run[i] = 0;
		}
		int b = 0;
		b = 0;
		bool stop = false;
		while(!stop && argv[place] != NULL)
		{
			if(!strcmp(argv[place] , ";") || !strcmp(argv[place] , "&&") || !strcmp(argv[place] , "||") || !strcmp(argv[place] , "#") )
			{
				place++;
				break;
				stop = true;
			}
			else
			{
				run[b] = argv[place];
				b++;
				place++;
			}
		}
		for(int i = 0; i < b; i++)
		{
			if(!strcmp(run[i], ";") || !strcmp(run[i], "&&") || !strcmp(run[i], "||") || !strcmp(run[i], "#") )
			{
				run[i] = NULL;
			}
		}
		run[b] = NULL;
		int pid = fork();
		for(int i = 0; i < b; i++)
		{
			if(!strcmp(run[i], "exit"))
			{
				exit(0);
			}
		}
		if(pid == -1)
		{
			perror("fork");
			exit(1);
		}
		else if(pid == 0)
		{
			exit_now = true;
			//exiting(run[0]);
			executive = execvp(run[0], run);
			exec_works = executive;
			if(executive == -1)
			{
				exec_works = false;
				perror("execvp");
			}
			else
			{
				exec_works = true;
			}
		}
		else if(pid > 0)
		{
			//exiting(run[0]);

			if(-1 == wait(0))
				perror("wait");
		}
		//exiting(run[0]);
		if(con_arr[a] == NULL)
		{
			com_end = true;
			break;
		//	exit(0);
		}
		else if(!strcmp(con_arr[a], "||"))
		{
			if(exec_works)
			{
				com_end = true;
				break;
				//exit(0);
			}
		}
		else if(!strcmp(con_arr[a], "&&"))
		{
			if(!exec_works)
			{
				com_end = true;
				break;
			//	exit(0);
			}
		}
		else if(!strcmp(con_arr[a], ";"))
		{
		}
		else if(!strcmp(con_arr[a], "#"))
		{
			com_end = true;
			break;
			//exit(0);
		}
		/*
		if(exec_works == false && com_end == true)
		{
			exit(1);
		}
		*/
		a++;
	}
	if(exit_now)
	{
		exit(1);
	}
}

void output()
{
	char host[255];
	string login = getlogin();
	gethostname(host, 255);
	cout << login << "@" << host << " ";
	string usr_input;
	size_t poso = usr_input.find("exit");
	if(poso > 0 && poso < 1000)
	{
		exit(0);
	}
	cout << "$";
	cout << " ";
	getline(cin, usr_input);
	get_input(usr_input);
}

int main(int argc, char *argv[])
{
	while(1)
	{
		output();
	}
	return 0;
}
<|endoftext|>


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

#include <iostream>
#include <time.h>
#include <Dates.h>

static const char* days[] =
{
  "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday",
};

static const char* days_short[] =
{
  "sun", "mon", "tue", "wed", "thu", "fri", "sat",
};

static const char* months[] =
{
  "january", "february", "march", "april", "may", "june",
  "july", "august", "september", "october", "november", "december",
};

static const char* months_short[] =
{
  "jan", "feb", "mar", "apr", "may", "jun",
  "jul", "aug", "sep", "oct", "nov", "dec",
};

static int month_days[12] =
{
  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
};

////////////////////////////////////////////////////////////////////////////////
static bool isMonth (const std::string& name, int& i)
{
  for (i = 0; i < 12; i++)
    if (name == months[i] || name == months_short[i])
      return true;

  return false;
}

////////////////////////////////////////////////////////////////////////////////
static bool isDay (const std::string& name, int& i)
{
  for (i = 0; i < 7; i++)
    if (name == days[i] || name == days_short[i])
      return true;

  return false;
}

////////////////////////////////////////////////////////////////////////////////
static bool leapYear (int year)
{
  return ((!(year % 4)) && (year % 100)) ||
         (!(year % 400));
}

////////////////////////////////////////////////////////////////////////////////
static int daysInMonth (int year, int month)
{
  if (month == 2 && leapYear (year))
    return 29;

  return month_days[month - 1];
}

////////////////////////////////////////////////////////////////////////////////
// now            = current date/time.
// today          = previous midnight.
// sod            = previous midnight.
// yesterday      = 2nd previous midnight.
// tomorrow       = next midnight.
// eod            = next midnight.
// <day>          = midnight at start of next <day>.
// <month>        = midnight on the 1st of <month>.
// soy            = midnight on January 1st, <year>.
// eoy            = midnight on December 31st, <year>.
// socm           = midnight on the 1st of current month.
// som            = midnight on the 1st of next month.
// eom            = midnight on the 1st of the next month.
// eocm           = midnight on the 1st of the next month.
// sow            =
// eow            =
// eocw           =
// socw           =
// soww           =
// eoww           =
// soq            =
// eoq            =
// later          = midnight, Jan 18th, 2038.
// someday        = midnight, Jan 18th, 2038.
// easter         =
// eastermonday   =
// ascension      =
// pentecost      =
// goodfriday     =
// midsommar      =
// midsommarafton =
// Nth            =

bool namedDates (const std::string& name, Variant& value)
{
  time_t now = time (NULL);
  int i;

  // TODO Extract helper functions from this code.

  // Dynamics.
  if (name == "now")
  {
    value = Variant (now, Variant::type_date);
  }

  else if (name == "today" || name == "sod")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "yesterday")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    value = Variant (mktime (t) - 86400, Variant::type_date);
  }

  else if (name == "tomorrow" || name == "eod")
  {
    struct tm* t = localtime (&now);
    t->tm_mday++;
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (isDay (name, i))
  {
    struct tm* t = localtime (&now);

    if (t->tm_wday >= i)
      t->tm_mday += i - t->tm_wday + 7;
    else
      t->tm_mday += i - t->tm_wday;

    t->tm_hour = t->tm_min = t->tm_sec = 0;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (isMonth (name, i))
  {
    struct tm* t = localtime (&now);
    if (t->tm_mon >= i)
      t->tm_year++;

    t->tm_mon = i;
    t->tm_mday = 1;
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "soy")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    t->tm_mon = 0;
    t->tm_mday = 1;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "eoy")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    t->tm_mon = 11;
    t->tm_mday = 31;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "socm")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    t->tm_mday = 1;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "som")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;

    t->tm_mon++;
    if (t->tm_mon == 12)
    {
      t->tm_year++;
      t->tm_mon = 0;
    }

    t->tm_mday = 1;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "eom" || name == "eocm")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    t->tm_mday = daysInMonth (t->tm_year + 1900, t->tm_mon + 1);
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "sow")
  {
/*
    Date sow (_t);
    sow -= (dayOfWeek () * 86400);
    return Date (sow.month (), sow.day (), sow.year (), 0, 0, 0);
*/
  }

  else if (name == "eow" || name == "eocw")
  {
/*
    if (found == "eow" || found == "eoww")
      dow = 5;
*/
  }

  else if (name == "socw")
  {
/*
    Date sow (_t);
    sow -= (dayOfWeek () * 86400);
    return Date (sow.month (), sow.day (), sow.year (), 0, 0, 0);
*/
  }

  else if (name == "soww")
  {
/*
    Date sow (_t);
    sow -= (dayOfWeek () * 86400);
    return Date (sow.month (), sow.day (), sow.year (), 0, 0, 0);
*/
  }

  else if (name == "eoww")
  {
/*
    if (found == "eow" || found == "eoww")
      dow = 5;
*/
  }

  else if (name == "soq" || name == "eoq")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;

    t->tm_mon += 3 - (t->tm_mon % 3);
    if (t->tm_mon > 11)
    {
      t->tm_mon -= 12;
      ++t->tm_year;
    }

    // TODO eoq: should be 24:00:00
    // t->tm_mday = daysInMonth (t->tm_year + 1900, t->tm_mon + 1);

    t->tm_mday = 1;

    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "later" || name == "someday")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    t->tm_year = 138;
    t->tm_mon = 0;
    t->tm_mday = 18;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "easter"       ||
           name == "eastermonday" ||
           name == "ascension"    ||
           name == "pentecost"    ||
           name == "goodfriday")
  {
    struct tm* t = localtime (&now);

    int Y = t->tm_year + 1900;
    int a = Y % 19;
    int b = Y / 100;
    int c = Y % 100;
    int d = b / 4;
    int e = b % 4;
    int f = (b + 8) / 25;
    int g = (b - f + 1) / 3;
    int h = (19 * a + b - d - g + 15) % 30;
    int i = c / 4;
    int k = c % 4;
    int L = (32 + 2 * e + 2 * i - h - k) % 7;
    int m = (a + 11 * h + 22 * L) / 451;
    int month = (h + L - 7 * m + 114) / 31;
    int day = ((h + L - 7 * m + 114) % 31) + 1;

    t->tm_isdst = -1;   // Requests that mktime determine summer time effect.
    t->tm_mday  = day;
    t->tm_mon   = month - 1;
    t->tm_year  = Y - 1900;

         if (name == "goodfriday")   t->tm_mday -= 2;
    else if (name == "eastermonday") t->tm_mday += 1;
    else if (name == "ascension")    t->tm_mday += 39;
    else if (name == "pentecost")    t->tm_mday += 49;

    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "midsommar")
  {
/*
    for (int midsommar = 20; midsommar <= 26; midsommar++)
    {
      Date then (6, midsommar, today.year ());
      if (6 == then.dayOfWeek ())
      {
        _t = then._t;
        return true;
      }
    }
*/
  }

  else if (name == "midsommarafton")
  {
/*
    for (int midsommar = 19; midsommar <= 25; midsommar++)
    {
      Date then (6, midsommar, today.year ());
      if (5 == then.dayOfWeek ())
      {
        _t = then._t;
        return true;
      }
    }
*/
  }

  // 1st
  // 2nd
  // 3rd
  else if (name == "????")
  {
/*
    int number;
    std::string ordinal;

    if (isdigit (in[1]))
    {
      number = atoi (in.substr (0, 2).c_str ());
      ordinal = lowerCase (in.substr (2));
    }
    else
    {
      number = atoi (in.substr (0, 2).c_str ());
      ordinal = lowerCase (in.substr (1));
    }

    // Sanity check.
    if (number <= 31)
    {
      if (ordinal == "st" ||
          ordinal == "nd" ||
          ordinal == "rd" ||
          ordinal == "th")
      {
        int m = today.month ();
        int d = today.day ();
        int y = today.year ();

        // If it is this month.
        if (d < number &&
            number <= Date::daysInMonth (m, y))
        {
          Date then (m, number, y);
          _t = then._t;
          return true;
        }

        do
        {
          m++;

          if (m > 12)
          {
            m = 1;
            y++;
          }
        }
        while (number > Date::daysInMonth (m, y));

        Date then (m, number, y);
        _t = then._t;
        return true;
      }
    }
*/
  }

  else
    return false;

  return true;
}

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

<commit_msg>Dates<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2013 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <iostream>
#include <time.h>
#include <text.h>
#include <Dates.h>

static const char* days[] =
{
  "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday",
};

static const char* days_short[] =
{
  "sun", "mon", "tue", "wed", "thu", "fri", "sat",
};

static const char* months[] =
{
  "january", "february", "march", "april", "may", "june",
  "july", "august", "september", "october", "november", "december",
};

static const char* months_short[] =
{
  "jan", "feb", "mar", "apr", "may", "jun",
  "jul", "aug", "sep", "oct", "nov", "dec",
};

static int month_days[12] =
{
  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
};

////////////////////////////////////////////////////////////////////////////////
static bool isMonth (const std::string& name, int& i)
{
  for (i = 0; i < 12; i++)
    if (name == months[i] || name == months_short[i])
      return true;

  return false;
}

////////////////////////////////////////////////////////////////////////////////
static bool isDay (const std::string& name, int& i)
{
  for (i = 0; i < 7; i++)
    if (name == days[i] || name == days_short[i])
      return true;

  return false;
}

////////////////////////////////////////////////////////////////////////////////
static bool leapYear (int year)
{
  return ((!(year % 4)) && (year % 100)) ||
         (!(year % 400));
}

////////////////////////////////////////////////////////////////////////////////
static int daysInMonth (int year, int month)
{
  if (month == 2 && leapYear (year))
    return 29;

  return month_days[month - 1];
}

////////////////////////////////////////////////////////////////////////////////
// now            = current date/time.
// today          = previous midnight.
// sod            = previous midnight.
// yesterday      = 2nd previous midnight.
// tomorrow       = next midnight.
// eod            = next midnight.
// <day>          = midnight at start of next <day>.
// <month>        = midnight on the 1st of <month>.
// soy            = midnight on January 1st, <year>.
// eoy            = midnight on December 31st, <year>.
// socm           = midnight on the 1st of current month.
// som            = midnight on the 1st of next month.
// eom            = midnight on the 1st of the next month.
// eocm           = midnight on the 1st of the next month.
// sow            =
// eow            =
// eocw           =
// socw           =
// soww           =
// eoww           =
// soq            =
// eoq            =
// later          = midnight, Jan 18th, 2038.
// someday        = midnight, Jan 18th, 2038.
// easter         =
// eastermonday   =
// ascension      =
// pentecost      =
// goodfriday     =
// midsommar      =
// midsommarafton =
// Nth            =

bool namedDates (const std::string& name, Variant& value)
{
  time_t now = time (NULL);
  int i;

  // TODO Extract helper functions from this code.

  // Dynamics.
  if (name == "now")
  {
    value = Variant (now, Variant::type_date);
  }

  else if (name == "today" || name == "sod")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "yesterday")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    value = Variant (mktime (t) - 86400, Variant::type_date);
  }

  else if (name == "tomorrow" || name == "eod")
  {
    struct tm* t = localtime (&now);
    t->tm_mday++;
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (isDay (name, i))
  {
    struct tm* t = localtime (&now);

    if (t->tm_wday >= i)
      t->tm_mday += i - t->tm_wday + 7;
    else
      t->tm_mday += i - t->tm_wday;

    t->tm_hour = t->tm_min = t->tm_sec = 0;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (isMonth (name, i))
  {
    struct tm* t = localtime (&now);
    if (t->tm_mon >= i)
      t->tm_year++;

    t->tm_mon = i;
    t->tm_mday = 1;
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "soy")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    t->tm_mon = 0;
    t->tm_mday = 1;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "eoy")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    t->tm_mon = 11;
    t->tm_mday = 31;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "socm")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    t->tm_mday = 1;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "som")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;

    t->tm_mon++;
    if (t->tm_mon == 12)
    {
      t->tm_year++;
      t->tm_mon = 0;
    }

    t->tm_mday = 1;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "eom" || name == "eocm")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    t->tm_mday = daysInMonth (t->tm_year + 1900, t->tm_mon + 1);
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "sow")
  {
/*
    Date sow (_t);
    sow -= (dayOfWeek () * 86400);
    return Date (sow.month (), sow.day (), sow.year (), 0, 0, 0);
*/
  }

  else if (name == "eow" || name == "eocw")
  {
/*
    if (found == "eow" || found == "eoww")
      dow = 5;
*/
  }

  else if (name == "socw")
  {
/*
    Date sow (_t);
    sow -= (dayOfWeek () * 86400);
    return Date (sow.month (), sow.day (), sow.year (), 0, 0, 0);
*/
  }

  else if (name == "soww")
  {
/*
    Date sow (_t);
    sow -= (dayOfWeek () * 86400);
    return Date (sow.month (), sow.day (), sow.year (), 0, 0, 0);
*/
  }

  else if (name == "eoww")
  {
/*
    if (found == "eow" || found == "eoww")
      dow = 5;
*/
  }

  else if (name == "soq" || name == "eoq")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;

    t->tm_mon += 3 - (t->tm_mon % 3);
    if (t->tm_mon > 11)
    {
      t->tm_mon -= 12;
      ++t->tm_year;
    }

    // TODO eoq: should be 24:00:00
    // t->tm_mday = daysInMonth (t->tm_year + 1900, t->tm_mon + 1);

    t->tm_mday = 1;

    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "later" || name == "someday")
  {
    struct tm* t = localtime (&now);
    t->tm_hour = t->tm_min = t->tm_sec = 0;
    t->tm_year = 138;
    t->tm_mon = 0;
    t->tm_mday = 18;
    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "easter"       ||
           name == "eastermonday" ||
           name == "ascension"    ||
           name == "pentecost"    ||
           name == "goodfriday")
  {
    struct tm* t = localtime (&now);

    int Y = t->tm_year + 1900;
    int a = Y % 19;
    int b = Y / 100;
    int c = Y % 100;
    int d = b / 4;
    int e = b % 4;
    int f = (b + 8) / 25;
    int g = (b - f + 1) / 3;
    int h = (19 * a + b - d - g + 15) % 30;
    int i = c / 4;
    int k = c % 4;
    int L = (32 + 2 * e + 2 * i - h - k) % 7;
    int m = (a + 11 * h + 22 * L) / 451;
    int month = (h + L - 7 * m + 114) / 31;
    int day = ((h + L - 7 * m + 114) % 31) + 1;

    t->tm_isdst = -1;   // Requests that mktime determine summer time effect.
    t->tm_mday  = day;
    t->tm_mon   = month - 1;
    t->tm_year  = Y - 1900;

         if (name == "goodfriday")   t->tm_mday -= 2;
    else if (name == "eastermonday") t->tm_mday += 1;
    else if (name == "ascension")    t->tm_mday += 39;
    else if (name == "pentecost")    t->tm_mday += 49;

    value = Variant (mktime (t), Variant::type_date);
  }

  else if (name == "midsommar")
  {
/*
    for (int midsommar = 20; midsommar <= 26; midsommar++)
    {
      Date then (6, midsommar, today.year ());
      if (6 == then.dayOfWeek ())
      {
        _t = then._t;
        return true;
      }
    }
*/
  }

  else if (name == "midsommarafton")
  {
/*
    for (int midsommar = 19; midsommar <= 25; midsommar++)
    {
      Date then (6, midsommar, today.year ());
      if (5 == then.dayOfWeek ())
      {
        _t = then._t;
        return true;
      }
    }
*/
  }

  // Support "21st" to indicate the next date that is the 21st day.
  // 1st
  // 2nd
  // 3rd
  else if (name.length () >= 3 &&
           name.length () <= 4 &&
           isdigit (name[0]))
  {
    int number;
    std::string ordinal;

    if (isdigit (name[1]))
    {
      number = atoi (name.substr (0, 2).c_str ());
      ordinal = lowerCase (name.substr (2));
    }
    else
    {
      number = atoi (name.substr (0, 2).c_str ());
      ordinal = lowerCase (name.substr (1));
    }

    // Sanity check.
    if (number <= 31)
    {
      if (ordinal == "st" ||
          ordinal == "nd" ||
          ordinal == "rd" ||
          ordinal == "th")
      {
        struct tm* t = localtime (&now);
        int y = t->tm_year + 1900;
        int m = t->tm_mon + 1;
        int d = t->tm_mday;

        // If it is this month.
        if (d < number &&
            number <= daysInMonth (m, y))
        {
          t->tm_hour = t->tm_min = t->tm_sec = 0;
          t->tm_mon  = m - 1;
          t->tm_mday = number;
          t->tm_year = y - 1900;
          value = Variant (mktime (t), Variant::type_date);
          return true;
        }

        do
        {
          m++;

          if (m > 12)
          {
            m = 1;
            y++;
          }
        }
        while (number > daysInMonth (m, y));

        t->tm_hour = t->tm_min = t->tm_sec = 0;
        t->tm_mon  = m - 1;
        t->tm_mday = number;
        t->tm_year = y - 1900;
        value = Variant (mktime (t), Variant::type_date);
        return true;
      }
    }
  }

  else
    return false;

  return true;
}

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

<|endoftext|>


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

#include "Vaca/Debug.h"
#include "Vaca/Mutex.h"
#include "Vaca/ScopedLock.h"
#include "Vaca/System.h"
#include "Vaca/Thread.h"

using namespace Vaca;

#ifndef NDEBUG
struct Debug;

static bool closed;
static Debug* dbg;

struct Debug {
  Mutex mutex;
  FILE* file;
  Debug() {
    file = fopen("vaca.log", "w");
    fprintf(file, "Log file created\n");
  }
  virtual ~Debug() {
    fprintf(file, "Log file closed\n");
    fclose(file);
    file = NULL;
    closed = true;
  }
};
#endif

void Vaca::details::trace(LPCSTR filename, UINT line, LPCSTR fmt, ...)
{
#ifndef NDEBUG
  if (closed) { return; }
  if (!dbg) { dbg = new Debug; }

  ScopedLock hold(dbg->mutex);
  char buf[1024];		// TODO: overflow
  va_list ap;

  va_start(ap, fmt);
  vsprintf(buf, fmt, ap);
  va_end(ap);

  fprintf(dbg->file, "%s:%d: [%d] %s", filename, line,
	  static_cast<unsigned>(::GetCurrentThreadId()), buf);
  fflush(dbg->file);
#endif
}

void Vaca::details::closeLogFile()
{
#ifndef NDEBUG
  delete dbg;
  dbg = NULL;
#endif
}
<commit_msg>Fixed some compilation errors including std namespace for <cstdio><commit_after>// Vaca - Visual Application Components Abstraction
// Copyright (c) 2005-2009 David Capello
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in
//   the documentation and/or other materials provided with the
//   distribution.
// * Neither the name of the author nor the names of its contributors
//   may be used to endorse or promote products derived from this
//   software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#include "Vaca/Debug.h"
#include "Vaca/Mutex.h"
#include "Vaca/ScopedLock.h"
#include "Vaca/System.h"
#include "Vaca/Thread.h"

#include <cstdio>

using namespace std;
using namespace Vaca;

#ifndef NDEBUG
struct Debug;

static bool closed;
static Debug* dbg;

struct Debug {
  Mutex mutex;
  FILE* file;
  Debug() {
    file = fopen("vaca.log", "w");
    fprintf(file, "Log file created\n");
  }
  virtual ~Debug() {
    fprintf(file, "Log file closed\n");
    fclose(file);
    file = NULL;
    closed = true;
  }
};
#endif

void Vaca::details::trace(LPCSTR filename, UINT line, LPCSTR fmt, ...)
{
#ifndef NDEBUG
  if (closed) { return; }
  if (!dbg) { dbg = new Debug; }

  ScopedLock hold(dbg->mutex);
  char buf[1024];		// TODO: overflow
  va_list ap;

  va_start(ap, fmt);
  vsprintf(buf, fmt, ap);
  va_end(ap);

  fprintf(dbg->file, "%s:%d: [%d] %s", filename, line,
	  static_cast<unsigned>(::GetCurrentThreadId()), buf);
  fflush(dbg->file);
#endif
}

void Vaca::details::closeLogFile()
{
#ifndef NDEBUG
  delete dbg;
  dbg = NULL;
#endif
}
<|endoftext|>


<commit_before><commit_msg>rados: accept '-b' as an argument.<commit_after><|endoftext|>


<commit_before>#include <vector>
#include <array>
#include <map>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <tuple>
#include <glm/glm.hpp>
#include <SDL.h>
#include "gl_core_3_3.h"
#include "util.h"

std::string util::read_file(const std::string &fName){
	std::ifstream file(fName);
	if (!file.is_open()){
		std::cout << "Failed to open file: " << fName << std::endl;
		return "";
	}
	return std::string((std::istreambuf_iterator<char>(file)),
		std::istreambuf_iterator<char>());
}
GLint util::load_shader(GLenum type, const std::string &file){
	GLuint shader = glCreateShader(type);
	std::string src = read_file(file);
	const char *csrc = src.c_str();
	glShaderSource(shader, 1, &csrc, 0);
	glCompileShader(shader);

	GLint status;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
	if (status == GL_FALSE){
		std::cerr << "loadShader: ";
		switch (type){
		case GL_VERTEX_SHADER:
			std::cerr << "Vertex shader: ";
			break;
		case GL_FRAGMENT_SHADER:
			std::cerr << "Fragment shader: ";
			break;
		case GL_GEOMETRY_SHADER:
			std::cerr << "Geometry shader: ";
			break;
		default:
			std::cerr << "Other shader type: ";
		}
		std::cerr << file << " failed to compile. Compilation log:\n";
		GLint len;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
		char *log = new char[len];
		glGetShaderInfoLog(shader, len, 0, log);
		std::cerr << log << "\n";
		delete[] log;
		glDeleteShader(shader);
		return -1;
	}
	return shader;
}
GLint util::load_program(const std::vector<std::tuple<GLenum, std::string>> &shaders){
	std::vector<GLuint> glshaders;
	for (const std::tuple<GLenum, std::string> &s : shaders){
		GLint h = load_shader(std::get<0>(s), std::get<1>(s));
		if (h == -1){
			std::cerr << "loadProgram: A required shader failed to compile, aborting\n";
			for (GLuint g : glshaders){
				glDeleteShader(g);
			}
			return -1;
		}
		glshaders.push_back(h);
	}
	GLuint program = glCreateProgram();
	for (GLuint s : glshaders){
		glAttachShader(program, s);
	}
	glLinkProgram(program);
	GLint status;
	glGetProgramiv(program, GL_LINK_STATUS, &status);
	if (status == GL_FALSE){
		std::cerr << "loadProgram: Program failed to link, log:\n";
		GLint len;
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
		char *log = new char[len];
		glGetProgramInfoLog(program, len, 0, log);
		std::cerr << log << "\n";
		delete[] log;
	}
	for (GLuint s : glshaders){
		glDetachShader(program, s);
		glDeleteShader(s);
	}
	if (status == GL_FALSE){
		glDeleteProgram(program);
		return -1;
	}
	return program;
}
GLuint util::load_texture(const std::string &file){
	SDL_Surface *surf = SDL_LoadBMP(file.c_str());
	//TODO: Throw an error?
	if (!surf){
		std::cout << "Failed to load bmp: " << file
			<< " SDL_error: " << SDL_GetError() << "\n";
		return 0;
	}
	//Assume 4 or 3 bytes per pixel
	GLenum format, internal;
	if (surf->format->BytesPerPixel == 4){
		internal = GL_RGBA;
		if (surf->format->Rmask == 0x000000ff){
			format = GL_RGBA;
		}
		else {
			format = GL_BGRA;
		}
	}
	else {
		internal = GL_RGB;
		if (surf->format->Rmask == 0x000000ff){
			format = GL_RGB;
		}
		else {
			format = GL_BGR;
		}
	}
	GLuint tex;
	glGenTextures(1, &tex);
	glBindTexture(GL_TEXTURE_2D, tex);

	glTexImage2D(GL_TEXTURE_2D, 0, internal, surf->w, surf->h, 0, format,
		GL_UNSIGNED_BYTE, surf->pixels);
	glGenerateMipmap(GL_TEXTURE_2D);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	SDL_FreeSurface(surf);
	return tex;
}
bool util::log_glerror(const std::string &msg){
	GLenum err = glGetError();
	if (err != GL_NO_ERROR){
		std::cerr << "OpenGL Error: ";
		switch (err){
		case GL_INVALID_ENUM:
			std::cerr << "Invalid enum";
			break;
		case GL_INVALID_VALUE:
			std::cerr << "Invalid value";
			break;
		case GL_INVALID_OPERATION:
			std::cerr << "Invalid operation";
			break;
		case GL_OUT_OF_MEMORY:
			std::cerr << "Out of memory";
			break;
		case GL_INVALID_FRAMEBUFFER_OPERATION:
			std::cerr << "Invalid FrameBuffer operation";
			break;
		default:
			std::cerr << std::hex << err << std::dec;
		}
		std::cerr << " - " << msg << "\n";
		return true;
	}
	return false;
}
#if _MSC_VER
void APIENTRY util::gldebug_callback(GLenum src, GLenum type, GLuint id, GLenum severity,
	GLsizei len, const GLchar *msg, const GLvoid *user)
#else
void util::gldebug_callback(GLenum src, GLenum type, GLuint id, GLenum severity,
	GLsizei len, const GLchar *msg, const GLvoid *user)
#endif
{
	//Print a time stamp for the message
	float sec = SDL_GetTicks() / 1000.f;
	int min = static_cast<int>(sec / 60.f);
	sec -= sec / 60.f;
	std::cout << "[" << min << ":"
		<< std::setprecision(3) << sec << "] OpenGL Debug -";
	switch (severity){
	case GL_DEBUG_SEVERITY_HIGH_ARB:
		std::cout << " High severity";
		break;
	case GL_DEBUG_SEVERITY_MEDIUM_ARB:
		std::cout << " Medium severity";
		break;
	case GL_DEBUG_SEVERITY_LOW_ARB:
		std::cout << " Low severity";
	}
	switch (src){
	case GL_DEBUG_SOURCE_API_ARB:
		std::cout << " API";
		break;
	case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
		std::cout << " Window system";
		break;
	case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
		std::cout << " Shader compiler";
		break;
	case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
		std::cout << " Third party";
		break;
	case GL_DEBUG_SOURCE_APPLICATION_ARB:
		std::cout << " Application";
		break;
	default:
		std::cout << " Other";
	}
	switch (type){
	case GL_DEBUG_TYPE_ERROR_ARB:
		std::cout << " Error";
		break;
	case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
		std::cout << " Deprecated behavior";
		break;
	case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
		std::cout << " Undefined behavior";
		break;
	case GL_DEBUG_TYPE_PORTABILITY_ARB:
		std::cout << " Portability";
		break;
	case GL_DEBUG_TYPE_PERFORMANCE_ARB:
		std::cout << " Performance";
		break;
	default:
		std::cout << " Other";
	}
	std::cout << ":\n\t" << msg << "\n";
}
bool util::load_OBJ(const std::string &fName, GLuint &vbo, GLuint &ebo, size_t &nElems){
	std::ifstream file(fName);
	if (!file.is_open()){
		std::cout << "Failed to find obj file: " << fName << std::endl;
		return false;
	}

	//Temporary storage for the data we read in
	std::vector<glm::vec3> tmpPos, tmpNorm;
	std::vector<glm::vec2> tmpUv;
	//A map to associate a unique vertex with its index
	std::map<std::string, GLushort> vertexIndices;
	//The final ordered packed vertices and indices
	std::vector<glm::vec3> vertexData;
	std::vector<GLushort> indices;

	std::string line;
	while (std::getline(file, line)){
		if (line.empty()){
			continue;
		}
		//Parse vertex info: positions, uv coords and normals
		else if (line.at(0) == 'v'){
			//positions
			if (line.at(1) == ' '){
				tmpPos.push_back(capture_vec3(line));
			}
			else if (line.at(1) == 't'){
				tmpUv.push_back(capture_vec2(line));
			}
			else if (line.at(1) == 'n'){
				tmpNorm.push_back(capture_vec3(line));
			}
		}
		//Parse faces
		else if (line.at(0) == 'f'){
			std::array<std::string, 3> face = capture_faces(line);
			for (std::string &v : face){
				auto fnd = vertexIndices.find(v);
				//If we find the vertex already in the list re-use the index
				//If not we create a new vertex and index
				if (fnd != vertexIndices.end()){
					indices.push_back(fnd->second);
				}
				else {
					std::array<unsigned int, 3> vertex = capture_vertex(v);
					//Pack the position, normal and uv into the vertex data, note that obj data is
					//1-indexed so we subtract 1
					vertexData.push_back(tmpPos[vertex[0] - 1]);
					vertexData.push_back(tmpNorm[vertex[2] - 1]);
					vertexData.push_back(glm::vec3(tmpUv[vertex[1] - 1], 0));
					//Store the new index, also subract 1 b/c size 1 => idx 0
					//and divide by 3 b/c there are 3 components per vertex
					indices.push_back((vertexData.size() - 1) / 3);
					vertexIndices[v] = indices.back();
				}
			}
		}
	}
	nElems = indices.size();
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(glm::vec3), &vertexData[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0], GL_STATIC_DRAW);
	return true;
}
glm::vec2 util::capture_vec2(const std::string &str){
	glm::vec2 vec;
	sscanf(str.c_str(), "%*s %f %f", &vec.x, &vec.y);
	return vec;
}
glm::vec3 util::capture_vec3(const std::string &str){
	glm::vec3 vec;
	sscanf(str.c_str(), "%*s %f %f %f", &vec.x, &vec.y, &vec.z);
	return vec;
}
std::array<std::string, 3> util::capture_faces(const std::string &str){
	std::array<std::string, 3> faces;
	//There's face information between each space in the string, and 3 faces total
	size_t prev = str.find(" ", 0);
	size_t next = prev;
	for (std::string &face : faces){
		next = str.find(" ", prev + 1);
		face = str.substr(prev + 1, next - prev - 1);
		prev = next;
	}
	return faces;
}
std::array<unsigned int, 3> util::capture_vertex(const std::string &str){
	std::array<unsigned int, 3> vertex;
	sscanf(str.c_str(), "%u/%u/%u", &vertex[0], &vertex[1], &vertex[2]);
	return vertex;
}
<commit_msg>Move to cerr for error logging and clean up loading some<commit_after>#include <vector>
#include <array>
#include <map>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <tuple>
#include <glm/glm.hpp>
#include <SDL.h>
#include "gl_core_3_3.h"
#include "util.h"

std::string util::read_file(const std::string &fName){
	std::ifstream file(fName);
	if (!file.is_open()){
		std::cout << "Failed to open file: " << fName << std::endl;
		return "";
	}
	return std::string((std::istreambuf_iterator<char>(file)),
		std::istreambuf_iterator<char>());
}
GLint util::load_shader(GLenum type, const std::string &file){
	GLuint shader = glCreateShader(type);
	std::string src = read_file(file);
	const char *csrc = src.c_str();
	glShaderSource(shader, 1, &csrc, 0);
	glCompileShader(shader);

	GLint status;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
	if (status == GL_FALSE){
		std::cerr << "loadShader: ";
		switch (type){
		case GL_VERTEX_SHADER:
			std::cerr << "Vertex shader: ";
			break;
		case GL_FRAGMENT_SHADER:
			std::cerr << "Fragment shader: ";
			break;
		case GL_GEOMETRY_SHADER:
			std::cerr << "Geometry shader: ";
			break;
		default:
			std::cerr << "Other shader type: ";
		}
		std::cerr << file << " failed to compile. Compilation log:\n";
		GLint len;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
		char *log = new char[len];
		glGetShaderInfoLog(shader, len, 0, log);
		std::cerr << log << "\n";
		delete[] log;
		glDeleteShader(shader);
		return -1;
	}
	return shader;
}
GLint util::load_program(const std::vector<std::tuple<GLenum, std::string>> &shaders){
	std::vector<GLuint> glshaders;
	for (const std::tuple<GLenum, std::string> &s : shaders){
		GLint h = load_shader(std::get<0>(s), std::get<1>(s));
		if (h == -1){
			std::cerr << "loadProgram: A required shader failed to compile, aborting\n";
			for (GLuint g : glshaders){
				glDeleteShader(g);
			}
			return -1;
		}
		glshaders.push_back(h);
	}
	GLuint program = glCreateProgram();
	for (GLuint s : glshaders){
		glAttachShader(program, s);
	}
	glLinkProgram(program);
	GLint status;
	glGetProgramiv(program, GL_LINK_STATUS, &status);
	if (status == GL_FALSE){
		std::cerr << "loadProgram: Program failed to link, log:\n";
		GLint len;
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
		char *log = new char[len];
		glGetProgramInfoLog(program, len, 0, log);
		std::cerr << log << "\n";
		delete[] log;
	}
	for (GLuint s : glshaders){
		glDetachShader(program, s);
		glDeleteShader(s);
	}
	if (status == GL_FALSE){
		glDeleteProgram(program);
		return -1;
	}
	return program;
}
GLuint util::load_texture(const std::string &file){
	SDL_Surface *surf = SDL_LoadBMP(file.c_str());
	//TODO: Throw an error?
	if (!surf){
		std::cout << "Failed to load bmp: " << file
			<< " SDL_error: " << SDL_GetError() << "\n";
		return 0;
	}
	//Assume 4 or 3 bytes per pixel
	GLenum format, internal;
	if (surf->format->BytesPerPixel == 4){
		internal = GL_RGBA;
		if (surf->format->Rmask == 0x000000ff){
			format = GL_RGBA;
		}
		else {
			format = GL_BGRA;
		}
	}
	else {
		internal = GL_RGB;
		if (surf->format->Rmask == 0x000000ff){
			format = GL_RGB;
		}
		else {
			format = GL_BGR;
		}
	}
	GLuint tex;
	glGenTextures(1, &tex);
	glBindTexture(GL_TEXTURE_2D, tex);

	glTexImage2D(GL_TEXTURE_2D, 0, internal, surf->w, surf->h, 0, format,
		GL_UNSIGNED_BYTE, surf->pixels);
	glGenerateMipmap(GL_TEXTURE_2D);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	SDL_FreeSurface(surf);
	return tex;
}
bool util::log_glerror(const std::string &msg){
	GLenum err = glGetError();
	if (err != GL_NO_ERROR){
		std::cerr << "OpenGL Error: ";
		switch (err){
		case GL_INVALID_ENUM:
			std::cerr << "Invalid enum";
			break;
		case GL_INVALID_VALUE:
			std::cerr << "Invalid value";
			break;
		case GL_INVALID_OPERATION:
			std::cerr << "Invalid operation";
			break;
		case GL_OUT_OF_MEMORY:
			std::cerr << "Out of memory";
			break;
		case GL_INVALID_FRAMEBUFFER_OPERATION:
			std::cerr << "Invalid FrameBuffer operation";
			break;
		default:
			std::cerr << std::hex << err << std::dec;
		}
		std::cerr << " - " << msg << "\n";
		return true;
	}
	return false;
}
#if _MSC_VER
void APIENTRY util::gldebug_callback(GLenum src, GLenum type, GLuint id, GLenum severity,
	GLsizei len, const GLchar *msg, const GLvoid *user)
#else
void util::gldebug_callback(GLenum src, GLenum type, GLuint id, GLenum severity,
	GLsizei len, const GLchar *msg, const GLvoid *user)
#endif
{
	//Print a time stamp for the message
	float sec = SDL_GetTicks() / 1000.f;
	int min = static_cast<int>(sec / 60.f);
	sec -= sec / 60.f;
	std::cerr << "[" << min << ":"
		<< std::setprecision(3) << sec << "] OpenGL Debug -";
	switch (severity){
	case GL_DEBUG_SEVERITY_HIGH_ARB:
		std::cerr << " High severity";
		break;
	case GL_DEBUG_SEVERITY_MEDIUM_ARB:
		std::cerr << " Medium severity";
		break;
	case GL_DEBUG_SEVERITY_LOW_ARB:
		std::cerr << " Low severity";
	}
	switch (src){
	case GL_DEBUG_SOURCE_API_ARB:
		std::cerr << " API";
		break;
	case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
		std::cerr << " Window system";
		break;
	case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
		std::cerr << " Shader compiler";
		break;
	case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
		std::cerr << " Third party";
		break;
	case GL_DEBUG_SOURCE_APPLICATION_ARB:
		std::cerr << " Application";
		break;
	default:
		std::cerr << " Other";
	}
	switch (type){
	case GL_DEBUG_TYPE_ERROR_ARB:
		std::cerr << " Error";
		break;
	case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
		std::cerr << " Deprecated behavior";
		break;
	case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
		std::cerr << " Undefined behavior";
		break;
	case GL_DEBUG_TYPE_PORTABILITY_ARB:
		std::cerr << " Portability";
		break;
	case GL_DEBUG_TYPE_PERFORMANCE_ARB:
		std::cerr << " Performance";
		break;
	default:
		std::cerr << " Other";
	}
	std::cerr << ":\n\t" << msg << "\n";
}
bool util::load_obj(const std::string &fname,
	InterleavedBuffer<glm::vec3, glm::vec3, glm::vec3> &vbo,
	InterleavedBuffer<GLushort> &ebo, size_t &n_elems)
{
	std::ifstream file(fname);
	if (!file.is_open()){
		std::cout << "Failed to find obj file: " << fname << std::endl;
		return false;
	}

	//Temporary storage for the data we read in
	std::vector<glm::vec3> tmp_pos, tmp_norm;
	std::vector<glm::vec2> tmp_uv;
	//A map to associate a unique vertex with its index
	std::map<std::string, GLushort> vert_indices;
	//The final ordered packed vertices and indices
	std::vector<glm::vec3> vert_data;
	std::vector<GLushort> indices;

	std::string line;
	while (std::getline(file, line)){
		if (line.empty()){
			continue;
		}
		//Parse vertex info: positions, uv coords and normals
		else if (line.at(0) == 'v'){
			//positions
			if (line.at(1) == ' '){
				tmp_pos.push_back(capture_vec3(line));
			}
			else if (line.at(1) == 't'){
				tmp_uv.push_back(capture_vec2(line));
			}
			else if (line.at(1) == 'n'){
				tmp_norm.push_back(capture_vec3(line));
			}
		}
		//Parse faces
		else if (line.at(0) == 'f'){
			std::array<std::string, 3> face = capture_faces(line);
			for (std::string &v : face){
				auto fnd = vert_indices.find(v);
				//If we find the vertex already in the list re-use the index
				//If not we create a new vertex and index
				if (fnd != vert_indices.end()){
					indices.push_back(fnd->second);
				}
				else {
					std::array<unsigned int, 3> vertex = capture_vertex(v);
					//Pack the position, normal and uv into the vertex data, note that obj data is
					//1-indexed so we subtract 1
					vert_data.push_back(tmp_pos[vertex[0] - 1]);
					vert_data.push_back(tmp_norm[vertex[2] - 1]);
					vert_data.push_back(glm::vec3(tmp_uv[vertex[1] - 1], 0));
					//Store the new index, also subract 1 b/c size 1 => idx 0
					//and divide by 3 b/c there are 3 components per vertex
					indices.push_back((vert_data.size() - 1) / 3);
					vert_indices[v] = indices.back();
				}
			}
		}
	}
	n_elems = indices.size();
	vbo = InterleavedBuffer<glm::vec3, glm::vec3, glm::vec3>(n_elems, GL_ARRAY_BUFFER, GL_STATIC_DRAW);
	vbo.map(GL_WRITE_ONLY);
	for (size_t i = 0; i < n_elems; ++i){
		vbo.write<0>(i) = vert_data[3 * i];
		vbo.write<1>(i) = vert_data[3 * i + 1];
		vbo.write<2>(i) = vert_data[3 * i + 2];
	}
	vbo.unmap();
	ebo = InterleavedBuffer<GLushort>(n_elems, GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW);
	ebo.map(GL_WRITE_ONLY);
	for (size_t i = 0; i < indices.size(); ++i){
		ebo.write<0>(i) = indices[i];
	}
	ebo.unmap();
	return true;
}
glm::vec2 util::capture_vec2(const std::string &str){
	glm::vec2 vec;
	sscanf(str.c_str(), "%*s %f %f", &vec.x, &vec.y);
	return vec;
}
glm::vec3 util::capture_vec3(const std::string &str){
	glm::vec3 vec;
	sscanf(str.c_str(), "%*s %f %f %f", &vec.x, &vec.y, &vec.z);
	return vec;
}
std::array<std::string, 3> util::capture_faces(const std::string &str){
	std::array<std::string, 3> faces;
	//There's face information between each space in the string, and 3 faces total
	size_t prev = str.find(" ", 0);
	size_t next = prev;
	for (std::string &face : faces){
		next = str.find(" ", prev + 1);
		face = str.substr(prev + 1, next - prev - 1);
		prev = next;
	}
	return faces;
}
std::array<unsigned int, 3> util::capture_vertex(const std::string &str){
	std::array<unsigned int, 3> vertex;
	sscanf(str.c_str(), "%u/%u/%u", &vertex[0], &vertex[1], &vertex[2]);
	return vertex;
}
<|endoftext|>


<commit_before>#pragma once

// `krbn::components_manager` can be used safely in a multi-threaded environment.

#include "constants.hpp"
#include "device_observer.hpp"
#include "dispatcher.hpp"
#include "grabber_client.hpp"
#include "monitor/version_monitor_utility.hpp"

namespace krbn {
class components_manager final : public pqrs::dispatcher::extra::dispatcher_client {
public:
  components_manager(const components_manager&) = delete;

  components_manager(void) : dispatcher_client() {
    version_monitor_ = version_monitor_utility::make_version_monitor_stops_main_run_loop_when_version_changed();

    async_start_grabber_client();
  }

  virtual ~components_manager(void) {
    detach_from_dispatcher([this] {
      stop_grabber_client();
      stop_device_observer();

      version_monitor_ = nullptr;
    });
  }

private:
  void async_start_grabber_client(void) {
    enqueue_to_dispatcher([this] {
      if (grabber_client_) {
        return;
      }

      grabber_client_ = std::make_shared<grabber_client>();

      grabber_client_->connected.connect([this] {
        if (version_monitor_) {
          version_monitor_->async_manual_check();
        }

        async_start_device_observer();
      });

      grabber_client_->connect_failed.connect([this](auto&& error_code) {
        if (version_monitor_) {
          version_monitor_->async_manual_check();
        }

        async_stop_device_observer();
      });

      grabber_client_->closed.connect([this] {
        if (version_monitor_) {
          version_monitor_->async_manual_check();
        }

        async_stop_device_observer();
      });

      grabber_client_->async_start();
    });
  }

  void async_stop_grabber_client(void) {
    enqueue_to_dispatcher([this] {
      stop_grabber_client();
    });
  }

  void stop_grabber_client(void) {
    if (!grabber_client_) {
      return;
    }

    grabber_client_ = nullptr;
  }

  void async_start_device_observer(void) {
    enqueue_to_dispatcher([this] {
      if (device_observer_) {
        return;
      }

      device_observer_ = std::make_shared<device_observer>(grabber_client_);
    });
  }

  void async_stop_device_observer(void) {
    enqueue_to_dispatcher([this] {
      async_stop_device_observer();
    });
  }

  void stop_device_observer(void) {
    if (!device_observer_) {
      return;
    }

    device_observer_ = nullptr;
  }

  std::shared_ptr<version_monitor> version_monitor_;
  std::shared_ptr<grabber_client> grabber_client_;
  std::shared_ptr<device_observer> device_observer_;
};
} // namespace krbn
<commit_msg>update observer<commit_after>#pragma once

// `krbn::components_manager` can be used safely in a multi-threaded environment.

#include "constants.hpp"
#include "device_observer.hpp"
#include "dispatcher.hpp"
#include "grabber_client.hpp"
#include "monitor/version_monitor_utility.hpp"

namespace krbn {
class components_manager final : public pqrs::dispatcher::extra::dispatcher_client {
public:
  components_manager(const components_manager&) = delete;

  components_manager(void) : dispatcher_client() {
    version_monitor_ = version_monitor_utility::make_version_monitor_stops_main_run_loop_when_version_changed();

    async_start_grabber_client();
  }

  virtual ~components_manager(void) {
    detach_from_dispatcher([this] {
      stop_grabber_client();
      stop_device_observer();

      version_monitor_ = nullptr;
    });
  }

private:
  void async_start_grabber_client(void) {
    enqueue_to_dispatcher([this] {
      if (grabber_client_) {
        return;
      }

      grabber_client_ = std::make_shared<grabber_client>();

      grabber_client_->connected.connect([this] {
        if (version_monitor_) {
          version_monitor_->async_manual_check();
        }

        start_device_observer();
      });

      grabber_client_->connect_failed.connect([this](auto&& error_code) {
        if (version_monitor_) {
          version_monitor_->async_manual_check();
        }

        stop_device_observer();
      });

      grabber_client_->closed.connect([this] {
        if (version_monitor_) {
          version_monitor_->async_manual_check();
        }

        stop_device_observer();
      });

      grabber_client_->async_start();
    });
  }

  void async_stop_grabber_client(void) {
    enqueue_to_dispatcher([this] {
      stop_grabber_client();
    });
  }

  void stop_grabber_client(void) {
    if (!grabber_client_) {
      return;
    }

    grabber_client_ = nullptr;
  }

  void start_device_observer(void) {
    if (device_observer_) {
      return;
    }

    device_observer_ = std::make_shared<device_observer>(grabber_client_);
  }

  void stop_device_observer(void) {
    if (!device_observer_) {
      return;
    }

    device_observer_ = nullptr;
  }

  std::shared_ptr<version_monitor> version_monitor_;
  std::shared_ptr<grabber_client> grabber_client_;
  std::shared_ptr<device_observer> device_observer_;
};
} // namespace krbn
<|endoftext|>