<commit_before>/*
 * Copyright (c) 2015, Romain Létendart
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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 "logger.h"

#include <chrono>
#include <ctime>
#include <iostream>
#include <sstream>

namespace geecxx
{

Logger::~Logger()
{
}

Logger& Logger::getInstance()
{
    // Static variable initialization ensures threadsafety in C++11 standard
    static Logger logger;
    return logger;
}

void Logger::log(const LogLevel& logLevel, const std::string& message)
{
    if (logLevel < _logLevelThreshold) {
        return;
    }

    std::lock_guard<std::mutex> lock(_mutex);
    std::time_t now = std::chrono::system_clock::to_time_t(
                                std::chrono::system_clock::now());
    char formattedTime[20];

    if (0 == strftime(formattedTime, 20, "%F %T", localtime(&now))) {
        // Be sure to display an empty string instead of undefined content
        formattedTime[0] = '\0';
    }

    std::istringstream stream(message);
    std::string messageChunk;
    while (std::getline(stream, messageChunk) && !messageChunk.empty()) {
        std::cout << "[" << formattedTime << "][" << logLevelToStr(logLevel) << "]: "
                  << messageChunk << std::endl;
    }
}

Logger::Logger()
{
}

std::string Logger::logLevelToStr(const LogLevel& logLevel)
{
    switch (logLevel) {
    case LogLevel::DEBUG:
        return "DEBUG";
    case LogLevel::INFO:
        return "INFO";
    case LogLevel::WARNING:
        return "WARNING";
    case LogLevel::ERROR:
        return "ERROR";
    default:
        return "UNKNOWN";
    }

    return "";
}

}
<commit_msg>Fixed issue in Logger<commit_after>/*
 * Copyright (c) 2015, Romain Létendart
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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 "logger.h"

#include <chrono>
#include <ctime>
#include <iostream>
#include <sstream>

namespace geecxx
{

Logger::~Logger()
{
}

Logger& Logger::getInstance()
{
    // Static variable initialization ensures threadsafety in C++11 standard
    static Logger logger;
    return logger;
}

void Logger::log(const LogLevel& logLevel, const std::string& message)
{
    if (logLevel < _logLevelThreshold) {
        return;
    }

    std::lock_guard<std::mutex> lock(_mutex);
    std::time_t now = std::chrono::system_clock::to_time_t(
                                std::chrono::system_clock::now());
    char formattedTime[20];

    if (0 == strftime(formattedTime, 20, "%F %T", localtime(&now))) {
        // Be sure to display an empty string instead of undefined content
        formattedTime[0] = '\0';
    }

    std::istringstream stream(message);
    std::string messageChunk;
    while (std::getline(stream, messageChunk)) {
        std::cout << "[" << formattedTime << "][" << logLevelToStr(logLevel) << "]: "
                  << messageChunk << std::endl;
    }
}

Logger::Logger()
{
}

std::string Logger::logLevelToStr(const LogLevel& logLevel)
{
    switch (logLevel) {
    case LogLevel::DEBUG:
        return "DEBUG";
    case LogLevel::INFO:
        return "INFO";
    case LogLevel::WARNING:
        return "WARNING";
    case LogLevel::ERROR:
        return "ERROR";
    default:
        return "UNKNOWN";
    }

    return "";
}

}
<|endoftext|>


<commit_before>//
//  Entity.hpp
//
// Sketchup C++ Wrapper for C API
// MIT License
//
// Copyright (c) 2017 Tom Kaneko
//
// 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.
//

#ifndef Entity_hpp
#define Entity_hpp

#include <stdio.h>
#include <string>
#include <vector>

#include <SketchUpAPI/model/entity.h>

namespace CW {

// Forward Declarations
class AttributeDictionary;
class TypedValue;

/*
* @brief Entity object wrapper.
* @descr This is the base class for all SketchUp entities. Entities are basically anything that can be contained in a model, including Drawingelements such as Edges, SectionPlanes, Groups, etc. and entities that relate to those Drawingelements, such as Loops, Layers, etc.
*
* Keep in mind that the methods below are available on all subclasses. For example, an Edge's parent class is Drawingelement, and a Drawingelement's parent class is Entity. Therefore an Edge has all of the methods defined in Drawingelement and Entity.
*/
class Entity {
  protected:
  /**
  * @brief The C SUEntityRef that this class wraps.
  */
  SUEntityRef m_entity;

  /**
  * @brief Indicates whether the Entity has been attached to a model.
  */
  bool m_attached;

  public:
  /**
  * @brief Constructor representing a null objject.
  */
	Entity();

  /**
  * @brief Creates a new Entity object.
  * @param entity - SUEntityRef from SU C API
  * @param attached - (optional) flag indicating whether the entity is attached to a model.  Defaults to true.
  */
  Entity(SUEntityRef entity, bool attached = true);

  /**
  * @brief Copy constructor with an optional parameter for the entity reference.
  * @descr SUEntityRef objects cannot be created from this class, so the Ref object must be passed to this constructor from a derived class object.
  * @param other - Entity object from which properties will be copied.
  * @param entity_ref - (optional) SUEntityRef object to assign to the copied object.
  */
  Entity(const Entity& other, SUEntityRef entity_ref = SU_INVALID);

  /**
  * @brief Destructor
  * @descr The C++ wrapper deals with releasing objects, so user does not have to keep track of memory allocations.
  */
  ~Entity();

  /** @brief Copy assignment operator */
  Entity& operator=(const Entity& other);

  /*
  * @brief Returns a copy of the wrapped SUEntityRef. USE WITH CAUTION.
  * @descr Note that the Entity object still manages the lifetime of the reference, so the SUEntityRef could become invalid.
  */
  operator SUEntityRef() const;

  /*
  * @brief Returns a pointer to the wrapped SUEntityRef. USE WITH CAUTION.
  * @descr Note that the Entity object still manages the lifetime of the reference, so the SUEntityRef could become invalid.
  */
  operator SUEntityRef*();

  /**
  * @brief Method lets the object know that it has been attached to a model.  This is important as it will let the object know that it does not need to "release" the object.
  * @param attach - (optional) true to let the object know that it has been attached to a model.  False to let the object know that it has not been attached.
  */
  void attached(bool attach =  true);

  /**
  * @brief Returns the AttributeDictionaries collection attached to the entity.
  * @return vector of AttributeDictionary objects associated with the entity. If no AttributeDictionary objects are associated with the entity, an empty vector will be returned.
  */
  std::vector<AttributeDictionary> attribute_dictionaries() const;

  /**
  * @brief Returns an attribute dictionary object with a given name that is attached to an Entity.
  * @param name - string representing the name of the AttributeDictionary
  * @return AttributeDictionary object with the given name.
  */
  AttributeDictionary attribute_dictionary(const std::string& name) const;

  /**
  * @brief Copies attributes from another Entity object to this one.
  * @param entity - object to get the attributes from.
  * @param bool true to delete existing attributes, false to retain and overwrite the values. // TODO: as the C API does not currentlty allow you to delete attributes, this flag can have no effect.
  * @return true for success, false for failure.
  */
  bool copy_attributes_from(const Entity& entity /*, bool clear_existing = false*/);

  /**
  * The delete_attribute method is used to delete an attribute from an entity.
  * @param AttributeDictionary& object in which to find the key.
  * @param std::string with the name of the key of the attribute.
  */
  /*
  * TODO: deleting attributes is not possible with the current C API.  It could be used, however, to store a list of deleted attributes, so if this object is copied, the deleted attributes are not copied over to the new object.
  void delete_attribute(AttributeDictionary &dict, std::string key);
  */

  /**
  * @brief Checks if the entity is valid.
  * @desc Note that this function does not check if the entity has been deleted. @see operator!().
  */
  bool is_valid() const;

  /**
  * @brief Returns true if this entity is not valid. Alias of !is_valid().
  */
  bool operator!() const;

	/**
  * @brief Retrieve a unique ID assigned to an entity.
  * @return int32_t key for the Entity object.
  */
  int32_t entityID() const;

  /**
  * @brief Retrieves the value of an attribute in the entity's attribute dictionary.
  * @param dict_name - string name of the attribute dictionary.
  * @param key - the attribute key.
  * @param default_value - (optional) default TypedValue to return if no attribute is found. Defaults to an empty TypedValue
  * @return value TypedValue of the attribute.  If no attribute found, the default value passed is returned.
  */
  TypedValue get_attribute(const std::string& dict_name, const std::string& key, const TypedValue& default_value = TypedValue()) const;

  /**
  * @brief Retrieves the value of an attribute in the entity's attribute dictionary.
  * @param dict - AttributeDictionary object to search.
  * @param key - the attribute key.
  * @param default_value - (optional) default TypedValue to return if no attribute is found. Defaults to an empty TypedValue
  * @return value TypedValue of the attribute.  If no attribute found, the default value passed is returned.
  */
  TypedValue get_attribute(const AttributeDictionary &dict, const std::string& key, const TypedValue& default_value = TypedValue()) const;

  /**
  // TODO: C API does not currently allow traversing upwards
  parent()
  */

  /**
  * @brief Sets the value of an attribute in the given AttributeDictionary object.
  * @param dict_name - string name of AttributeDictionary object that the attribute is in.
  * @param key - std::string attribute key.
  * @param value - TypedValue to set.
  * @return true on success, false on failure
  */
  bool set_attribute(const std::string& dict_name, const std::string& key, const TypedValue& value);

	/**
  * @brief Sets the value of an attribute in the given AttributeDictionary object.
  * @param dict - AttributeDictionary object that the attribute is in.
  * @param key - std::string attribute key.
  * @param value - TypedValue to set.
  * @return true on success, false on failure
  */
  bool set_attribute(AttributeDictionary& dict, const std::string& key, const TypedValue& value);

  /**
  * @brief Returns the type of the entity. See enum SURefType.
  */
  enum SURefType entity_type() const;

  /**
  * Returns whether these objects are the same.
  */
  //bool operator==(const Entity& entity) const;

  /**
  * @brief Equality operator for two entity objects
  */
  friend bool operator==(const Entity& lhs, const Entity& rhs);

  /**
  * @brief Non-equality operator for two entity objects
  */
  friend bool operator!=(const Entity& lhs, const Entity& rhs);

};

} /* namespace CW */

#endif /* Entity_hpp */
<commit_msg>Add missing include for TypedValue<commit_after>//
//  Entity.hpp
//
// Sketchup C++ Wrapper for C API
// MIT License
//
// Copyright (c) 2017 Tom Kaneko
//
// 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.
//

#ifndef Entity_hpp
#define Entity_hpp

#include <stdio.h>
#include <string>
#include <vector>

#include <SketchUpAPI/model/entity.h>

#include "SUAPI-CppWrapper/model/TypedValue.hpp"

namespace CW {

// Forward Declarations
class AttributeDictionary;

/*
* @brief Entity object wrapper.
* @descr This is the base class for all SketchUp entities. Entities are basically anything that can be contained in a model, including Drawingelements such as Edges, SectionPlanes, Groups, etc. and entities that relate to those Drawingelements, such as Loops, Layers, etc.
*
* Keep in mind that the methods below are available on all subclasses. For example, an Edge's parent class is Drawingelement, and a Drawingelement's parent class is Entity. Therefore an Edge has all of the methods defined in Drawingelement and Entity.
*/
class Entity {
  protected:
  /**
  * @brief The C SUEntityRef that this class wraps.
  */
  SUEntityRef m_entity;

  /**
  * @brief Indicates whether the Entity has been attached to a model.
  */
  bool m_attached;

  public:
  /**
  * @brief Constructor representing a null objject.
  */
	Entity();

  /**
  * @brief Creates a new Entity object.
  * @param entity - SUEntityRef from SU C API
  * @param attached - (optional) flag indicating whether the entity is attached to a model.  Defaults to true.
  */
  Entity(SUEntityRef entity, bool attached = true);

  /**
  * @brief Copy constructor with an optional parameter for the entity reference.
  * @descr SUEntityRef objects cannot be created from this class, so the Ref object must be passed to this constructor from a derived class object.
  * @param other - Entity object from which properties will be copied.
  * @param entity_ref - (optional) SUEntityRef object to assign to the copied object.
  */
  Entity(const Entity& other, SUEntityRef entity_ref = SU_INVALID);

  /**
  * @brief Destructor
  * @descr The C++ wrapper deals with releasing objects, so user does not have to keep track of memory allocations.
  */
  ~Entity();

  /** @brief Copy assignment operator */
  Entity& operator=(const Entity& other);

  /*
  * @brief Returns a copy of the wrapped SUEntityRef. USE WITH CAUTION.
  * @descr Note that the Entity object still manages the lifetime of the reference, so the SUEntityRef could become invalid.
  */
  operator SUEntityRef() const;

  /*
  * @brief Returns a pointer to the wrapped SUEntityRef. USE WITH CAUTION.
  * @descr Note that the Entity object still manages the lifetime of the reference, so the SUEntityRef could become invalid.
  */
  operator SUEntityRef*();

  /**
  * @brief Method lets the object know that it has been attached to a model.  This is important as it will let the object know that it does not need to "release" the object.
  * @param attach - (optional) true to let the object know that it has been attached to a model.  False to let the object know that it has not been attached.
  */
  void attached(bool attach =  true);

  /**
  * @brief Returns the AttributeDictionaries collection attached to the entity.
  * @return vector of AttributeDictionary objects associated with the entity. If no AttributeDictionary objects are associated with the entity, an empty vector will be returned.
  */
  std::vector<AttributeDictionary> attribute_dictionaries() const;

  /**
  * @brief Returns an attribute dictionary object with a given name that is attached to an Entity.
  * @param name - string representing the name of the AttributeDictionary
  * @return AttributeDictionary object with the given name.
  */
  AttributeDictionary attribute_dictionary(const std::string& name) const;

  /**
  * @brief Copies attributes from another Entity object to this one.
  * @param entity - object to get the attributes from.
  * @param bool true to delete existing attributes, false to retain and overwrite the values. // TODO: as the C API does not currentlty allow you to delete attributes, this flag can have no effect.
  * @return true for success, false for failure.
  */
  bool copy_attributes_from(const Entity& entity /*, bool clear_existing = false*/);

  /**
  * The delete_attribute method is used to delete an attribute from an entity.
  * @param AttributeDictionary& object in which to find the key.
  * @param std::string with the name of the key of the attribute.
  */
  /*
  * TODO: deleting attributes is not possible with the current C API.  It could be used, however, to store a list of deleted attributes, so if this object is copied, the deleted attributes are not copied over to the new object.
  void delete_attribute(AttributeDictionary &dict, std::string key);
  */

  /**
  * @brief Checks if the entity is valid.
  * @desc Note that this function does not check if the entity has been deleted. @see operator!().
  */
  bool is_valid() const;

  /**
  * @brief Returns true if this entity is not valid. Alias of !is_valid().
  */
  bool operator!() const;

	/**
  * @brief Retrieve a unique ID assigned to an entity.
  * @return int32_t key for the Entity object.
  */
  int32_t entityID() const;

  /**
  * @brief Retrieves the value of an attribute in the entity's attribute dictionary.
  * @param dict_name - string name of the attribute dictionary.
  * @param key - the attribute key.
  * @param default_value - (optional) default TypedValue to return if no attribute is found. Defaults to an empty TypedValue
  * @return value TypedValue of the attribute.  If no attribute found, the default value passed is returned.
  */
  TypedValue get_attribute(const std::string& dict_name, const std::string& key, const TypedValue& default_value = TypedValue()) const;

  /**
  * @brief Retrieves the value of an attribute in the entity's attribute dictionary.
  * @param dict - AttributeDictionary object to search.
  * @param key - the attribute key.
  * @param default_value - (optional) default TypedValue to return if no attribute is found. Defaults to an empty TypedValue
  * @return value TypedValue of the attribute.  If no attribute found, the default value passed is returned.
  */
  TypedValue get_attribute(const AttributeDictionary &dict, const std::string& key, const TypedValue& default_value = TypedValue()) const;

  /**
  // TODO: C API does not currently allow traversing upwards
  parent()
  */

  /**
  * @brief Sets the value of an attribute in the given AttributeDictionary object.
  * @param dict_name - string name of AttributeDictionary object that the attribute is in.
  * @param key - std::string attribute key.
  * @param value - TypedValue to set.
  * @return true on success, false on failure
  */
  bool set_attribute(const std::string& dict_name, const std::string& key, const TypedValue& value);

	/**
  * @brief Sets the value of an attribute in the given AttributeDictionary object.
  * @param dict - AttributeDictionary object that the attribute is in.
  * @param key - std::string attribute key.
  * @param value - TypedValue to set.
  * @return true on success, false on failure
  */
  bool set_attribute(AttributeDictionary& dict, const std::string& key, const TypedValue& value);

  /**
  * @brief Returns the type of the entity. See enum SURefType.
  */
  enum SURefType entity_type() const;

  /**
  * Returns whether these objects are the same.
  */
  //bool operator==(const Entity& entity) const;

  /**
  * @brief Equality operator for two entity objects
  */
  friend bool operator==(const Entity& lhs, const Entity& rhs);

  /**
  * @brief Non-equality operator for two entity objects
  */
  friend bool operator!=(const Entity& lhs, const Entity& rhs);

};

} /* namespace CW */

#endif /* Entity_hpp */
<|endoftext|>


<commit_before>/*
 *  This file is part of PlantLight application.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

/*
 * Built for Attiny85 1Mhz, using AVR USBasp programmer.
 * VERSION 0.7
 */

#include <avr/sleep.h>
#include <avr/interrupt.h>

#include <Arduino.h>
#include <TinyWireM.h>
#include <Time.h>
#include <BH1750FVI.h>
#include <DS1307RTC.h>

#define RELAY_SW_OUT            4       // Relay out pin
#define CMD_MAN_IN              1       // Manual light switch
#define WD_TICK_TIME            8       // Watchdog tick time [s] (check WD_MODE or datasheet)
#define WD_WAIT_TIME            24      // Time [s] to count between two sensor read
#define SAMPLE_COUNT            8       // Light sample count (average measurement)

// ####################### Prototypes #######################

// Setup watchdog wakeup interrupt
// tick: watchdog tick time [s] (check WD_MODE or datasheet)
void setupWatchdog(float tick);

// Set system into the sleep state,
// system wakes up when watchdog is timed out
void systemSleep();

// Provides a time_t to Time library, wrapper for call
// to RTC.get(), which is not a static function (class member)
time_t timeProvider();

// Display a date in readable format on the serial interface
void printDigits(int digits);
void SerialDisplayDateTime(const time_t &timeToDisplay);

// Sets the RTC to the new time
void setTime();

// Checks the current time of day and month of the year.
// Returns true if the light is now enabled.
boolean checkEnable(const time_t &now);

// Checks actual lux value. Returns true if the conditions
// to turn lights on are met.
boolean checkLightCond(float lux);

// Sample some lux value and calculate the running average over time
float sample();

void printLuxArray();
void cleanLuxArray();

// ####################### Constants ########################

// Watchdog interrupt sleep time
// 0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms, 6=1 sec, 7=2 sec, 8=4 sec, 9=8sec
const float WD_MODE[10] = { 0.016, 0.032, 0.064, 0.128, 0.25, 0.5, 1, 2, 4, 8 };

// ####################### Variables ########################

USI_TWI bus;                            // TinyWireM instance (I2C bus)
BH1750FVI BH1750(bus);                  // Light sensor instance
RTC_DS1307 RTC(bus);                    // RTC clock instance

tmDriftInfo di;

volatile uint8_t wdCount = 0;

// Watchdog interrupt count before reading light value
// wd count * wd interval == 4 * 8 s = 32 s
uint16_t wdMatch = 0;
boolean relayState = false, first = false;
static float luxSamples[SAMPLE_COUNT] = {};
static uint8_t readCounter = 0;

// ####################### Functions ########################

void setupWatchdog(float tick) {
  // 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
  // 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
  uint8_t wdreg, wdmode = 0;

  for (uint8_t i = 0; i < 10; ++i) {
    if (WD_MODE[i] == tick) {
      wdmode = i;
    }
  }

  if (wdmode > 9)
    wdmode = 9;
  wdreg = wdmode & 7;

  if (wdmode > 7)
    wdreg |= (1 << 5);
  wdreg |= (1 << WDCE);

  MCUSR &= ~(1 << WDRF);

  // Start timed sequence
  WDTCR |= (1 << WDCE) | (1 << WDE);

  // Set new watchdog timeout value
  WDTCR = wdreg;
  WDTCR |= _BV(WDIE);
}

void systemSleep() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // Sleep mode is set here
  sleep_enable();
  sleep_mode();                         // System actually sleeps here
  sleep_disable();                      // System continues execution here when watchdog timed out
}

// Watchdog Interrupt Service Routine
ISR(WDT_vect) {
  wdCount++;
}

// PCINT Interrupt Service Routine (unused)
ISR(PCINT0_vect) {
  // Don't do anything here but we must include this
  // block of code otherwise the interrupt calls an
  // uninitialized interrupt handler.
}

time_t timeProvider() {
  return RTC.get();
}

void printDigits(int digits) {
  // Utility function for digital clock display: prints preceding colon and leading 0
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void SerialDisplayDateTime(const time_t &timeToDisplay) {
  printDigits(day(timeToDisplay));
  Serial.print("/");
  printDigits(month(timeToDisplay));
  Serial.print("/");
  Serial.print(year(timeToDisplay));
  Serial.print(" ");
  printDigits(hour(timeToDisplay));
  Serial.print(":");
  printDigits(minute(timeToDisplay));
  Serial.print(":");
  printDigits(second(timeToDisplay));
  Serial.print(" ");
}

void setTime() {
  tmElements_t tme;
  time_t newTime;

  tme.Year   = 46;
  tme.Month  = 2;
  tme.Day    = 19;
  tme.Hour   = 21;
  tme.Minute = 07;
  tme.Second = 00;
  newTime = makeTime(tme);
  RTC.set(newTime);                             // Set the RTC
  setTime(newTime);                             // Set the system time

  tmDriftInfo diUpdate = RTC.read_DriftInfo();  // Update DriftInfo in RTC
  diUpdate.DriftStart = newTime;
  RTC.write_DriftInfo(diUpdate);

  SerialDisplayDateTime(newTime);
}

float sample() {
  float tmpLux = 0.0;
  // Shift left values in sample array
  for (int i = 0; i < SAMPLE_COUNT - 1; ++i) {
    luxSamples[i] = luxSamples[i + 1];
    tmpLux += luxSamples[i];
  }

  luxSamples[SAMPLE_COUNT - 1] = BH1750.getLightIntensity();  // Get lux value

  tmpLux += luxSamples[SAMPLE_COUNT - 1];

  if (readCounter < SAMPLE_COUNT) {
    readCounter++;
  }

  return tmpLux / readCounter;
}

void printLuxArray() {
  for (int i = 0; i < SAMPLE_COUNT; ++i) {
    Serial.print(luxSamples[i]);
    Serial.print(" ");
  }
}

void cleanLuxArray() {
  readCounter = 0;
  for (int i = 0; i < SAMPLE_COUNT; ++i) {
    luxSamples[i] = 0.0;
  }
}

boolean checkEnable(const time_t &now) {
  int nowH = hour(now);

  switch (month(now)) {
    // Winter
    case 1:
    case 2:
    case 10:
    case 11:
    case 12:
        if (nowH <= 16 || nowH >= 23) {
          return false;
        } else {
          return true;
        }
      break;

    // Spring / Autumn
    case 3:
    case 4:
    case 9:
      return false;
      break;

    // Summer
    case 5:
    case 6:
    case 7:
    case 8:
      return false;
      break;
    default:
      break;
  }

 return false;
}

boolean checkLightCond(float lux) {
  if (lux <= 10) {
    return true;
  } else {
    return false;
  }
}

void setup() {
  Serial.begin(9600);

  pinMode(RELAY_SW_OUT, OUTPUT);
  pinMode(CMD_MAN_IN, INPUT_PULLUP);

  // Setup watchdog timeout to 8 s (mode 9)
  setupWatchdog(WD_TICK_TIME);

  // Watchdog interrupt count before reading light value
  // example: wd count * wd interval == 4 * 8 s = 32 s
  wdMatch = (uint16_t) WD_WAIT_TIME / WD_TICK_TIME;

  // Setup Pin change interrupt on PCINT1
  GIMSK |= _BV(PCIE);
  PCMSK |= _BV(PCINT1);

  // Set the internal registers to reduce power consumes
  ACSR   = (1 << ACD);                  // Shut down the analog comparator
  MCUCR |= (1 << BODS);                 // BOD disabled

  // I2C begin() is called BEFORE sensors library "begin" methods:
  // it is called just once for all the sensors.
  bus.begin();

  // Sensors initialization
  // Light sensor
  BH1750.powerOn();
  BH1750.setMode(BH1750_CONTINUOUS_HIGH_RES_MODE_2);
  BH1750.setMtreg(200);                 // Set measurement time register to high value

  // Real time clock
  setSyncProvider(timeProvider);        // Pointer to function to get the time from the RTC
  setSyncInterval(WD_WAIT_TIME);        // Set system time at every sensor read

  // Update drift info from RTC
  di = RTC.read_DriftInfo();
  di.DriftDays = 1000;                  // RTC drift in seconds/day. 18 s per day is 18000/1000
  di.DriftSeconds = 18000;
  RTC.write_DriftInfo(di);
  setDriftInfo(di);
}

void loop() {
  BH1750.sleep();                       // Send light sensor to sleep
  systemSleep();                        // Send the unit to sleep

  // Manual command to turn light on
  if (!digitalRead(CMD_MAN_IN)) {
    if (!first) {
      // Used only once to set the time with external input
      // setTime();
      first = true;
      cleanLuxArray();
      digitalWrite(RELAY_SW_OUT, true);
    }

  } else  {
    // first = true -> First cycle in automatic mode, after manual mode

    if (wdCount >= wdMatch || first) {
      first = false;
      wdCount = 0;

      time_t timeNow = now();

      if (checkEnable(timeNow)) {
        BH1750.wakeUp(BH1750_CONTINUOUS_HIGH_RES_MODE_2);
        delay(300);

        float lux = sample();

#ifdef DEBUG
        SerialDisplayDateTime(timeNow);
        printLuxArray();
        Serial.print("= ");
        Serial.println(lux);
#endif
        if (checkLightCond(lux)) {
          digitalWrite(RELAY_SW_OUT, true);
        } else {
          digitalWrite(RELAY_SW_OUT, false);
        }
      } else {
        cleanLuxArray();
        digitalWrite(RELAY_SW_OUT, false);
      }
    }
  }

}
<commit_msg>Changed time/date set<commit_after>/*
 *  This file is part of PlantLight application.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

/*
 * Built for Attiny85 1Mhz, using AVR USBasp programmer.
 * VERSION 0.7
 */

#include <avr/sleep.h>
#include <avr/interrupt.h>

#include <Arduino.h>
#include <TinyWireM.h>
#include <Time.h>
#include <BH1750FVI.h>
#include <DS1307RTC.h>

#define RELAY_SW_OUT            4       // Relay out pin
#define CMD_MAN_IN              1       // Manual light switch
#define WD_TICK_TIME            8       // Watchdog tick time [s] (check WD_MODE or datasheet)
#define WD_WAIT_TIME            24      // Time [s] to count between two sensor read
#define SAMPLE_COUNT            8       // Light sample count (average measurement)

// ####################### Prototypes #######################

// Setup watchdog wakeup interrupt
// tick: watchdog tick time [s] (check WD_MODE or datasheet)
void setupWatchdog(float tick);

// Set system into the sleep state,
// system wakes up when watchdog is timed out
void systemSleep();

// Provides a time_t to Time library, wrapper for call
// to RTC.get(), which is not a static function (class member)
time_t timeProvider();

// Display a date in readable format on the serial interface
void printDigits(int digits);
void SerialDisplayDateTime(const time_t &timeToDisplay);

// Sets the RTC to the new time
void setTime();

// Checks the current time of day and month of the year.
// Returns true if the light is now enabled.
boolean checkEnable(const time_t &now);

// Checks actual lux value. Returns true if the conditions
// to turn lights on are met.
boolean checkLightCond(float lux);

// Sample some lux value and calculate the running average over time
float sample();

void printLuxArray();
void cleanLuxArray();

// ####################### Constants ########################

// Watchdog interrupt sleep time
// 0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms, 6=1 sec, 7=2 sec, 8=4 sec, 9=8sec
const float WD_MODE[10] = { 0.016, 0.032, 0.064, 0.128, 0.25, 0.5, 1, 2, 4, 8 };

// ####################### Variables ########################

USI_TWI bus;                            // TinyWireM instance (I2C bus)
BH1750FVI BH1750(bus);                  // Light sensor instance
RTC_DS1307 RTC(bus);                    // RTC clock instance

tmDriftInfo di;

volatile uint8_t wdCount = 0;

// Watchdog interrupt count before reading light value
// wd count * wd interval == 4 * 8 s = 32 s
uint16_t wdMatch = 0;
boolean relayState = false, first = false;
static float luxSamples[SAMPLE_COUNT] = {};
static uint8_t readCounter = 0;

// ####################### Functions ########################

void setupWatchdog(float tick) {
  // 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
  // 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
  uint8_t wdreg, wdmode = 0;

  for (uint8_t i = 0; i < 10; ++i) {
    if (WD_MODE[i] == tick) {
      wdmode = i;
    }
  }

  if (wdmode > 9)
    wdmode = 9;
  wdreg = wdmode & 7;

  if (wdmode > 7)
    wdreg |= (1 << 5);
  wdreg |= (1 << WDCE);

  MCUSR &= ~(1 << WDRF);

  // Start timed sequence
  WDTCR |= (1 << WDCE) | (1 << WDE);

  // Set new watchdog timeout value
  WDTCR = wdreg;
  WDTCR |= _BV(WDIE);
}

void systemSleep() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // Sleep mode is set here
  sleep_enable();
  sleep_mode();                         // System actually sleeps here
  sleep_disable();                      // System continues execution here when watchdog timed out
}

// Watchdog Interrupt Service Routine
ISR(WDT_vect) {
  wdCount++;
}

// PCINT Interrupt Service Routine (unused)
ISR(PCINT0_vect) {
  // Don't do anything here but we must include this
  // block of code otherwise the interrupt calls an
  // uninitialized interrupt handler.
}

time_t timeProvider() {
  return RTC.get();
}

void printDigits(int digits) {
  // Utility function for digital clock display: prints preceding colon and leading 0
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void SerialDisplayDateTime(const time_t &timeToDisplay) {
  printDigits(day(timeToDisplay));
  Serial.print("/");
  printDigits(month(timeToDisplay));
  Serial.print("/");
  Serial.print(year(timeToDisplay));
  Serial.print(" ");
  printDigits(hour(timeToDisplay));
  Serial.print(":");
  printDigits(minute(timeToDisplay));
  Serial.print(":");
  printDigits(second(timeToDisplay));
  Serial.print(" ");
}

void setTime() {
  tmElements_t tme;
  time_t newTime;

  tme.Year   = 46;
  tme.Month  = 2;
  tme.Day    = 20;
  tme.Hour   = 17;
  tme.Minute = 9;
  tme.Second = 45;
  newTime = makeTime(tme);
  RTC.set(newTime);                             // Set the RTC
  setTime(newTime);                             // Set the system time

  tmDriftInfo diUpdate = RTC.read_DriftInfo();  // Update DriftInfo in RTC
  diUpdate.DriftStart = newTime;
  RTC.write_DriftInfo(diUpdate);

  SerialDisplayDateTime(newTime);
}

float sample() {
  float tmpLux = 0.0;
  // Shift left values in sample array
  for (int i = 0; i < SAMPLE_COUNT - 1; ++i) {
    luxSamples[i] = luxSamples[i + 1];
    tmpLux += luxSamples[i];
  }

  luxSamples[SAMPLE_COUNT - 1] = BH1750.getLightIntensity();  // Get lux value

  tmpLux += luxSamples[SAMPLE_COUNT - 1];

  if (readCounter < SAMPLE_COUNT) {
    readCounter++;
  }

  return tmpLux / readCounter;
}

void printLuxArray() {
  for (int i = 0; i < SAMPLE_COUNT; ++i) {
    Serial.print(luxSamples[i]);
    Serial.print(" ");
  }
}

void cleanLuxArray() {
  readCounter = 0;
  for (int i = 0; i < SAMPLE_COUNT; ++i) {
    luxSamples[i] = 0.0;
  }
}

boolean checkEnable(const time_t &now) {
  int nowH = hour(now);

  switch (month(now)) {
    // Winter
    case 1:
    case 2:
    case 10:
    case 11:
    case 12:
        if (nowH <= 16 || nowH >= 23) {
          return false;
        } else {
          return true;
        }
      break;

    // Spring / Autumn
    case 3:
    case 4:
    case 9:
      return false;
      break;

    // Summer
    case 5:
    case 6:
    case 7:
    case 8:
      return false;
      break;
    default:
      break;
  }

 return false;
}

boolean checkLightCond(float lux) {
  if (lux <= 10) {
    return true;
  } else {
    return false;
  }
}

void setup() {
  Serial.begin(9600);

  pinMode(RELAY_SW_OUT, OUTPUT);
  pinMode(CMD_MAN_IN, INPUT_PULLUP);

  // Setup watchdog timeout to 8 s (mode 9)
  setupWatchdog(WD_TICK_TIME);

  // Watchdog interrupt count before reading light value
  // example: wd count * wd interval == 4 * 8 s = 32 s
  wdMatch = (uint16_t) WD_WAIT_TIME / WD_TICK_TIME;

  // Setup Pin change interrupt on PCINT1
  GIMSK |= _BV(PCIE);
  PCMSK |= _BV(PCINT1);

  // Set the internal registers to reduce power consumes
  ACSR   = (1 << ACD);                  // Shut down the analog comparator
  MCUCR |= (1 << BODS);                 // BOD disabled

  // I2C begin() is called BEFORE sensors library "begin" methods:
  // it is called just once for all the sensors.
  bus.begin();

  // Sensors initialization
  // Light sensor
  BH1750.powerOn();
  BH1750.setMode(BH1750_CONTINUOUS_HIGH_RES_MODE_2);
  BH1750.setMtreg(200);                 // Set measurement time register to high value

  // Real time clock
  setSyncProvider(timeProvider);        // Pointer to function to get the time from the RTC
  setSyncInterval(WD_WAIT_TIME);        // Set system time at every sensor read

  // Update drift info from RTC
  di = RTC.read_DriftInfo();
  di.DriftDays = 1000;                  // RTC drift in seconds/day. 18 s per day is 18000/1000
  di.DriftSeconds = 18000;
  RTC.write_DriftInfo(di);
  setDriftInfo(di);
}

void loop() {
  BH1750.sleep();                       // Send light sensor to sleep
  systemSleep();                        // Send the unit to sleep

  // Manual command to turn light on
  if (!digitalRead(CMD_MAN_IN)) {
    if (!first) {
      // Used only once to set the time with external input
      // setTime();
      first = true;
      cleanLuxArray();
      digitalWrite(RELAY_SW_OUT, true);
    }

  } else  {
    // first = true -> First cycle in automatic mode, after manual mode

    if (wdCount >= wdMatch || first) {
      first = false;
      wdCount = 0;

      time_t timeNow = now();

      if (checkEnable(timeNow)) {
        BH1750.wakeUp(BH1750_CONTINUOUS_HIGH_RES_MODE_2);
        delay(300);

        float lux = sample();

#ifdef DEBUG
        SerialDisplayDateTime(timeNow);
        printLuxArray();
        Serial.print("= ");
        Serial.println(lux);
#endif
        if (checkLightCond(lux)) {
          digitalWrite(RELAY_SW_OUT, true);
        } else {
          digitalWrite(RELAY_SW_OUT, false);
        }
      } else {
        cleanLuxArray();
        digitalWrite(RELAY_SW_OUT, false);
      }
    }
  }

}
<|endoftext|>


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

#ifndef ADC_CPP_SOWNSTCK_HXX
#define ADC_CPP_SOWNSTCK_HXX

// USED SERVICES
    // BASE CLASSES
#include "cxt2ary.hxx"
    // COMPONENTS
#include <ary/cpp/c_etypes.hxx>
#include <estack.hxx>
    // PARAMETERS
#include <ary/cpp/c_namesp.hxx>
#include <x_parse.hxx>

namespace cpp
{

using ary::cpp::E_Protection;

/** Implementation struct for cpp::ContextForAry.
*/
struct ContextForAry::S_OwnerStack
{
  public:
                        S_OwnerStack();
    void                SetGlobalNamespace(
                            ary::cpp::Namespace &
                                                io_rGlobalNamespace );
                        ~S_OwnerStack();

    void                Reset();

    void                OpenNamespace(
                            ary::cpp::Namespace &
                                                io_rOpenedNamespace );
    void                OpenExternC();
    void                OpenClass(
                            ary::cpp::Class &   io_rOpenedClass );
    void                OpenEnum(
                            ary::cpp::Enum &    io_rOpenedEnum );
    void                CloseBlock();
    void                CloseClass();
    void                CloseEnum();
    void                SetCurProtection(
                            ary::cpp::E_Protection
                                                i_eProtection );
    ary::cpp::Namespace &
                        CurNamespace() const;
    ary::cpp::Class *   CurClass() const;
    ary::cpp::Enum *    CurEnum() const;

    Owner &             CurOwner() const;
    ary::cpp::E_Protection
                        CurProtection() const;
    bool                IsExternC() const       { return nExternC > 0; }

  private:
    typedef std::pair< ary::cpp::Class*, E_Protection >     ClassEnv;
    typedef EStack< ary::cpp::Namespace* >                  Stack_Namespaces;
    typedef EStack< ClassEnv >                              Stack_Classes;
    typedef ary::cpp::InputContext::Owner                   Ifc_Owner;

    void                SetOwner_2CurNamespace();
    void                SetOwner_2CurClass();
    void                SetOwner_2None();

    // DATA
    Stack_Namespaces    aStack_Namespaces;
    Stack_Classes       aStack_Classes;
    ary::cpp::Enum *    pCurEnum;
    uintt               nExternC;               /// This is a number, for the case that extern "C" blocks are nested.

    Dyn<Owner_Namespace>
                        pOwner_Namespace;
    Dyn<Owner_Class>    pOwner_Class;
    Ifc_Owner *         pOwner_Cur;
};

// IMPLEMENTATION

/*  The implementation is in header, though not inline, because this file is included
    in cxt2ary.cxx only!
*/

inline ary::cpp::Namespace &
ContextForAry::
S_OwnerStack::CurNamespace() const
{
    csv_assert( aStack_Namespaces.size() > 0 );
    return *aStack_Namespaces.top();
}

inline ary::cpp::Class *
ContextForAry::
S_OwnerStack::CurClass() const
{
    return aStack_Classes.size() > 0
                ?   aStack_Classes.top().first
                :   (ary::cpp::Class *) 0;
}

inline void
ContextForAry::
S_OwnerStack::SetOwner_2CurNamespace()
{
    csv_assert( aStack_Namespaces.size() > 0 );
    pOwner_Cur = pOwner_Namespace.MutablePtr();
    pOwner_Namespace->SetAnotherNamespace( CurNamespace() );
}

inline void
ContextForAry::
S_OwnerStack::SetOwner_2CurClass()
{
    csv_assert( aStack_Classes.size() > 0 );
    pOwner_Cur = pOwner_Class.MutablePtr();
    pOwner_Class->SetAnotherClass( *CurClass() );
}

ContextForAry::
S_OwnerStack::S_OwnerStack()
    :   // aStack_Namespaces,
        // aStack_Classes,
        pCurEnum(0),
        nExternC(0),
        pOwner_Namespace(new Owner_Namespace),
        pOwner_Class(new Owner_Class),
        pOwner_Cur(0)
{
}

void
ContextForAry::
S_OwnerStack::Reset()
{
    while ( aStack_Namespaces.top()->Owner() != 0 )
        aStack_Namespaces.pop();
    while ( NOT aStack_Classes.empty() )
        aStack_Classes.pop();
    pCurEnum = 0;
    nExternC = 0;
    SetOwner_2CurNamespace();
}

inline void
ContextForAry::
S_OwnerStack::SetGlobalNamespace( ary::cpp::Namespace & io_rGlobalNamespace )
{
    csv_assert( aStack_Namespaces.size() == 0 );
    aStack_Namespaces.push(&io_rGlobalNamespace);
    SetOwner_2CurNamespace();
}

ContextForAry::
S_OwnerStack::~S_OwnerStack()
{
}

inline void
ContextForAry::
S_OwnerStack::OpenNamespace( ary::cpp::Namespace & io_rOpenedNamespace )
{
    csv_assert( aStack_Namespaces.size() > 0  OR io_rOpenedNamespace.Parent() == 0 );
    aStack_Namespaces.push(&io_rOpenedNamespace);
    SetOwner_2CurNamespace();
}

inline void
ContextForAry::
S_OwnerStack::OpenExternC()
{
    ++nExternC;
//    SetOwner_2None();
}

inline void
ContextForAry::
S_OwnerStack::SetCurProtection( ary::cpp::E_Protection i_eProtection )
{
    csv_assert( aStack_Classes.size() > 0 );
    aStack_Classes.top().second = i_eProtection;
}

inline ary::cpp::Enum *
ContextForAry::
S_OwnerStack::CurEnum() const
{
    return pCurEnum;
}

inline ary::cpp::InputContext::Owner &
ContextForAry::
S_OwnerStack::CurOwner() const
{
    csv_assert( pOwner_Cur != 0 );
    return *pOwner_Cur;
}

inline E_Protection
ContextForAry::
S_OwnerStack::CurProtection() const
{
    return aStack_Classes.size() > 0
                ?   aStack_Classes.top().second
                :   ary::cpp::PROTECT_global;
}

inline void
ContextForAry::
S_OwnerStack::SetOwner_2None()
{
    pOwner_Cur = 0;
}

void
ContextForAry::
S_OwnerStack::OpenClass( ary::cpp::Class & io_rOpenedClass )
{
    E_Protection eDefaultProtection
            = io_rOpenedClass.ClassKey() == ary::cpp::CK_class
                    ?   ary::cpp::PROTECT_private
                    :   ary::cpp::PROTECT_public;
    aStack_Classes.push( ClassEnv(&io_rOpenedClass, eDefaultProtection) );
    SetOwner_2CurClass();
}

inline void
ContextForAry::
S_OwnerStack::OpenEnum( ary::cpp::Enum & io_rOpenedEnum )
{
    csv_assert( pCurEnum == 0 );
    pCurEnum = &io_rOpenedEnum;
    SetOwner_2None();
}

void
ContextForAry::
S_OwnerStack::CloseBlock()
{
    if (nExternC > 0)
    {
        --nExternC;
    }
    else
    {
        // csv_assert( aStack_Classes.size() == 0 );
        if ( aStack_Classes.size() > 0 )
            throw X_Parser(X_Parser::x_UnspecifiedSyntaxError, "", udmstri::Null_(), 0);

        csv_assert( pCurEnum == 0 );
        aStack_Namespaces.pop();

        // csv_assert( aStack_Namespaces.size() > 0 );
        if( aStack_Namespaces.size() == 0 )
            throw X_Parser(X_Parser::x_UnspecifiedSyntaxError, "", udmstri::Null_(), 0);

    }
    SetOwner_2CurNamespace();
}

void
ContextForAry::
S_OwnerStack::CloseClass()
{
    // csv_assert( aStack_Classes.size() > 0 );
    if ( aStack_Classes.size() == 0 )
          throw X_Parser(X_Parser::x_UnspecifiedSyntaxError, "", udmstri::Null_(), 0);

    aStack_Classes.pop();
    if ( aStack_Classes.size() > 0 )
        SetOwner_2CurClass();
    else
        SetOwner_2CurNamespace();
}

void
ContextForAry::
S_OwnerStack::CloseEnum()
{
    csv_assert( pCurEnum != 0 );
    pCurEnum = 0;
    if ( aStack_Classes.size() > 0 )
        SetOwner_2CurClass();
    else
        SetOwner_2CurNamespace();
}

}   // namespace cpp

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.110); FILE MERGED 2005/09/05 13:11:54 rt 1.2.110.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sownstck.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 18:33:11 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef ADC_CPP_SOWNSTCK_HXX
#define ADC_CPP_SOWNSTCK_HXX

// USED SERVICES
    // BASE CLASSES
#include "cxt2ary.hxx"
    // COMPONENTS
#include <ary/cpp/c_etypes.hxx>
#include <estack.hxx>
    // PARAMETERS
#include <ary/cpp/c_namesp.hxx>
#include <x_parse.hxx>

namespace cpp
{

using ary::cpp::E_Protection;

/** Implementation struct for cpp::ContextForAry.
*/
struct ContextForAry::S_OwnerStack
{
  public:
                        S_OwnerStack();
    void                SetGlobalNamespace(
                            ary::cpp::Namespace &
                                                io_rGlobalNamespace );
                        ~S_OwnerStack();

    void                Reset();

    void                OpenNamespace(
                            ary::cpp::Namespace &
                                                io_rOpenedNamespace );
    void                OpenExternC();
    void                OpenClass(
                            ary::cpp::Class &   io_rOpenedClass );
    void                OpenEnum(
                            ary::cpp::Enum &    io_rOpenedEnum );
    void                CloseBlock();
    void                CloseClass();
    void                CloseEnum();
    void                SetCurProtection(
                            ary::cpp::E_Protection
                                                i_eProtection );
    ary::cpp::Namespace &
                        CurNamespace() const;
    ary::cpp::Class *   CurClass() const;
    ary::cpp::Enum *    CurEnum() const;

    Owner &             CurOwner() const;
    ary::cpp::E_Protection
                        CurProtection() const;
    bool                IsExternC() const       { return nExternC > 0; }

  private:
    typedef std::pair< ary::cpp::Class*, E_Protection >     ClassEnv;
    typedef EStack< ary::cpp::Namespace* >                  Stack_Namespaces;
    typedef EStack< ClassEnv >                              Stack_Classes;
    typedef ary::cpp::InputContext::Owner                   Ifc_Owner;

    void                SetOwner_2CurNamespace();
    void                SetOwner_2CurClass();
    void                SetOwner_2None();

    // DATA
    Stack_Namespaces    aStack_Namespaces;
    Stack_Classes       aStack_Classes;
    ary::cpp::Enum *    pCurEnum;
    uintt               nExternC;               /// This is a number, for the case that extern "C" blocks are nested.

    Dyn<Owner_Namespace>
                        pOwner_Namespace;
    Dyn<Owner_Class>    pOwner_Class;
    Ifc_Owner *         pOwner_Cur;
};

// IMPLEMENTATION

/*  The implementation is in header, though not inline, because this file is included
    in cxt2ary.cxx only!
*/

inline ary::cpp::Namespace &
ContextForAry::
S_OwnerStack::CurNamespace() const
{
    csv_assert( aStack_Namespaces.size() > 0 );
    return *aStack_Namespaces.top();
}

inline ary::cpp::Class *
ContextForAry::
S_OwnerStack::CurClass() const
{
    return aStack_Classes.size() > 0
                ?   aStack_Classes.top().first
                :   (ary::cpp::Class *) 0;
}

inline void
ContextForAry::
S_OwnerStack::SetOwner_2CurNamespace()
{
    csv_assert( aStack_Namespaces.size() > 0 );
    pOwner_Cur = pOwner_Namespace.MutablePtr();
    pOwner_Namespace->SetAnotherNamespace( CurNamespace() );
}

inline void
ContextForAry::
S_OwnerStack::SetOwner_2CurClass()
{
    csv_assert( aStack_Classes.size() > 0 );
    pOwner_Cur = pOwner_Class.MutablePtr();
    pOwner_Class->SetAnotherClass( *CurClass() );
}

ContextForAry::
S_OwnerStack::S_OwnerStack()
    :   // aStack_Namespaces,
        // aStack_Classes,
        pCurEnum(0),
        nExternC(0),
        pOwner_Namespace(new Owner_Namespace),
        pOwner_Class(new Owner_Class),
        pOwner_Cur(0)
{
}

void
ContextForAry::
S_OwnerStack::Reset()
{
    while ( aStack_Namespaces.top()->Owner() != 0 )
        aStack_Namespaces.pop();
    while ( NOT aStack_Classes.empty() )
        aStack_Classes.pop();
    pCurEnum = 0;
    nExternC = 0;
    SetOwner_2CurNamespace();
}

inline void
ContextForAry::
S_OwnerStack::SetGlobalNamespace( ary::cpp::Namespace & io_rGlobalNamespace )
{
    csv_assert( aStack_Namespaces.size() == 0 );
    aStack_Namespaces.push(&io_rGlobalNamespace);
    SetOwner_2CurNamespace();
}

ContextForAry::
S_OwnerStack::~S_OwnerStack()
{
}

inline void
ContextForAry::
S_OwnerStack::OpenNamespace( ary::cpp::Namespace & io_rOpenedNamespace )
{
    csv_assert( aStack_Namespaces.size() > 0  OR io_rOpenedNamespace.Parent() == 0 );
    aStack_Namespaces.push(&io_rOpenedNamespace);
    SetOwner_2CurNamespace();
}

inline void
ContextForAry::
S_OwnerStack::OpenExternC()
{
    ++nExternC;
//    SetOwner_2None();
}

inline void
ContextForAry::
S_OwnerStack::SetCurProtection( ary::cpp::E_Protection i_eProtection )
{
    csv_assert( aStack_Classes.size() > 0 );
    aStack_Classes.top().second = i_eProtection;
}

inline ary::cpp::Enum *
ContextForAry::
S_OwnerStack::CurEnum() const
{
    return pCurEnum;
}

inline ary::cpp::InputContext::Owner &
ContextForAry::
S_OwnerStack::CurOwner() const
{
    csv_assert( pOwner_Cur != 0 );
    return *pOwner_Cur;
}

inline E_Protection
ContextForAry::
S_OwnerStack::CurProtection() const
{
    return aStack_Classes.size() > 0
                ?   aStack_Classes.top().second
                :   ary::cpp::PROTECT_global;
}

inline void
ContextForAry::
S_OwnerStack::SetOwner_2None()
{
    pOwner_Cur = 0;
}

void
ContextForAry::
S_OwnerStack::OpenClass( ary::cpp::Class & io_rOpenedClass )
{
    E_Protection eDefaultProtection
            = io_rOpenedClass.ClassKey() == ary::cpp::CK_class
                    ?   ary::cpp::PROTECT_private
                    :   ary::cpp::PROTECT_public;
    aStack_Classes.push( ClassEnv(&io_rOpenedClass, eDefaultProtection) );
    SetOwner_2CurClass();
}

inline void
ContextForAry::
S_OwnerStack::OpenEnum( ary::cpp::Enum & io_rOpenedEnum )
{
    csv_assert( pCurEnum == 0 );
    pCurEnum = &io_rOpenedEnum;
    SetOwner_2None();
}

void
ContextForAry::
S_OwnerStack::CloseBlock()
{
    if (nExternC > 0)
    {
        --nExternC;
    }
    else
    {
        // csv_assert( aStack_Classes.size() == 0 );
        if ( aStack_Classes.size() > 0 )
            throw X_Parser(X_Parser::x_UnspecifiedSyntaxError, "", udmstri::Null_(), 0);

        csv_assert( pCurEnum == 0 );
        aStack_Namespaces.pop();

        // csv_assert( aStack_Namespaces.size() > 0 );
        if( aStack_Namespaces.size() == 0 )
            throw X_Parser(X_Parser::x_UnspecifiedSyntaxError, "", udmstri::Null_(), 0);

    }
    SetOwner_2CurNamespace();
}

void
ContextForAry::
S_OwnerStack::CloseClass()
{
    // csv_assert( aStack_Classes.size() > 0 );
    if ( aStack_Classes.size() == 0 )
          throw X_Parser(X_Parser::x_UnspecifiedSyntaxError, "", udmstri::Null_(), 0);

    aStack_Classes.pop();
    if ( aStack_Classes.size() > 0 )
        SetOwner_2CurClass();
    else
        SetOwner_2CurNamespace();
}

void
ContextForAry::
S_OwnerStack::CloseEnum()
{
    csv_assert( pCurEnum != 0 );
    pCurEnum = 0;
    if ( aStack_Classes.size() > 0 )
        SetOwner_2CurClass();
    else
        SetOwner_2CurNamespace();
}

}   // namespace cpp

#endif

<|endoftext|>


<commit_before>#include <spv_utils.h>
#include <array>
#include <catch.hpp>
#include <cstdint>
#include <fstream>
#include <iostream>

#define STR_EXPAND(str) #str
#define STR(str) STR_EXPAND(str)

TEST_CASE("spv utils is tested with correct spir-v binary",
          "[spv-utils-correct-spvbin]") {
  // Read spv binary module from a file
  std::ifstream spv_file(STR(SPV_ASSETS_FOLDER) "/test.frag.spv",
                         std::ios::binary | std::ios::ate | std::ios::in);
  REQUIRE(spv_file.is_open() == true);
  std::streampos size = spv_file.tellg();
  CHECK(size > 0);

  spv_file.seekg(0, std::ios::beg);
  char *data = new char[size];
  spv_file.read(data, size);
  spv_file.close();

  SECTION("Passing a null ptr for the data throws an exception") {
    REQUIRE_THROWS_AS(sut::OpcodeStream(nullptr, size), sut::InvalidParameter);
  }
  SECTION("Passing size zero for the size throws an exception") {
    REQUIRE_THROWS_AS(sut::OpcodeStream(data, 0), sut::InvalidParameter);
  }
  SECTION("Passing size zero for the size and nullptr throws an exception") {
    REQUIRE_THROWS_AS(sut::OpcodeStream(nullptr, 0), sut::InvalidParameter);
  }
  SECTION("Passing correct data ptr and size creates the object") {
    REQUIRE_NOTHROW(sut::OpcodeStream(data, size));

    uint32_t instruction = 0xDEADBEEF;
    std::array<uint32_t, 4U> longer_instruction = {0xDEADBEEF, 0xDEADBEEF,
                                                   0xDEADBEEF, 0xDEADBEEF};
    std::array<uint32_t, 4U> longer_instruction_2 = {0x1EADBEEF, 0x1EADBEEF,
                                                     0x1EADBEEF, 0x1EADBEEF};
    SECTION(
        "Inserting before, after and removing produces an output of the right "
        "size") {
      sut::OpcodeStream stream(data, size);
      for (auto &i : stream) {
        if (i.GetOpcode() == spv::Op::OpCapability) {
          i.InsertBefore(longer_instruction.data(), longer_instruction.size());
          i.InsertAfter(&instruction, 1U);
          i.InsertAfter(longer_instruction.data(), longer_instruction.size());
          i.InsertAfter(longer_instruction.data(), longer_instruction.size());
          i.InsertBefore(longer_instruction_2.data(),
                         longer_instruction_2.size());
          i.Remove();
        }
      }

      sut::OpcodeStream new_stream = stream.EmitFilteredStream();
      std::vector<uint32_t> new_module = new_stream.GetWordsStream();

      // -1 is due to removing the instruction OpCapability which is 2 words
      // long
      // and adding one instruction one word long.
      REQUIRE(new_module.size() ==
              ((size / 4) + (longer_instruction.size() * 3) +
               longer_instruction_2.size() - 1));
    }

    SECTION("Replacing produces an output of the right size") {
      sut::OpcodeStream stream(data, size);
      for (auto &i : stream) {
        if (i.GetOpcode() == spv::Op::OpCapability) {
          i.Replace(longer_instruction.data(), longer_instruction.size());
        }
      }

      sut::OpcodeStream new_stream = stream.EmitFilteredStream();
      std::vector<uint32_t> new_module = new_stream.GetWordsStream();

      // -2 is due to removing the instruction OpCapability which is 2 words
      // long
      REQUIRE(new_module.size() ==
              ((size / 4) + longer_instruction.size() - 2));
    }

    SECTION("Inserting does not alter the size of the original raw module") {
      sut::OpcodeStream stream(data, size);
      for (auto &i : stream) {
        if (i.GetOpcode() == spv::Op::OpCapability) {
          i.InsertAfter(longer_instruction.data(), longer_instruction.size());
        }
      }

      std::vector<uint32_t> old_module = stream.GetWordsStream();

      // -2 is due to removing the instruction OpCapability which is 2 words
      // long
      REQUIRE(old_module.size() == size / 4 );
    }
  }
}
<commit_msg>Apply code formatting<commit_after>#include <spv_utils.h>
#include <array>
#include <catch.hpp>
#include <cstdint>
#include <fstream>
#include <iostream>

#define STR_EXPAND(str) #str
#define STR(str) STR_EXPAND(str)

TEST_CASE("spv utils is tested with correct spir-v binary",
          "[spv-utils-correct-spvbin]") {
  // Read spv binary module from a file
  std::ifstream spv_file(STR(SPV_ASSETS_FOLDER) "/test.frag.spv",
                         std::ios::binary | std::ios::ate | std::ios::in);
  REQUIRE(spv_file.is_open() == true);
  std::streampos size = spv_file.tellg();
  CHECK(size > 0);

  spv_file.seekg(0, std::ios::beg);
  char *data = new char[size];
  spv_file.read(data, size);
  spv_file.close();

  SECTION("Passing a null ptr for the data throws an exception") {
    REQUIRE_THROWS_AS(sut::OpcodeStream(nullptr, size), sut::InvalidParameter);
  }
  SECTION("Passing size zero for the size throws an exception") {
    REQUIRE_THROWS_AS(sut::OpcodeStream(data, 0), sut::InvalidParameter);
  }
  SECTION("Passing size zero for the size and nullptr throws an exception") {
    REQUIRE_THROWS_AS(sut::OpcodeStream(nullptr, 0), sut::InvalidParameter);
  }
  SECTION("Passing correct data ptr and size creates the object") {
    REQUIRE_NOTHROW(sut::OpcodeStream(data, size));

    uint32_t instruction = 0xDEADBEEF;
    std::array<uint32_t, 4U> longer_instruction = {0xDEADBEEF, 0xDEADBEEF,
                                                   0xDEADBEEF, 0xDEADBEEF};
    std::array<uint32_t, 4U> longer_instruction_2 = {0x1EADBEEF, 0x1EADBEEF,
                                                     0x1EADBEEF, 0x1EADBEEF};
    SECTION(
        "Inserting before, after and removing produces an output of the right "
        "size") {
      sut::OpcodeStream stream(data, size);
      for (auto &i : stream) {
        if (i.GetOpcode() == spv::Op::OpCapability) {
          i.InsertBefore(longer_instruction.data(), longer_instruction.size());
          i.InsertAfter(&instruction, 1U);
          i.InsertAfter(longer_instruction.data(), longer_instruction.size());
          i.InsertAfter(longer_instruction.data(), longer_instruction.size());
          i.InsertBefore(longer_instruction_2.data(),
                         longer_instruction_2.size());
          i.Remove();
        }
      }

      sut::OpcodeStream new_stream = stream.EmitFilteredStream();
      std::vector<uint32_t> new_module = new_stream.GetWordsStream();

      // -1 is due to removing the instruction OpCapability which is 2 words
      // long
      // and adding one instruction one word long.
      REQUIRE(new_module.size() ==
              ((size / 4) + (longer_instruction.size() * 3) +
               longer_instruction_2.size() - 1));
    }

    SECTION("Replacing produces an output of the right size") {
      sut::OpcodeStream stream(data, size);
      for (auto &i : stream) {
        if (i.GetOpcode() == spv::Op::OpCapability) {
          i.Replace(longer_instruction.data(), longer_instruction.size());
        }
      }

      sut::OpcodeStream new_stream = stream.EmitFilteredStream();
      std::vector<uint32_t> new_module = new_stream.GetWordsStream();

      // -2 is due to removing the instruction OpCapability which is 2 words
      // long
      REQUIRE(new_module.size() ==
              ((size / 4) + longer_instruction.size() - 2));
    }

    SECTION("Inserting does not alter the size of the original raw module") {
      sut::OpcodeStream stream(data, size);
      for (auto &i : stream) {
        if (i.GetOpcode() == spv::Op::OpCapability) {
          i.InsertAfter(longer_instruction.data(), longer_instruction.size());
        }
      }

      std::vector<uint32_t> old_module = stream.GetWordsStream();

      // -2 is due to removing the instruction OpCapability which is 2 words
      // long
      REQUIRE(old_module.size() == size / 4);
    }
  }
}
<|endoftext|>


<commit_before>#include "../include/matrix.h"
#include <string>

template <class T>
matrix<T>::matrix(unsigned int x, unsigned int y){
	resize(x,y);
}

template <class T>
matrix<T>::matrix(matrix& matrix){
	*this = matrix;
}

template <class T>
void matrix<T>::resize(unsigned int x, unsigned int y){
	m.resize(x, vector<T>(y));
}

template <class T>
vector<T> & matrix<T>::operator[](unsigned int i) {
	return m[i];
}

template <class T>
matrix<T>& matrix<T>::operator=(matrix& matrix){
	m = matrix.m;
	return (*this);
}

//

template class matrix <int>;
template class matrix <double>;
template class matrix <float>;
template class matrix <char>;
template class matrix <string>;
<commit_msg>added bool template<commit_after>#include "../include/matrix.h"
#include <string>

template <class T>
matrix<T>::matrix(unsigned int x, unsigned int y){
	resize(x,y);
}

template <class T>
matrix<T>::matrix(matrix& matrix){
	*this = matrix;
}

template <class T>
void matrix<T>::resize(unsigned int x, unsigned int y){
	m.resize(x, vector<T>(y));
}

template <class T>
vector<T> & matrix<T>::operator[](unsigned int i) {
	return m[i];
}

template <class T>
matrix<T>& matrix<T>::operator=(matrix& matrix){
	m = matrix.m;
	return (*this);
}

//

template class matrix <int>;
template class matrix <double>;
template class matrix <float>;
template class matrix <char>;
template class matrix <string>;
template class matrix <bool>;
<|endoftext|>


<commit_before>#include "luciconnect/message.h"

namespace luciconnect {
  Message::Message(json header) {
    this->header_ = header;

    if(!this->ValidateHeader()) {
      LOG(ERROR) << "Header validation failed";
      throw "Header validation failed";
    }
  }

  Message* Message::RunMessage(int64_t callId, std::string serviceName, json inputs, std::vector<Attachment*> attachments) {
    json header = {{"run", serviceName},{"callID", callId}};
    for (json::iterator it = inputs.begin(); it != inputs.end(); ++it)
      header[it.key()] = it.value();
    Message* message = new Message(header);
    for (Attachment* atc : attachments)
      message->AddAttachment(atc);
    return message;
  }

  Message* Message::CancelMessage(int64_t callId) {
    json header = {{"cancel", callId}, {"callID", callId}};
    return new Message(header);
  }

  Message* Message::ResultMessage(int64_t callId, json result, std::vector<Attachment*> attachments) {
    json header = {
      {"result", result},
      {"callID", callId}
    };
    Message* message = new Message(header);
    for (Attachment* atc : attachments)
      message->AddAttachment(atc);
    return message;
  }

  Message* Message::ProgressMessage(int64_t callId, int64_t percentage, std::vector<Attachment*> attachments, json intermediateResult) {
    json header = {
      {"progress", percentage},
      {"callID", callId},
      {"intermediateResult", intermediateResult}
    };
    Message* message = new Message(header);
    for (Attachment* atc : attachments)
      message->AddAttachment(atc);
    return message;
  }

  Message* Message::ErrorMessage(int64_t callId, std::string error) {
    json header = {{"error", error}, {"callID", callId}};
    return new Message(header);
  }

  size_t Message::AddAttachment(Attachment* attachment) {
    size_t index = this->attachments_.size();
    size_t position = index + 1; // LC2 position starts at 1

    MD5 md5;
    std::string md5sum = md5(attachment->data, attachment->size);

    bool attachment_header_missing = true;
    for (json element : this->header_["result"]) {
      if (element.count("attachment") > 0 && element["attachment"]["position"] == position) {
          if (element.count("format") == 0  || element.count("name") == 0) {
            LOG(ERROR) << "Attachment header is incomplete";
            throw "Attachment header is incomplete";
          }

          if (element["attachment"].count("length") == 0  || element["attachment"].count("checksum") == 0) {
            LOG(ERROR) << "Attachment subheader is incomplete";
            throw "Attachment subheader is incomplete";
          }

          // validate
          if (md5sum != element["attachment"]["checksum"]) {
            LOG(ERROR) << "Attachment checksums do not match up";
            throw "Attachment checksums do not match up";
          }

          if (attachment->size != element["attachment"]["length"]) {
            LOG(ERROR) << "Attachment sizes do not match up.";
            throw "Attachment sizes do not match up";
          }

          attachment_header_missing = false;
          attachment->format = element["format"];
          attachment->name = element["name"];
      }
    }

    if (attachment_header_missing) {
      // construct header data for attachment
      json attachmentjson;
      attachmentjson["format"] = attachment->format;
      attachmentjson["attachment"] = {
        {"length", attachment->size},
        {"position", position},
        {"checksum", md5sum}
      };
      attachmentjson["name"] = attachment->name;

      this->header_["result"][attachment->name] = attachmentjson;
    }

    this->attachments_.push_back(attachment);
    return index;
  }

  Attachment* Message::GetAttachment(size_t index) {
    if (index >= this->attachments_.size()) {
      throw "Index out of bounds";
    }
    return this->attachments_[index];
  }

  std::vector<Attachment*> Message::GetAttachments() {
    return this->attachments_;
  }

  size_t Message::GetNumAttachments() {
    return this->attachments_.size();
  }

  json Message::GetHeader() {
    // copy header
    json header = json::parse(this->header_.dump());
    return header;
  }

  MessageType Message::GetType() {
    // copy header
    return this->type_;
  }

  bool Message::ValidateHeader() {
    if (this->header_.count("callID") != 1) {
      LOG(WARNING) << "Message does not contain a callID.";
      return false;
    }
    this->callId_ = this->header_["callID"];

    size_t runC, cancelC, resultC, progressC, errorC;
    runC = this->header_.count("run");
    cancelC = this->header_.count("cancel");
    resultC = this->header_.count("result");
    progressC = this->header_.count("progress");
    errorC = this->header_.count("error");

    size_t totalC = runC + cancelC + resultC + progressC + errorC;

    if (totalC < 1) {
      LOG(WARNING) << "Message contains no type keyword.";
      return false;
    }

    if (totalC > 1) {
      LOG(WARNING) << "Message contains more than two type keywords.";
      return false;
    }

    if (runC) {
      this->type_ = MessageType::run;
      return ValidateRunMessage();
    }

    if (cancelC) {
      this->type_ = MessageType::cancel;
      return ValidateCancelMessage();
    }

    if (resultC) {
      this->type_ = MessageType::result;
      return ValidateResultMessage();
    }

    if (progressC) {
      this->type_ = MessageType::progress;
      return ValidateProgressMessage();
    }

    if (errorC) {
      this->type_ = MessageType::error;
      return ValidateErrorMessage();
    }

    return false;
  }

  bool Message::ValidateRunMessage() {
    std::string serviceName;
    try {
      serviceName = this->header_["run"];
      return !serviceName.empty();
    }
    catch (std::exception& err) {
      LOG(WARNING) << "Message of type `run` - validation failed. Header: " << this->header_.dump();;
      return false;
    }
  }

  bool Message::ValidateCancelMessage() {
    try {
      return this->header_["cancel"] == nullptr\
       || this->header_["cancel"] == (json){}\
       || this->header_["cancel"] == this->header_["callID"];
    }
    catch (std::exception& err) {
      LOG(WARNING) << "Message of type `cancel` - validation failed. Header: " << this->header_.dump();;
      return false;
    }
  }

  bool Message::ValidateResultMessage() {
    json result;
    std::string serviceName;

    try {
      result = this->header_["result"];
      (int64_t)this->header_["callID"];
      return true;
    }
    catch (std::exception& err) {
      LOG(WARNING) << "Message of type `result` - validation failed. Header: " << this->header_.dump();
      return false;
    }
  }

  bool Message::ValidateProgressMessage() {
    json intermediateResult;
    std::string serviceName;

    try {
      (int64_t)this->header_["progress"];
      (int64_t)this->header_["callID"];
      if (this->header_.count("intermediateResult") > 0)
        intermediateResult = this->header_["intermediateResult"];
      return true;
    }
    catch (std::exception& err) {
      LOG(WARNING) << "Message of type `progress` - validation failed. Header: " << this->header_.dump();;
      return false;
    }
  }

  bool Message::ValidateErrorMessage() {
    std::string error;

    try {
      error = this->header_["error"];
      (int64_t)this->header_["callID"];
      return true;
    }
    catch (std::exception& err) {
      LOG(WARNING) << "Message of type `error` - validation failed. Header: " << this->header_.dump();;
      return false;
    }
  }
}
<commit_msg>Fixed #3<commit_after>#include "luciconnect/message.h"

namespace luciconnect {
  Message::Message(json header) {
    this->header_ = header;

    if(!this->ValidateHeader()) {
      LOG(ERROR) << "Header validation failed";
      throw "Header validation failed";
    }
  }

  Message* Message::RunMessage(int64_t callId, std::string serviceName, json inputs, std::vector<Attachment*> attachments) {
    json header = {{"run", serviceName},{"callID", callId}};
    for (json::iterator it = inputs.begin(); it != inputs.end(); ++it)
      header[it.key()] = it.value();
    Message* message = new Message(header);
    for (Attachment* atc : attachments)
      message->AddAttachment(atc);
    return message;
  }

  Message* Message::CancelMessage(int64_t callId) {
    json header = {{"cancel", callId}, {"callID", callId}};
    return new Message(header);
  }

  Message* Message::ResultMessage(int64_t callId, json result, std::vector<Attachment*> attachments) {
    json header = {
      {"result", result},
      {"callID", callId}
    };
    Message* message = new Message(header);
    for (Attachment* atc : attachments)
      message->AddAttachment(atc);
    return message;
  }

  Message* Message::ProgressMessage(int64_t callId, int64_t percentage, std::vector<Attachment*> attachments, json intermediateResult) {
    json header = {
      {"progress", percentage},
      {"callID", callId},
      {"intermediateResult", intermediateResult}
    };
    Message* message = new Message(header);
    for (Attachment* atc : attachments)
      message->AddAttachment(atc);
    return message;
  }

  Message* Message::ErrorMessage(int64_t callId, std::string error) {
    json header = {{"error", error}, {"callID", callId}};
    return new Message(header);
  }

  size_t Message::AddAttachment(Attachment* attachment) {
    size_t index = this->attachments_.size();
    size_t position = index + 1; // LC2 position starts at 1

    MD5 md5;
    std::string md5sum = md5(attachment->data, attachment->size);

    bool attachment_header_missing = true;
    for (json element : this->header_["result"]) {
      if (element.count("attachment") > 0 && element["attachment"]["position"] == position) {
          if (element.count("format") == 0  || element.count("name") == 0) {
            LOG(ERROR) << "Attachment header is incomplete";
            throw "Attachment header is incomplete";
          }

          if (element["attachment"].count("length") == 0  || element["attachment"].count("checksum") == 0) {
            LOG(ERROR) << "Attachment subheader is incomplete";
            throw "Attachment subheader is incomplete";
          }

          // validate
          if (md5sum != element["attachment"]["checksum"]) {
            LOG(ERROR) << "Attachment checksums do not match up";
            throw "Attachment checksums do not match up";
          }

          if (attachment->size != element["attachment"]["length"]) {
            LOG(ERROR) << "Attachment sizes do not match up.";
            throw "Attachment sizes do not match up";
          }

          attachment_header_missing = false;
          attachment->format = element["format"];
          attachment->name = element["name"];
      }
    }

    if (attachment_header_missing) {
      // construct header data for attachment
      json attachmentjson;
      attachmentjson["format"] = attachment->format;
      attachmentjson["attachment"] = {
        {"length", attachment->size},
        {"position", position},
        {"checksum", md5sum}
      };
      attachmentjson["name"] = attachment->name;

      this->header_["result"][attachment->name] = attachmentjson;
    }

    this->attachments_.push_back(attachment);
    return index;
  }

  Attachment* Message::GetAttachment(size_t index) {
    if (index >= this->attachments_.size()) {
      throw "Index out of bounds";
    }
    return this->attachments_[index];
  }

  std::vector<Attachment*> Message::GetAttachments() {
    return this->attachments_;
  }

  size_t Message::GetNumAttachments() {
    return this->attachments_.size();
  }

  json Message::GetHeader() {
    // copy header
    json header = json::parse(this->header_.dump());
    return header;
  }

  MessageType Message::GetType() {
    // copy header
    return this->type_;
  }

  bool Message::ValidateHeader() {
    // callID-check currently not enforced for error messages => handling also doesn't work! // TODO
    if (this->header_.count("error") == 0 && this->header_.count("callID") != 1) {
      LOG(WARNING) << "Message does not contain a callID.";
      return false;
    }
    this->callId_ = this->header_["callID"];

    size_t runC, cancelC, resultC, progressC, errorC;
    runC = this->header_.count("run");
    cancelC = this->header_.count("cancel");
    resultC = this->header_.count("result");
    progressC = this->header_.count("progress");
    errorC = this->header_.count("error");

    size_t totalC = runC + cancelC + resultC + progressC + errorC;

    if (totalC < 1) {
      LOG(WARNING) << "Message contains no type keyword.";
      return false;
    }

    if (totalC > 1) {
      LOG(WARNING) << "Message contains more than two type keywords.";
      return false;
    }

    if (runC) {
      this->type_ = MessageType::run;
      return ValidateRunMessage();
    }

    if (cancelC) {
      this->type_ = MessageType::cancel;
      return ValidateCancelMessage();
    }

    if (resultC) {
      this->type_ = MessageType::result;
      return ValidateResultMessage();
    }

    if (progressC) {
      this->type_ = MessageType::progress;
      return ValidateProgressMessage();
    }

    if (errorC) {
      this->type_ = MessageType::error;
      return ValidateErrorMessage();
    }

    return false;
  }

  bool Message::ValidateRunMessage() {
    std::string serviceName;
    try {
      serviceName = this->header_["run"];
      return !serviceName.empty();
    }
    catch (std::exception& err) {
      LOG(WARNING) << "Message of type `run` - validation failed. Header: " << this->header_.dump();;
      return false;
    }
  }

  bool Message::ValidateCancelMessage() {
    try {
      return this->header_["cancel"] == nullptr\
       || this->header_["cancel"] == (json){}\
       || this->header_["cancel"] == this->header_["callID"];
    }
    catch (std::exception& err) {
      LOG(WARNING) << "Message of type `cancel` - validation failed. Header: " << this->header_.dump();;
      return false;
    }
  }

  bool Message::ValidateResultMessage() {
    json result;
    std::string serviceName;

    try {
      result = this->header_["result"];
      (int64_t)this->header_["callID"];
      return true;
    }
    catch (std::exception& err) {
      LOG(WARNING) << "Message of type `result` - validation failed. Header: " << this->header_.dump();
      return false;
    }
  }

  bool Message::ValidateProgressMessage() {
    json intermediateResult;
    std::string serviceName;

    try {
      (int64_t)this->header_["progress"];
      (int64_t)this->header_["callID"];
      if (this->header_.count("intermediateResult") > 0)
        intermediateResult = this->header_["intermediateResult"];
      return true;
    }
    catch (std::exception& err) {
      LOG(WARNING) << "Message of type `progress` - validation failed. Header: " << this->header_.dump();;
      return false;
    }
  }

  bool Message::ValidateErrorMessage() {
    std::string error;

    try {
      error = this->header_["error"];
      (int64_t)this->header_["callID"];
      return true;
    }
    catch (std::exception& err) {
      LOG(WARNING) << "Message of type `error` - validation failed. Header: " << this->header_.dump();;
      return false;
    }
  }
}
<|endoftext|>