<commit_before>#include <geometry_msgs/Quaternion.h>
#include <ros/ros.h>
#include <serial/serial.h>
#include <sensor_msgs/Imu.h>
#include <std_msgs/String.h>
#include <std_srvs/Empty.h>
#include <string>
#include <tf/transform_broadcaster.h>
#include <tf/transform_datatypes.h>

bool zero_orientation_set = false;

bool set_zero_orientation(std_srvs::Empty::Request&,
			  std_srvs::Empty::Response&)
{
  ROS_INFO("Zero Orientation Set.");
  zero_orientation_set = false;
  return true;
}

int main(int argc, char** argv)
{
  serial::Serial ser;
  std::string port;
  std::string tf_parent_frame_id;
  std::string tf_frame_id;
  std::string imu_frame_id;
  double time_offset_in_seconds;

  tf::Quaternion orientation;
  tf::Quaternion zero_orientation;

  std::string partial_line = "";

  ros::init(argc, argv, "mpu6050_serial_to_imu_node");

  ros::NodeHandle private_node_handle("~");
  private_node_handle.param<std::string>("port", port, "/dev/ttyACM0");
  private_node_handle.param<std::string>("tf_parent_frame_id", tf_parent_frame_id, "imu_base");
  private_node_handle.param<std::string>("tf_frame_id", tf_frame_id, "imu");
  private_node_handle.param<std::string>("imu_frame_id", imu_frame_id, "imu_base");
  private_node_handle.param<double>("time_offset_in_seconds", time_offset_in_seconds, 0.0);

  ros::NodeHandle nh;
  ros::Publisher imu_pub = nh.advertise<sensor_msgs::Imu>("imu", 50);
  ros::ServiceServer service = nh.advertiseService("set_zero_orientation", set_zero_orientation);

  ros::Rate r(1000); // 1000 hz

  while(ros::ok())
  {
    try
    {
      if (ser.isOpen())
      {

        // read string from serial device
        if(ser.available())
        {
          //ROS_INFO_STREAM("Reading from serial port");
          std_msgs::String result;
          result.data = ser.readline(ser.available(), "\n");
          //ROS_INFO_STREAM("Read: " << result.data);

          // find distance__ tag
          std::string input = partial_line + result.data;
          //std::cout << " *********** :"  << input << std::endl;

          // is this a complete line? the atoi lines crash if the string is not long enough
          if (input.at( input.length() - 1 ) == '\n')
          {
            // line complete, delete partial_line var
            partial_line = "";
            //ROS_INFO_STREAM("Read: " << input);
            // TODO check if line is long enough??

            if (input.compare(0,53,"Send any character to begin DMP programming and demo:") == 0 )
            {
              ROS_INFO("Sending 'A'");
              ser.write("A");
            }

            // parse line, get quaternion values

            if (input.compare(0,2,"$\x02") == 0 && (input.size() == 14))
            {
              for (int i = 0; i < 14; i= i+1)
	      {
                  //ROS_INFO("%d: %02x", i , 0xff & (char)input[i]);
              }
              //ROS_INFO_STREAM(std::hex << input << std::dec);
             // std::string channelString = input.substr(10,1);
               uint w = (((0xff &(char)input[2]) << 8) | 0xff &(char)input[3]) ;
               ROS_INFO("w = %04x", w );

               uint x = (((0xff &(char)input[4]) << 8) | 0xff &(char)input[5]);
               ROS_INFO("x = %04x", x );

               uint y = (((0xff &(char)input[6]) << 8) | 0xff &(char)input[7]);
               ROS_INFO("y = %04x", y );

               uint z = (((0xff &(char)input[8]) << 8) | 0xff &(char)input[9]);
               ROS_INFO("z = %04x", z );
              //int value = atoi(input.substr(12,4).c_str());

              double wf = w/16384.0;
              double xf = x/16384.0;
              double yf = y/16384.0;
              double zf = z/16384.0;

              if (wf >= 2.0)
		wf = -4.0 +wf;

              if (xf >= 2.0)
		xf = -4.0 +xf;

              if (yf >= 2.0)
		yf = -4.0 +yf;

              if (zf >= 2.0)
		zf = -4.0 +zf;

              tf::Quaternion orientation(xf, yf, zf, wf);

              if (!zero_orientation_set)
              {
                zero_orientation = orientation;
                zero_orientation_set = true;
              }

              //http://answers.ros.org/question/10124/relative-rotation-between-two-quaternions/

              tf::Quaternion differential_rotation;
              differential_rotation = zero_orientation.inverse() * orientation;

              // calculate measurement time
              ros::Time measurement_time = ros::Time::now() + ros::Duration(time_offset_in_seconds);

              // publish imu message
              sensor_msgs::Imu imu;
              imu.header.stamp = measurement_time;
              imu.header.frame_id = imu_frame_id;

// http://answers.ros.org/question/50870/what-frame-is-sensor_msgsimuorientation-relative-to/

// rosserial imu message zui groß für arduino buffer ?????
// http://answers.ros.org/question/91301/rosserial-fails-when-using-sensor_msgsimu/

              quaternionTFToMsg(differential_rotation, imu.orientation);

              // i do not know the orientation covariance
              imu.orientation_covariance[0] = 0;
              imu.orientation_covariance[1] = 0;
              imu.orientation_covariance[2] = 0;
              imu.orientation_covariance[3] = 0;
              imu.orientation_covariance[4] = 0;
              imu.orientation_covariance[5] = 0;
              imu.orientation_covariance[6] = 0;
              imu.orientation_covariance[7] = 0;
              imu.orientation_covariance[8] = 0;

              // angular velocity is not provided
              imu.angular_velocity_covariance[0] = -1;

              // linear acceleration is not provided
              imu.linear_acceleration_covariance[0] = -1;

              imu_pub.publish(imu);

              // publish tf transform

              static tf::TransformBroadcaster br;
              tf::Transform transform;
              transform.setRotation(differential_rotation);
              br.sendTransform(tf::StampedTransform(transform, measurement_time, tf_parent_frame_id, tf_frame_id));
            }
          }
          else
          {
            // line incomplete, remember already received characters
            partial_line = input;
          }
        }
        else  // ser not available
        {

        }
      }
      else
      {
        // try and open the serial port
        try
        {
          ser.setPort(port);
          ser.setBaudrate(115200);
          serial::Timeout to = serial::Timeout::simpleTimeout(1000);
          ser.setTimeout(to);
          ser.open();
        }
        catch (serial::IOException& e)
        {
          ROS_ERROR_STREAM("Unable to open serial port " << ser.getPort() << ". Trying again in 5 seconds.");
          ros::Duration(5).sleep();
        }

        if(ser.isOpen())
        {
          ROS_INFO_STREAM("Serial port " << ser.getPort() << " initialized.");
        }
        else
        {
          //ROS_INFO_STREAM("Could not initialize serial port.");
        }

      }
    }
    catch (serial::IOException& e)
    {
      ROS_ERROR_STREAM("Error reading from the serial port " << ser.getPort() << ". Closing connection.");
      ser.close();
    }
    ros::spinOnce();
    r.sleep();
  }
}

<commit_msg>fixed indentation, moved INFO outputs to DEBUG, removed old comments<commit_after>#include <geometry_msgs/Quaternion.h>
#include <ros/ros.h>
#include <serial/serial.h>
#include <sensor_msgs/Imu.h>
#include <std_msgs/String.h>
#include <std_srvs/Empty.h>
#include <string>
#include <tf/transform_broadcaster.h>
#include <tf/transform_datatypes.h>

bool zero_orientation_set = false;

bool set_zero_orientation(std_srvs::Empty::Request&,
                          std_srvs::Empty::Response&)
{
  ROS_INFO("Zero Orientation Set.");
  zero_orientation_set = false;
  return true;
}

int main(int argc, char** argv)
{
  serial::Serial ser;
  std::string port;
  std::string tf_parent_frame_id;
  std::string tf_frame_id;
  std::string imu_frame_id;
  double time_offset_in_seconds;

  tf::Quaternion orientation;
  tf::Quaternion zero_orientation;

  std::string partial_line = "";

  ros::init(argc, argv, "mpu6050_serial_to_imu_node");

  ros::NodeHandle private_node_handle("~");
  private_node_handle.param<std::string>("port", port, "/dev/ttyACM0");
  private_node_handle.param<std::string>("tf_parent_frame_id", tf_parent_frame_id, "imu_base");
  private_node_handle.param<std::string>("tf_frame_id", tf_frame_id, "imu");
  private_node_handle.param<std::string>("imu_frame_id", imu_frame_id, "imu_base");
  private_node_handle.param<double>("time_offset_in_seconds", time_offset_in_seconds, 0.0);

  ros::NodeHandle nh;
  ros::Publisher imu_pub = nh.advertise<sensor_msgs::Imu>("imu", 50);
  ros::ServiceServer service = nh.advertiseService("set_zero_orientation", set_zero_orientation);

  ros::Rate r(1000); // 1000 hz

  while(ros::ok())
  {
    try
    {
      if (ser.isOpen())
      {
        // read string from serial device
        if(ser.available())
        {
          std_msgs::String result;
          result.data = ser.readline(ser.available(), "\n");

          std::string input = partial_line + result.data;

          if (input.at( input.length() - 1 ) == '\n')
          {
            // line complete, delete partial_line var
            partial_line = "";

            // TODO check if line is long enough??
            if (input.compare(0,53,"Send any character to begin DMP programming and demo:") == 0 )
            {
              ROS_DEBUG("Sending 'A'");
              ser.write("A");
            }

            // parse line, get quaternion values
            if (input.compare(0,2,"$\x02") == 0 && (input.size() == 14))
            {
              uint w = (((0xff &(char)input[2]) << 8) | 0xff &(char)input[3]);
              ROS_DEBUG("w = %04x", w );

              uint x = (((0xff &(char)input[4]) << 8) | 0xff &(char)input[5]);
              ROS_DEBUG("x = %04x", x );

              uint y = (((0xff &(char)input[6]) << 8) | 0xff &(char)input[7]);
              ROS_DEBUG("y = %04x", y );

              uint z = (((0xff &(char)input[8]) << 8) | 0xff &(char)input[9]);
              ROS_DEBUG("z = %04x", z );

              double wf = w/16384.0;
              double xf = x/16384.0;
              double yf = y/16384.0;
              double zf = z/16384.0;

              if (wf >= 2.0)
              {
                wf = -4.0 +wf;
              }

              if (xf >= 2.0)
              {
                xf = -4.0 +xf;
              }

              if (yf >= 2.0)
              {
                yf = -4.0 +yf;
              }

              if (zf >= 2.0)
              {
                zf = -4.0 +zf;
              }

              tf::Quaternion orientation(xf, yf, zf, wf);

              if (!zero_orientation_set)
              {
                zero_orientation = orientation;
                zero_orientation_set = true;
              }

              //http://answers.ros.org/question/10124/relative-rotation-between-two-quaternions/
              tf::Quaternion differential_rotation;
              differential_rotation = zero_orientation.inverse() * orientation;

              // calculate measurement time
              ros::Time measurement_time = ros::Time::now() + ros::Duration(time_offset_in_seconds);

              // publish imu message
              sensor_msgs::Imu imu;
              imu.header.stamp = measurement_time;
              imu.header.frame_id = imu_frame_id;

              quaternionTFToMsg(differential_rotation, imu.orientation);

              // i do not know the orientation covariance
              imu.orientation_covariance[0] = 0;
              imu.orientation_covariance[1] = 0;
              imu.orientation_covariance[2] = 0;
              imu.orientation_covariance[3] = 0;
              imu.orientation_covariance[4] = 0;
              imu.orientation_covariance[5] = 0;
              imu.orientation_covariance[6] = 0;
              imu.orientation_covariance[7] = 0;
              imu.orientation_covariance[8] = 0;

              // angular velocity is not provided
              imu.angular_velocity_covariance[0] = -1;

              // linear acceleration is not provided
              imu.linear_acceleration_covariance[0] = -1;

              imu_pub.publish(imu);

              // publish tf transform
              static tf::TransformBroadcaster br;
              tf::Transform transform;
              transform.setRotation(differential_rotation);
              br.sendTransform(tf::StampedTransform(transform, measurement_time, tf_parent_frame_id, tf_frame_id));
            }
          }
          else
          {
            // line incomplete, remember already received characters
            partial_line = input;
          }
        }
        else  // ser not available
        {

        }
      }
      else
      {
        // try and open the serial port
        try
        {
          ser.setPort(port);
          ser.setBaudrate(115200);
          serial::Timeout to = serial::Timeout::simpleTimeout(1000);
          ser.setTimeout(to);
          ser.open();
        }
        catch (serial::IOException& e)
        {
          ROS_ERROR_STREAM("Unable to open serial port " << ser.getPort() << ". Trying again in 5 seconds.");
          ros::Duration(5).sleep();
        }

        if(ser.isOpen())
        {
          ROS_DEBUG_STREAM("Serial port " << ser.getPort() << " initialized.");
        }
        else
        {
          //ROS_INFO_STREAM("Could not initialize serial port.");
        }

      }
    }
    catch (serial::IOException& e)
    {
      ROS_ERROR_STREAM("Error reading from the serial port " << ser.getPort() << ". Closing connection.");
      ser.close();
    }
    ros::spinOnce();
    r.sleep();
  }
}

<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

#include <net/http/client_connection.hpp>
#include <net/http/basic_client.hpp>

namespace http {

  Client_connection::Client_connection(Basic_client& client, Stream_ptr stream)
    : Connection{std::move(stream)},
      client_(client),
      req_(nullptr),
      res_(nullptr),
      on_response_{nullptr},
      timer_({this, &Client_connection::timeout_request}),
      timeout_dur_{timeout_duration::zero()},
      redirect_{client.default_follow_redirect}
  {
    // setup close event
    stream_->on_close({this, &Client_connection::close});
  }

  void Client_connection::send(Request_ptr req, Response_handler on_res, int redirects, timeout_duration timeout)
  {
    Expects(available());
    req_ = std::move(req);
    on_response_ = std::move(on_res);
    Expects(on_response_ != nullptr);
    timeout_dur_ = timeout;
    redirect_ = redirects;

    if(timeout_dur_ > timeout_duration::zero())
      timer_.restart(timeout_dur_);

    // if the stream is not established, send the request when connected
    if(not stream_->is_connected())
    {
      stream_->on_connect([this](auto&)
      {
        this->send_request();
      });
    }
    else {
      send_request();
    }
  }

  void Client_connection::send_request()
  {
    keep_alive_ = (req_->header().value(header::Connection) != "close");

    stream_->on_read(0 , {this, &Client_connection::recv_response});

    stream_->write(req_->to_string());
  }

  void Client_connection::recv_response(buffer_t buf)
  {
    if (buf->empty()) {
      end_response({Error::NO_REPLY});
      return;
    }

    const std::string data{(char*) buf->data(), buf->size()};

    // restart timer since we got data
    if(timer_.is_running())
      timer_.restart(timeout_dur_);

    // create response if not exist
    if(res_ == nullptr)
    {
      try {
        res_ = make_response(data); // this also parses
      }
      catch(...)
      {
        end_response({Error::INVALID});
        return;
      }
    }
    // if there already is a response
    else
    {
      // this is the case when Status line is received, but not yet headers.
      if(not res_->headers_complete() && req_->method() != HEAD)
      {
        *res_ << data;
        res_->parse();
      }
      // here we assume all headers has already been received (could not be true?)
      else
      {
        // add chunks of body data
        res_->add_chunk(data);
      }
    }

    const auto& header = res_->header();
    // TODO: Temporary, not good enough
    // if(res_->is_complete())
    // Assume we want some headers
    if(!header.is_empty())
    {
      if(header.has_field(header::Content_Length))
      {
        try
        {
          const unsigned conlen = std::stoul(std::string(header.value(header::Content_Length)));
          const unsigned body_size = res_->body().size();
          //printf("<http::Connection> [%s] Data: %u ConLen: %u Body:%u\n",
          //  req_->uri().to_string().to_string().c_str(), data.size(), conlen, body_size);
          // risk buffering forever if no timeout
          if(body_size == conlen)
          {
            end_response();
          }
          else if(body_size > conlen)
          {
            end_response({Error::INVALID});
          }
        }
        catch(...)
        { end_response({Error::INVALID}); }
      }
      else
        end_response();
    }
    else if(req_->method() == HEAD)
    {
      end_response();
    }
  }

  void Client_connection::end_response(Error err)
  {
    // If the request has timed out, but the response is received later,
    // just discard (we can't do anything because we have no callback).
    // This MAY have side effects if the connection is reused and
    // a delayed response is received
    if (on_response_)
    {
      if(UNLIKELY(not err and can_redirect(res_)))
      {
        uri::URI location{res_->header().value("Location")};

        if(location.is_valid())
        {
          redirect(location);
          end(); // hope its good here..
          return;
        }

      }
      // move response to a copy in case of callback result in new request
      auto callback = std::move(on_response_);
      on_response_.reset();

      // stop timeout timer
      timer_.stop();

      callback(err, std::move(res_), *this);
    }
    end();
    /*if(!released())
    {
      // avoid trying to parse any more responses
      tcpconn_->on_read(0, nullptr);

      if(!keep_alive_) // user callback may override this
        shutdown();
    }
    else
    {
      close();
    }*/
  }

  bool Client_connection::can_redirect(const Response_ptr& res) const
  {
    if(redirect_ < 1) return false;
    if(res == nullptr) return false;
    if(not is_redirection(res->status_code())) return false;
    if(not res->header().has_field("Location")) return false;

    return true;
  }

  void Client_connection::redirect(uri::URI location)
  {
    Expects(on_response_);

    // modify req
    client_.populate_from_url(*req_, location);

    // build option
    Basic_client::Options options;
    options.timeout         = timeout_dur_;
    options.follow_redirect = --redirect_;

    // move callback
    auto callback = std::move(on_response_);
    on_response_.reset();

    // have client send new request
    client_.send(std::move(req_), location, std::move(callback), options);
  }

  void Client_connection::close()
  {
    // if the user havent received a response yet
    if(on_response_ != nullptr)
    {
      auto callback = std::move(on_response_);
      on_response_.reset();
      timer_.stop();
      callback(Error::CLOSING, std::move(res_), *this);
    }

    client_.close(*this);
  }

}
<commit_msg>http: Client wait for server close if no content length in header according to http 1.0 spec<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

#include <net/http/client_connection.hpp>
#include <net/http/basic_client.hpp>

namespace http {

  Client_connection::Client_connection(Basic_client& client, Stream_ptr stream)
    : Connection{std::move(stream)},
      client_(client),
      req_(nullptr),
      res_(nullptr),
      on_response_{nullptr},
      timer_({this, &Client_connection::timeout_request}),
      timeout_dur_{timeout_duration::zero()},
      redirect_{client.default_follow_redirect}
  {
    // setup close event
    stream_->on_close({this, &Client_connection::close});
  }

  void Client_connection::send(Request_ptr req, Response_handler on_res, int redirects, timeout_duration timeout)
  {
    Expects(available());
    req_ = std::move(req);
    on_response_ = std::move(on_res);
    Expects(on_response_ != nullptr);
    timeout_dur_ = timeout;
    redirect_ = redirects;

    if(timeout_dur_ > timeout_duration::zero())
      timer_.restart(timeout_dur_);

    // if the stream is not established, send the request when connected
    if(not stream_->is_connected())
    {
      stream_->on_connect([this](auto&)
      {
        this->send_request();
      });
    }
    else {
      send_request();
    }
  }

  void Client_connection::send_request()
  {
    keep_alive_ = (req_->header().value(header::Connection) != "close");

    stream_->on_read(0 , {this, &Client_connection::recv_response});

    stream_->write(req_->to_string());
  }

  void Client_connection::recv_response(buffer_t buf)
  {
    if (buf->empty()) {
      end_response({Error::NO_REPLY});
      return;
    }

    const std::string data{(char*) buf->data(), buf->size()};

    // restart timer since we got data
    if(timer_.is_running())
      timer_.restart(timeout_dur_);

    // create response if not exist
    if(res_ == nullptr)
    {
      try {
        res_ = make_response(data); // this also parses
      }
      catch(...)
      {
        end_response({Error::INVALID});
        return;
      }
    }
    // if there already is a response
    else
    {
      // this is the case when Status line is received, but not yet headers.
      if(not res_->headers_complete() && req_->method() != HEAD)
      {
        *res_ << data;
        res_->parse();
      }
      // here we assume all headers has already been received (could not be true?)
      else
      {
        // add chunks of body data
        res_->add_chunk(data);
      }
    }

    const auto& header = res_->header();
    // TODO: Temporary, not good enough
    // if(res_->is_complete())
    // Assume we want some headers
    if(!header.is_empty())
    {
      if(header.has_field(header::Content_Length))
      {
        try
        {
          const unsigned conlen = std::stoul(std::string(header.value(header::Content_Length)));
          const unsigned body_size = res_->body().size();
          //printf("<http::Connection> [%s] Data: %u ConLen: %u Body:%u\n",
          //  req_->uri().to_string().to_string().c_str(), data.size(), conlen, body_size);
          // risk buffering forever if no timeout
          if(body_size == conlen)
          {
            end_response();
          }
          else if(body_size > conlen)
          {
            end_response({Error::INVALID});
          }
        }
        catch(...)
        { end_response({Error::INVALID}); }
      }
    }
    else if(req_->method() == HEAD)
    {
      end_response();
    }
  }

  void Client_connection::end_response(Error err)
  {
    // If the request has timed out, but the response is received later,
    // just discard (we can't do anything because we have no callback).
    // This MAY have side effects if the connection is reused and
    // a delayed response is received
    if (on_response_)
    {
      if(UNLIKELY(not err and can_redirect(res_)))
      {
        uri::URI location{res_->header().value("Location")};

        if(location.is_valid())
        {
          redirect(location);
          end(); // hope its good here..
          return;
        }

      }
      // move response to a copy in case of callback result in new request
      auto callback = std::move(on_response_);
      on_response_.reset();

      // stop timeout timer
      timer_.stop();

      callback(err, std::move(res_), *this);
    }
    end();
    /*if(!released())
    {
      // avoid trying to parse any more responses
      tcpconn_->on_read(0, nullptr);

      if(!keep_alive_) // user callback may override this
        shutdown();
    }
    else
    {
      close();
    }*/
  }

  bool Client_connection::can_redirect(const Response_ptr& res) const
  {
    if(redirect_ < 1) return false;
    if(res == nullptr) return false;
    if(not is_redirection(res->status_code())) return false;
    if(not res->header().has_field("Location")) return false;

    return true;
  }

  void Client_connection::redirect(uri::URI location)
  {
    Expects(on_response_);

    // modify req
    client_.populate_from_url(*req_, location);

    // build option
    Basic_client::Options options;
    options.timeout         = timeout_dur_;
    options.follow_redirect = --redirect_;

    // move callback
    auto callback = std::move(on_response_);
    on_response_.reset();

    // have client send new request
    client_.send(std::move(req_), location, std::move(callback), options);
  }

  void Client_connection::close()
  {
    // if the user havent received a response yet
    if(on_response_ != nullptr)
    {
      auto callback = std::move(on_response_);
      on_response_.reset();
      timer_.stop();
      if(res_ != nullptr and res_->headers_complete()) {
        callback(Error::NONE, std::move(res_), *this);
      }
      else {
        callback(Error::CLOSING, std::move(res_), *this);
      }
    }

    client_.close(*this);
  }

}
<|endoftext|>


<commit_before><commit_msg>added cast to remove 'signed vs. unsigned' warning<commit_after><|endoftext|>


<commit_before>#ifndef ALPINO_CORPUSREADER_HH
#define ALPINO_CORPUSREADER_HH

#include <list>
#include <queue>
#include <string>
#include <tr1/memory>

#include <AlpinoCorpus/DLLDefines.hh>
#include <AlpinoCorpus/util/NonCopyable.hh>

namespace alpinocorpus {

/**
 * Abstract base class for corpus readers.
 *
 * A corpus is conceptually a mapping of names to XML documents.
 * Both are represented as strings.
 */
class ALPINO_CORPUS_EXPORT CorpusReader : private util::NonCopyable
{
  protected:
    // Iterator body. We need handle-body/proxy/pimpl for polymorphic copy.
    struct IterImpl {
        virtual ~IterImpl() {}
        virtual std::string current() const = 0;
        virtual bool equals(IterImpl const &) const = 0;
        virtual void next() = 0;

        // Query iterators must override this
        virtual std::string contents(CorpusReader const &rdr) const;
    };

  public:
    /** Forward iterator over entry names */
    class ALPINO_CORPUS_EXPORT EntryIterator
    : public std::iterator<std::input_iterator_tag, std::string, ptrdiff_t, std::string *, std::string>
    {
        std::tr1::shared_ptr<IterImpl> impl;

      public:
        EntryIterator() {}
        EntryIterator(IterImpl *p) : impl(p) { }
        EntryIterator(EntryIterator const &other) : impl(other.impl) { }
        virtual ~EntryIterator() {}
        EntryIterator &operator++();
        EntryIterator operator++(int);
        bool operator==(EntryIterator const &other) const;
        bool operator!=(EntryIterator const &other) const;
        value_type operator*() const;
        //value_type const *operator->() const { return impl->current(); }

        /**
         * Get contents of entry pointed to by iterator.
         * This will be a null string for an ordinary iterator,
         * and the matching part for a query iterator.
         */
        std::string contents(CorpusReader const &rdr) const;
    };

    struct MarkerQuery {
        MarkerQuery(std::string const &newQuery, std::string const &newAttr,
            std::string const &newValue) :
            query(newQuery), attr(newAttr), value(newValue) {}
        std::string query;
        std::string attr;
        std::string value;
    };

    virtual ~CorpusReader() {}

    /** Return canonical name of corpus */
    std::string name() const;

    /** Iterator to begin of entry names */
    EntryIterator begin() const;

    /** Iterator to end of entry names */
    EntryIterator end() const;

    enum QueryDialect { XPATH, XQUERY };

    /** Is a query valid? */
    bool isValidQuery(QueryDialect d, bool variables, std::string const &q) const;

    /** Execute query. The end of the range is given by end(). */
    EntryIterator query(QueryDialect d, std::string const &q) const;

    /** Return content of a single treebank entry. */
    std::string read(std::string const &entry) const;

    /**
     * Return content of a single treebank entry, marking matching elements using the
     * given attribute and value.
     */
    std::string readMarkQueries(std::string const &entry, std::list<MarkerQuery> const &queries) const;

    /** The number of entries in the corpus. */
    size_t size() const;

    /**
     * Factory method: open a corpus, determining its type automatically.
     * The caller is responsible for deleting the object returned.
     */
    static CorpusReader *open(std::string const &corpusPath);

    /**
     * Factory method: open a directory with multiple corpora recursively.
     * The caller is responsible for deleting the object returned.
     */
    static CorpusReader *openRecursive(std::string const &path);

  protected:
    class FilterIter : public IterImpl {
      public:
        FilterIter(CorpusReader const &, EntryIterator, EntryIterator, std::string const &);
        std::string current() const;
        bool equals(IterImpl const &) const;
        void next();
        std::string contents(CorpusReader const &) const;

      private:
        void parseFile(std::string const &);

        CorpusReader const &d_corpus;
        EntryIterator d_itr;
        EntryIterator d_end;
        std::string d_file;
        std::string d_query;
        std::queue<std::string> d_buffer;
    };

  private:
    virtual EntryIterator getBegin() const = 0;
    virtual EntryIterator getEnd() const = 0;
    virtual std::string getName() const = 0;
    virtual size_t getSize() const = 0;
    virtual std::string readEntry(std::string const &entry) const = 0;
    virtual std::string readEntryMarkQueries(std::string const &entry,
        std::list<MarkerQuery> const &queries) const;
    virtual EntryIterator runXPath(std::string const &) const;
    virtual EntryIterator runXQuery(std::string const &) const;
    virtual bool validQuery(QueryDialect d, bool variables, std::string const &q) const;
};

}

#endif  // ALPINO_CORPUSREADER_HH
<commit_msg>CorpusReader: cstddef require for ptrdiff_t.<commit_after>#ifndef ALPINO_CORPUSREADER_HH
#define ALPINO_CORPUSREADER_HH

#include <cstddef>
#include <list>
#include <queue>
#include <string>
#include <tr1/memory>

#include <AlpinoCorpus/DLLDefines.hh>
#include <AlpinoCorpus/util/NonCopyable.hh>

namespace alpinocorpus {

/**
 * Abstract base class for corpus readers.
 *
 * A corpus is conceptually a mapping of names to XML documents.
 * Both are represented as strings.
 */
class ALPINO_CORPUS_EXPORT CorpusReader : private util::NonCopyable
{
  protected:
    // Iterator body. We need handle-body/proxy/pimpl for polymorphic copy.
    struct IterImpl {
        virtual ~IterImpl() {}
        virtual std::string current() const = 0;
        virtual bool equals(IterImpl const &) const = 0;
        virtual void next() = 0;

        // Query iterators must override this
        virtual std::string contents(CorpusReader const &rdr) const;
    };

  public:
    /** Forward iterator over entry names */
    class ALPINO_CORPUS_EXPORT EntryIterator
    : public std::iterator<std::input_iterator_tag, std::string, ptrdiff_t, std::string *, std::string>
    {
        std::tr1::shared_ptr<IterImpl> impl;

      public:
        EntryIterator() {}
        EntryIterator(IterImpl *p) : impl(p) { }
        EntryIterator(EntryIterator const &other) : impl(other.impl) { }
        virtual ~EntryIterator() {}
        EntryIterator &operator++();
        EntryIterator operator++(int);
        bool operator==(EntryIterator const &other) const;
        bool operator!=(EntryIterator const &other) const;
        value_type operator*() const;
        //value_type const *operator->() const { return impl->current(); }

        /**
         * Get contents of entry pointed to by iterator.
         * This will be a null string for an ordinary iterator,
         * and the matching part for a query iterator.
         */
        std::string contents(CorpusReader const &rdr) const;
    };

    struct MarkerQuery {
        MarkerQuery(std::string const &newQuery, std::string const &newAttr,
            std::string const &newValue) :
            query(newQuery), attr(newAttr), value(newValue) {}
        std::string query;
        std::string attr;
        std::string value;
    };

    virtual ~CorpusReader() {}

    /** Return canonical name of corpus */
    std::string name() const;

    /** Iterator to begin of entry names */
    EntryIterator begin() const;

    /** Iterator to end of entry names */
    EntryIterator end() const;

    enum QueryDialect { XPATH, XQUERY };

    /** Is a query valid? */
    bool isValidQuery(QueryDialect d, bool variables, std::string const &q) const;

    /** Execute query. The end of the range is given by end(). */
    EntryIterator query(QueryDialect d, std::string const &q) const;

    /** Return content of a single treebank entry. */
    std::string read(std::string const &entry) const;

    /**
     * Return content of a single treebank entry, marking matching elements using the
     * given attribute and value.
     */
    std::string readMarkQueries(std::string const &entry, std::list<MarkerQuery> const &queries) const;

    /** The number of entries in the corpus. */
    size_t size() const;

    /**
     * Factory method: open a corpus, determining its type automatically.
     * The caller is responsible for deleting the object returned.
     */
    static CorpusReader *open(std::string const &corpusPath);

    /**
     * Factory method: open a directory with multiple corpora recursively.
     * The caller is responsible for deleting the object returned.
     */
    static CorpusReader *openRecursive(std::string const &path);

  protected:
    class FilterIter : public IterImpl {
      public:
        FilterIter(CorpusReader const &, EntryIterator, EntryIterator, std::string const &);
        std::string current() const;
        bool equals(IterImpl const &) const;
        void next();
        std::string contents(CorpusReader const &) const;

      private:
        void parseFile(std::string const &);

        CorpusReader const &d_corpus;
        EntryIterator d_itr;
        EntryIterator d_end;
        std::string d_file;
        std::string d_query;
        std::queue<std::string> d_buffer;
    };

  private:
    virtual EntryIterator getBegin() const = 0;
    virtual EntryIterator getEnd() const = 0;
    virtual std::string getName() const = 0;
    virtual size_t getSize() const = 0;
    virtual std::string readEntry(std::string const &entry) const = 0;
    virtual std::string readEntryMarkQueries(std::string const &entry,
        std::list<MarkerQuery> const &queries) const;
    virtual EntryIterator runXPath(std::string const &) const;
    virtual EntryIterator runXQuery(std::string const &) const;
    virtual bool validQuery(QueryDialect d, bool variables, std::string const &q) const;
};

}

#endif  // ALPINO_CORPUSREADER_HH
<|endoftext|>


<commit_before>/*
 * Copyright © 2008, 2009 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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.
 */
#include <getopt.h>

/** @file main.cpp
 *
 * This file is the main() routine and scaffolding for producing
 * builtin_compiler (which doesn't include builtins itself and is used
 * to generate the profile information for builtin_function.cpp), and
 * for glsl_compiler (which does include builtins and can be used to
 * offline compile GLSL code and examine the resulting GLSL IR.
 */

#include "ast.h"
#include "glsl_parser_extras.h"
#include "ir_optimization.h"
#include "program.h"
#include "loop_analysis.h"
#include "standalone_scaffolding.h"

static void
initialize_context(struct gl_context *ctx, gl_api api)
{
   initialize_context_to_defaults(ctx, api);

   /* The standalone compiler needs to claim support for almost
    * everything in order to compile the built-in functions.
    */
   ctx->Const.GLSLVersion = 330;
   ctx->Extensions.ARB_ES3_compatibility = true;

   ctx->Const.MaxClipPlanes = 8;
   ctx->Const.MaxDrawBuffers = 2;

   /* More than the 1.10 minimum to appease parser tests taken from
    * apps that (hopefully) already checked the number of coords.
    */
   ctx->Const.MaxTextureCoordUnits = 4;

   ctx->Driver.NewShader = _mesa_new_shader;
}

/* Returned string will have 'ctx' as its ralloc owner. */
static char *
load_text_file(void *ctx, const char *file_name)
{
	char *text = NULL;
	size_t size;
	size_t total_read = 0;
	FILE *fp = fopen(file_name, "rb");

	if (!fp) {
		return NULL;
	}

	fseek(fp, 0L, SEEK_END);
	size = ftell(fp);
	fseek(fp, 0L, SEEK_SET);

	text = (char *) ralloc_size(ctx, size + 1);
	if (text != NULL) {
		do {
			size_t bytes = fread(text + total_read,
					     1, size - total_read, fp);
			if (bytes < size - total_read) {
				free(text);
				text = NULL;
				break;
			}

			if (bytes == 0) {
				break;
			}

			total_read += bytes;
		} while (total_read < size);

		text[total_read] = '\0';
	}

	fclose(fp);

	return text;
}

int glsl_es = 0;
int dump_ast = 0;
int dump_hir = 0;
int dump_lir = 0;
int do_link = 0;

const struct option compiler_opts[] = {
   { "glsl-es",  0, &glsl_es,  1 },
   { "dump-ast", 0, &dump_ast, 1 },
   { "dump-hir", 0, &dump_hir, 1 },
   { "dump-lir", 0, &dump_lir, 1 },
   { "link",     0, &do_link,  1 },
   { NULL, 0, NULL, 0 }
};

/**
 * \brief Print proper usage and exit with failure.
 */
void
usage_fail(const char *name)
{

   const char *header =
      "usage: %s [options] <file.vert | file.geom | file.frag>\n"
      "\n"
      "Possible options are:\n";
   printf(header, name, name);
   for (const struct option *o = compiler_opts; o->name != 0; ++o) {
      printf("    --%s\n", o->name);
   }
   exit(EXIT_FAILURE);
}

void
compile_shader(struct gl_context *ctx, struct gl_shader *shader)
{
   struct _mesa_glsl_parse_state *state =
      new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);

   _mesa_glsl_compile_shader(ctx, shader, dump_ast, dump_hir);

   /* Print out the resulting IR */
   if (!state->error && dump_lir) {
      _mesa_print_ir(shader->ir, state);
   }

   return;
}

int
main(int argc, char **argv)
{
   int status = EXIT_SUCCESS;
   struct gl_context local_ctx;
   struct gl_context *ctx = &local_ctx;

   int c;
   int idx = 0;
   while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1)
      /* empty */ ;

   if (argc <= optind)
      usage_fail(argv[0]);

   initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL_COMPAT);

   struct gl_shader_program *whole_program;

   whole_program = rzalloc (NULL, struct gl_shader_program);
   assert(whole_program != NULL);
   whole_program->InfoLog = ralloc_strdup(whole_program, "");

   for (/* empty */; argc > optind; optind++) {
      whole_program->Shaders =
	 reralloc(whole_program, whole_program->Shaders,
		  struct gl_shader *, whole_program->NumShaders + 1);
      assert(whole_program->Shaders != NULL);

      struct gl_shader *shader = rzalloc(whole_program, gl_shader);

      whole_program->Shaders[whole_program->NumShaders] = shader;
      whole_program->NumShaders++;

      const unsigned len = strlen(argv[optind]);
      if (len < 6)
	 usage_fail(argv[0]);

      const char *const ext = & argv[optind][len - 5];
      if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0)
	 shader->Type = GL_VERTEX_SHADER;
      else if (strncmp(".geom", ext, 5) == 0)
	 shader->Type = GL_GEOMETRY_SHADER;
      else if (strncmp(".frag", ext, 5) == 0)
	 shader->Type = GL_FRAGMENT_SHADER;
      else
	 usage_fail(argv[0]);

      shader->Source = load_text_file(whole_program, argv[optind]);
      if (shader->Source == NULL) {
	 printf("File \"%s\" does not exist.\n", argv[optind]);
	 exit(EXIT_FAILURE);
      }

      compile_shader(ctx, shader);

      if (!shader->CompileStatus) {
	 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
	 status = EXIT_FAILURE;
	 break;
      }
   }

   if ((status == EXIT_SUCCESS) && do_link)  {
      link_shaders(ctx, whole_program);
      status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;

      if (strlen(whole_program->InfoLog) > 0)
	 printf("Info log for linking:\n%s\n", whole_program->InfoLog);
   }

   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
      ralloc_free(whole_program->_LinkedShaders[i]);

   ralloc_free(whole_program);
   _mesa_glsl_release_types();
   _mesa_glsl_release_builtin_functions();

   return status;
}
<commit_msg>glsl_compiler: Use no_argument instead of 0 in getopt_long options<commit_after>/*
 * Copyright © 2008, 2009 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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.
 */
#include <getopt.h>

/** @file main.cpp
 *
 * This file is the main() routine and scaffolding for producing
 * builtin_compiler (which doesn't include builtins itself and is used
 * to generate the profile information for builtin_function.cpp), and
 * for glsl_compiler (which does include builtins and can be used to
 * offline compile GLSL code and examine the resulting GLSL IR.
 */

#include "ast.h"
#include "glsl_parser_extras.h"
#include "ir_optimization.h"
#include "program.h"
#include "loop_analysis.h"
#include "standalone_scaffolding.h"

static void
initialize_context(struct gl_context *ctx, gl_api api)
{
   initialize_context_to_defaults(ctx, api);

   /* The standalone compiler needs to claim support for almost
    * everything in order to compile the built-in functions.
    */
   ctx->Const.GLSLVersion = 330;
   ctx->Extensions.ARB_ES3_compatibility = true;

   ctx->Const.MaxClipPlanes = 8;
   ctx->Const.MaxDrawBuffers = 2;

   /* More than the 1.10 minimum to appease parser tests taken from
    * apps that (hopefully) already checked the number of coords.
    */
   ctx->Const.MaxTextureCoordUnits = 4;

   ctx->Driver.NewShader = _mesa_new_shader;
}

/* Returned string will have 'ctx' as its ralloc owner. */
static char *
load_text_file(void *ctx, const char *file_name)
{
	char *text = NULL;
	size_t size;
	size_t total_read = 0;
	FILE *fp = fopen(file_name, "rb");

	if (!fp) {
		return NULL;
	}

	fseek(fp, 0L, SEEK_END);
	size = ftell(fp);
	fseek(fp, 0L, SEEK_SET);

	text = (char *) ralloc_size(ctx, size + 1);
	if (text != NULL) {
		do {
			size_t bytes = fread(text + total_read,
					     1, size - total_read, fp);
			if (bytes < size - total_read) {
				free(text);
				text = NULL;
				break;
			}

			if (bytes == 0) {
				break;
			}

			total_read += bytes;
		} while (total_read < size);

		text[total_read] = '\0';
	}

	fclose(fp);

	return text;
}

int glsl_es = 0;
int dump_ast = 0;
int dump_hir = 0;
int dump_lir = 0;
int do_link = 0;

const struct option compiler_opts[] = {
   { "glsl-es",  no_argument, &glsl_es,  1 },
   { "dump-ast", no_argument, &dump_ast, 1 },
   { "dump-hir", no_argument, &dump_hir, 1 },
   { "dump-lir", no_argument, &dump_lir, 1 },
   { "link",     no_argument, &do_link,  1 },
   { NULL, 0, NULL, 0 }
};

/**
 * \brief Print proper usage and exit with failure.
 */
void
usage_fail(const char *name)
{

   const char *header =
      "usage: %s [options] <file.vert | file.geom | file.frag>\n"
      "\n"
      "Possible options are:\n";
   printf(header, name, name);
   for (const struct option *o = compiler_opts; o->name != 0; ++o) {
      printf("    --%s\n", o->name);
   }
   exit(EXIT_FAILURE);
}

void
compile_shader(struct gl_context *ctx, struct gl_shader *shader)
{
   struct _mesa_glsl_parse_state *state =
      new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);

   _mesa_glsl_compile_shader(ctx, shader, dump_ast, dump_hir);

   /* Print out the resulting IR */
   if (!state->error && dump_lir) {
      _mesa_print_ir(shader->ir, state);
   }

   return;
}

int
main(int argc, char **argv)
{
   int status = EXIT_SUCCESS;
   struct gl_context local_ctx;
   struct gl_context *ctx = &local_ctx;

   int c;
   int idx = 0;
   while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1)
      /* empty */ ;

   if (argc <= optind)
      usage_fail(argv[0]);

   initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL_COMPAT);

   struct gl_shader_program *whole_program;

   whole_program = rzalloc (NULL, struct gl_shader_program);
   assert(whole_program != NULL);
   whole_program->InfoLog = ralloc_strdup(whole_program, "");

   for (/* empty */; argc > optind; optind++) {
      whole_program->Shaders =
	 reralloc(whole_program, whole_program->Shaders,
		  struct gl_shader *, whole_program->NumShaders + 1);
      assert(whole_program->Shaders != NULL);

      struct gl_shader *shader = rzalloc(whole_program, gl_shader);

      whole_program->Shaders[whole_program->NumShaders] = shader;
      whole_program->NumShaders++;

      const unsigned len = strlen(argv[optind]);
      if (len < 6)
	 usage_fail(argv[0]);

      const char *const ext = & argv[optind][len - 5];
      if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0)
	 shader->Type = GL_VERTEX_SHADER;
      else if (strncmp(".geom", ext, 5) == 0)
	 shader->Type = GL_GEOMETRY_SHADER;
      else if (strncmp(".frag", ext, 5) == 0)
	 shader->Type = GL_FRAGMENT_SHADER;
      else
	 usage_fail(argv[0]);

      shader->Source = load_text_file(whole_program, argv[optind]);
      if (shader->Source == NULL) {
	 printf("File \"%s\" does not exist.\n", argv[optind]);
	 exit(EXIT_FAILURE);
      }

      compile_shader(ctx, shader);

      if (!shader->CompileStatus) {
	 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
	 status = EXIT_FAILURE;
	 break;
      }
   }

   if ((status == EXIT_SUCCESS) && do_link)  {
      link_shaders(ctx, whole_program);
      status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;

      if (strlen(whole_program->InfoLog) > 0)
	 printf("Info log for linking:\n%s\n", whole_program->InfoLog);
   }

   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
      ralloc_free(whole_program->_LinkedShaders[i]);

   ralloc_free(whole_program);
   _mesa_glsl_release_types();
   _mesa_glsl_release_builtin_functions();

   return status;
}
<|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/utilities/CCopasiMessage.cpp,v $
   $Revision: 1.22 $
   $Name:  $
   $Author: shoops $
   $Date: 2005/04/14 15:22:24 $
   End CVS Header */

// CCopasiMessage
//
// New Class based on pmutils read functionality
// (C) Stefan Hoops 2001

#include <string>
#include <iostream>

#include <time.h>
#include <stdio.h>
#include <stdarg.h>

#define  COPASI_TRACE_CONSTRUCTION

#include "copasi.h"
#include "CCopasiMessage.h"
#include "messages.h"
#include "CCopasiException.h"

std::string TimeStamp();
#define INITIALTEXTSIZE 1024

std::deque< CCopasiMessage > CCopasiMessage::mMessageDeque;

const CCopasiMessage & CCopasiMessage::peekFirstMessage()
{
  if (mMessageDeque.empty())
    CCopasiMessage(CCopasiMessage::RAW,
                   MCCopasiMessage + 1);

  return mMessageDeque.front();
}

const CCopasiMessage & CCopasiMessage::peekLastMessage()
{
  if (mMessageDeque.empty())
    CCopasiMessage(CCopasiMessage::RAW,
                   MCCopasiMessage + 1);

  return mMessageDeque.back();
}

CCopasiMessage CCopasiMessage::getFirstMessage()
{
  if (mMessageDeque.empty())
    CCopasiMessage(CCopasiMessage::RAW,
                   MCCopasiMessage + 1);

  CCopasiMessage Message(mMessageDeque.front());
  mMessageDeque.pop_front();

  return Message;
}

CCopasiMessage CCopasiMessage::getLastMessage()
{
  if (mMessageDeque.empty())
    CCopasiMessage(CCopasiMessage::RAW,
                   MCCopasiMessage + 1);

  CCopasiMessage Message(mMessageDeque.back());
  mMessageDeque.pop_back();

  return Message;
}

std::string CCopasiMessage::getAllMessageText(const bool & chronological)
{
  std::string Text = "";
  CCopasiMessage (*getMessage)() = chronological ? getFirstMessage : getLastMessage;

  while (!mMessageDeque.empty())
    {
      if (Text != "") Text += "\n";
      Text += getMessage().getText();
    }

  return Text;
}

void CCopasiMessage::clearDeque()
{
  mMessageDeque.clear();

  return;
}

CCopasiMessage::CCopasiMessage(void):
    mText(),
    mType(CCopasiMessage::RAW),
    mNumber(0)
{}

CCopasiMessage::CCopasiMessage(const CCopasiMessage & src):
    mText(src.mText),
    mType(src.mType),
    mNumber(src.mNumber)
{}

CCopasiMessage::CCopasiMessage(CCopasiMessage::Type type,
                               const char *format, ...)
{
  C_INT32 TextSize = INITIALTEXTSIZE;
  C_INT32 Printed = 0;

  va_list Arguments; // = NULL;
  va_start(Arguments, format);

  char *Text = NULL;
  Text = new char[TextSize + 1];

  Printed = vsnprintf(Text, TextSize + 1, format, Arguments);

  while (Printed < 0 || TextSize < Printed)
    {
      delete [] Text;

      (Printed < 0) ? TextSize *= 2 : TextSize = Printed;
      Text = new char[TextSize + 1];

      Printed = vsnprintf(Text, TextSize, format, Arguments);
    }

  mText = Text;
  mType = type;
  mNumber = 0;

  va_end(Arguments);

  handler();
}

CCopasiMessage::CCopasiMessage(CCopasiMessage::Type type,
                               unsigned C_INT32 number, ...)
{
  C_INT32 i = 0;

  C_INT32 TextSize = INITIALTEXTSIZE;
  C_INT32 Printed = 0;

  while (Messages[i].No != number && Messages[i].Text)
    i++;

  if (!Messages[i].Text)
    fatalError();

  va_list Arguments; // = NULL;
  va_start(Arguments, number);

  char *Text = NULL;
  Text = new char[TextSize + 1];

  Printed = vsnprintf(Text, TextSize, Messages[i].Text, Arguments);

  while (Printed < 0 || TextSize < Printed)
    {
      delete [] Text;

      (Printed < 0) ? TextSize *= 2 : TextSize = Printed;
      Text = new char[TextSize + 1];

      Printed = vsnprintf(Text, TextSize, Messages[i].Text, Arguments);
    }

  mText = Text;
  mType = type;
  mNumber = number;

  va_end(Arguments);

  handler();
}

void CCopasiMessage::handler(const bool & _throw)
{
  std::string Text = mText;

  switch (mType)
    {
    case RAW:
      mText = "";
      break;

    case TRACE:
      mText = ">TRACE ";
      mText += TimeStamp();
      mText += "<\n";
      break;

    case WARNING:
      mText = ">WARNING ";
      mText += TimeStamp();
      mText += "<\n";
      break;

    case ERROR:
      mText = ">ERROR ";
      mText += TimeStamp();
      mText += "<\n";
      break;

    case EXCEPTION:
      mText = ">EXCEPTION ";
      mText += TimeStamp();
      mText += "<\n";
      break;
    }

  mText += Text;

  if (mType != RAW) lineBreak();

  mMessageDeque.push_back(*this);

  if (mType == EXCEPTION)
    {
#ifdef COPASI_DEBUG
      DebugFile << mText << std::endl;
#endif // COPASI_DEBUG

      throw CCopasiException(*this);
    }
  else
    {
      std::cout << mText << std::endl;
    }
}

// overload assignment operator
CCopasiMessage &CCopasiMessage::operator=(const CCopasiMessage &RHS)
{
  mText = RHS.mText;
  mType = RHS.mType;
  mNumber = RHS.mNumber;

  return *this;
}
CCopasiMessage::~CCopasiMessage(void) {}
const std::string & CCopasiMessage::getText(void) const {return mText;}
const CCopasiMessage::Type & CCopasiMessage::getType(void) const {return mType;}
const unsigned C_INT32 & CCopasiMessage::getNumber(void) const {return mNumber;}

std::string TimeStamp()
{
  time_t Time;
  tm *sTime = NULL;
  char str[20];

  time(&Time);
  sTime = localtime(&Time);

  if (sTime)
    {
      sprintf(str, "%d-%.02d-%.02d %.02d:%.02d:%.02d",
              sTime->tm_year + 1900,
              sTime->tm_mon + 1,
              sTime->tm_mday,
              sTime->tm_hour,
              sTime->tm_min,
              sTime->tm_sec);
    }
  else
    {
      sprintf(str, "0000-00-00 00:00:00");
    }

  return (std::string) str;
}

void CCopasiMessage::lineBreak()
{
  std::string Search("\n");
  std::string Replace("\n  ");
  std::string::size_type pos = 0;

  while (true)
    {
      pos = mText.find(Search, pos);

      if (pos == std::string::npos)
        break;

      mText.replace(pos, Search.length(), Replace);

      pos += Replace.length();
    }
}
<commit_msg>Replaced local function TimeStamp with LocalTimeStamp provided by utility.cpp.<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/utilities/CCopasiMessage.cpp,v $
   $Revision: 1.23 $
   $Name:  $
   $Author: shoops $
   $Date: 2005/07/15 20:22:35 $
   End CVS Header */

// CCopasiMessage
//
// New Class based on pmutils read functionality
// (C) Stefan Hoops 2001

#include <string>
#include <iostream>

#include <time.h>
#include <stdio.h>
#include <stdarg.h>

#define  COPASI_TRACE_CONSTRUCTION

#include "copasi.h"
#include "CCopasiMessage.h"
#include "messages.h"
#include "CCopasiException.h"
#include "utility.h"

#define INITIALTEXTSIZE 1024

std::deque< CCopasiMessage > CCopasiMessage::mMessageDeque;

const CCopasiMessage & CCopasiMessage::peekFirstMessage()
{
  if (mMessageDeque.empty())
    CCopasiMessage(CCopasiMessage::RAW,
                   MCCopasiMessage + 1);

  return mMessageDeque.front();
}

const CCopasiMessage & CCopasiMessage::peekLastMessage()
{
  if (mMessageDeque.empty())
    CCopasiMessage(CCopasiMessage::RAW,
                   MCCopasiMessage + 1);

  return mMessageDeque.back();
}

CCopasiMessage CCopasiMessage::getFirstMessage()
{
  if (mMessageDeque.empty())
    CCopasiMessage(CCopasiMessage::RAW,
                   MCCopasiMessage + 1);

  CCopasiMessage Message(mMessageDeque.front());
  mMessageDeque.pop_front();

  return Message;
}

CCopasiMessage CCopasiMessage::getLastMessage()
{
  if (mMessageDeque.empty())
    CCopasiMessage(CCopasiMessage::RAW,
                   MCCopasiMessage + 1);

  CCopasiMessage Message(mMessageDeque.back());
  mMessageDeque.pop_back();

  return Message;
}

std::string CCopasiMessage::getAllMessageText(const bool & chronological)
{
  std::string Text = "";
  CCopasiMessage (*getMessage)() = chronological ? getFirstMessage : getLastMessage;

  while (!mMessageDeque.empty())
    {
      if (Text != "") Text += "\n";
      Text += getMessage().getText();
    }

  return Text;
}

void CCopasiMessage::clearDeque()
{
  mMessageDeque.clear();

  return;
}

CCopasiMessage::CCopasiMessage(void):
    mText(),
    mType(CCopasiMessage::RAW),
    mNumber(0)
{}

CCopasiMessage::CCopasiMessage(const CCopasiMessage & src):
    mText(src.mText),
    mType(src.mType),
    mNumber(src.mNumber)
{}

CCopasiMessage::CCopasiMessage(CCopasiMessage::Type type,
                               const char *format, ...)
{
  C_INT32 TextSize = INITIALTEXTSIZE;
  C_INT32 Printed = 0;

  va_list Arguments; // = NULL;
  va_start(Arguments, format);

  char *Text = NULL;
  Text = new char[TextSize + 1];

  Printed = vsnprintf(Text, TextSize + 1, format, Arguments);

  while (Printed < 0 || TextSize < Printed)
    {
      delete [] Text;

      (Printed < 0) ? TextSize *= 2 : TextSize = Printed;
      Text = new char[TextSize + 1];

      Printed = vsnprintf(Text, TextSize, format, Arguments);
    }

  mText = Text;
  mType = type;
  mNumber = 0;

  va_end(Arguments);

  handler();
}

CCopasiMessage::CCopasiMessage(CCopasiMessage::Type type,
                               unsigned C_INT32 number, ...)
{
  C_INT32 i = 0;

  C_INT32 TextSize = INITIALTEXTSIZE;
  C_INT32 Printed = 0;

  while (Messages[i].No != number && Messages[i].Text)
    i++;

  if (!Messages[i].Text)
    fatalError();

  va_list Arguments; // = NULL;
  va_start(Arguments, number);

  char *Text = NULL;
  Text = new char[TextSize + 1];

  Printed = vsnprintf(Text, TextSize, Messages[i].Text, Arguments);

  while (Printed < 0 || TextSize < Printed)
    {
      delete [] Text;

      (Printed < 0) ? TextSize *= 2 : TextSize = Printed;
      Text = new char[TextSize + 1];

      Printed = vsnprintf(Text, TextSize, Messages[i].Text, Arguments);
    }

  mText = Text;
  mType = type;
  mNumber = number;

  va_end(Arguments);

  handler();
}

void CCopasiMessage::handler(const bool & _throw)
{
  std::string Text = mText;

  switch (mType)
    {
    case RAW:
      mText = "";
      break;

    case TRACE:
      mText = ">TRACE ";
      mText += LocalTimeStamp();
      mText += "<\n";
      break;

    case WARNING:
      mText = ">WARNING ";
      mText += LocalTimeStamp();
      mText += "<\n";
      break;

    case ERROR:
      mText = ">ERROR ";
      mText += LocalTimeStamp();
      mText += "<\n";
      break;

    case EXCEPTION:
      mText = ">EXCEPTION ";
      mText += LocalTimeStamp();
      mText += "<\n";
      break;
    }

  mText += Text;

  if (mType != RAW) lineBreak();

  mMessageDeque.push_back(*this);

  if (mType == EXCEPTION)
    {
#ifdef COPASI_DEBUG
      DebugFile << mText << std::endl;
#endif // COPASI_DEBUG

      throw CCopasiException(*this);
    }
  else
    {
      std::cout << mText << std::endl;
    }
}

// overload assignment operator
CCopasiMessage &CCopasiMessage::operator=(const CCopasiMessage &RHS)
{
  mText = RHS.mText;
  mType = RHS.mType;
  mNumber = RHS.mNumber;

  return *this;
}
CCopasiMessage::~CCopasiMessage(void) {}
const std::string & CCopasiMessage::getText(void) const {return mText;}
const CCopasiMessage::Type & CCopasiMessage::getType(void) const {return mType;}
const unsigned C_INT32 & CCopasiMessage::getNumber(void) const {return mNumber;}

void CCopasiMessage::lineBreak()
{
  std::string Search("\n");
  std::string Replace("\n  ");
  std::string::size_type pos = 0;

  while (true)
    {
      pos = mText.find(Search, pos);

      if (pos == std::string::npos)
        break;

      mText.replace(pos, Search.length(), Replace);

      pos += Replace.length();
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005 Tommi Maekitalo
 *
 * 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.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <tntdb/postgresql/impl/statement.h>
#include <tntdb/postgresql/impl/connection.h>
#include <tntdb/postgresql/impl/result.h>
#include <tntdb/postgresql/impl/cursor.h>
#include <tntdb/postgresql/error.h>
#include <tntdb/bits/result.h>
#include <tntdb/bits/row.h>
#include <tntdb/bits/value.h>
#include <tntdb/stmtparser.h>
#include <sstream>
#include <cxxtools/log.h>
#include "config.h"

log_define("tntdb.postgresql.statement")

#ifdef HAVE_PQPREPARE
#  define SET_TYPE(pos, type)
#else
#  define SET_TYPE(pos, type)  setType(pos, type)
#endif

namespace tntdb
{
  namespace postgresql
  {
    typedef std::map<std::string, unsigned> hostvarMapType;

    namespace
    {
      class SE : public StmtEvent
      {
          hostvarMapType& hostvarMap;
          unsigned idx;

        public:
          SE(hostvarMapType& hm)
            : hostvarMap(hm),
              idx(0)
            { }
          std::string onHostVar(const std::string& name);
          unsigned getMaxIdx() const  { return idx; }
      };

      std::string SE::onHostVar(const std::string& name)
      {
        unsigned n;

        hostvarMapType::const_iterator it = hostvarMap.find(name);
        if (it == hostvarMap.end())
        {
          n = idx++;
          hostvarMap[name] = n;
        }
        else
          n = it->second;

        log_debug("hostvar :" << name << " => $" << (n + 1));

        std::ostringstream r;
        r << '$' << (n + 1);
        return r.str();
      }
    }

    Statement::Statement(Connection* conn_, const std::string& query_)
      : conn(conn_)
    {
      // parse hostvars
      StmtParser parser;
      SE se(hostvarMap);
      parser.parse(query_, se);

      values.resize(se.getMaxIdx());

      query = parser.getSql();

      paramValues.resize(se.getMaxIdx());
      paramLengths.resize(se.getMaxIdx());
      paramFormats.resize(se.getMaxIdx());
    }

    Statement::~Statement()
    {
      if (!stmtName.empty())
      {
        std::string sql = "DEALLOCATE " + stmtName;

        log_debug("PQexec(" << getPGConn() << ", \"" << sql << "\")");
        PGresult* result = PQexec(getPGConn(), sql.c_str());

        if (isError(result))
          log_error("error deallocating statement: " << PQresultErrorMessage(result));

        log_debug("PQclear(" << result << ')');
        PQclear(result);
      }
    }

    void Statement::doPrepare()
    {
      // create statementname
      std::ostringstream s;
      s << "tntdbstmt" << this;

      // prepare statement
#ifdef HAVE_PQPREPARE
      log_debug("PQprepare(" << getPGConn() << ", \"" << s.str()
        << "\", \"" << query << "\", 0, 0)");
      PGresult* result = PQprepare(getPGConn(),
        s.str().c_str(), query.c_str(), 0, 0);

      if (isError(result))
      {
        log_error(PQresultErrorMessage(result));
        throw PgSqlError(query, "PQprepare", result, true);
      }
#else
      std::ostringstream sql;
      sql << "PREPARE " << s.str();
      for (valuesType::const_iterator it = values.begin(); it != values.end(); ++it)
        sql << (it == values.begin() ? " (" : ", " ) << it->getType();
      if (!values.empty())
        sql << ')';
      sql << " AS " << query;

      log_debug("PQexec(" << getPGConn() << ", \"" << sql.str() << "\")");
      PGresult* result = PQexec(getPGConn(), sql.str().c_str());

      if (isError(result))
      {
        log_error(PQresultErrorMessage(result));
        throw PgSqlError(sql.str(), "PQexec", result, true);
      }
#endif

      stmtName = s.str();

      log_debug("PQclear(" << result << ')');
      PQclear(result);
    }

    PGresult* Statement::execPrepared()
    {
      if (stmtName.empty())
        doPrepare();

      log_debug("PQexecPrepared(" << getPGConn() << ", \"" << stmtName
        << "\", " << values.size() << ", paramValues, paramLengths, paramFormats, 0)");
      PGresult* result = PQexecPrepared(getPGConn(), stmtName.c_str(),
        getNParams(), getParamValues(), getParamLengths(), getParamFormats(), 0);

      if (isError(result))
      {
        log_error(PQresultErrorMessage(result));
        throw PgSqlError(query, "PQexecPrepared", result, true);
      }

      return result;
    }

    template <typename T>
    void Statement::setValue(const std::string& col, T data)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        std::ostringstream v;
        v << data;
        values[it->second].setValue(v.str());
        paramFormats[it->second] = 0;
      }
    }

    template <>
    void Statement::setValue(const std::string& col, float data)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        std::ostringstream v;
        v.precision(24);
        v << data;
        values[it->second].setValue(v.str());
        paramFormats[it->second] = 0;
      }
    }

    template <>
    void Statement::setValue(const std::string& col, double data)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        std::ostringstream v;
        v.precision(24);
        v << data;
        values[it->second].setValue(v.str());
        paramFormats[it->second] = 0;
      }
    }

    template <>
    void Statement::setValue(const std::string& col, Decimal data)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        std::ostringstream v;
        v.precision(24);
        v << data;
        values[it->second].setValue(v.str());
        paramFormats[it->second] = 0;
      }
    }

    template <typename T>
    void Statement::setStringValue(const std::string& col, T data, bool binary)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        values[it->second].setValue(data);
        paramFormats[it->second] = binary;
      }
    }

    template <typename T>
    void Statement::setIsoValue(const std::string& col, T data)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        values[it->second].setValue(data.getIso());
        paramFormats[it->second] = 0;
      }
    }

#ifndef HAVE_PQPREPARE
    void Statement::setType(const std::string& col, const std::string& type)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it != hostvarMap.end())
        values[it->second].setType(type);
    }
#endif

    void Statement::clear()
    {
      log_debug("clear()");
      for (valuesType::iterator it = values.begin(); it != values.end(); ++it)
        it->setNull();
    }

    void Statement::setNull(const std::string& col)
    {
      log_debug("setNull(\"" << col << "\")");

      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        values[it->second].setNull();
        paramFormats[it->second] = 0;
      }
    }

    void Statement::setBool(const std::string& col, bool data)
    {
      log_debug("setBool(\"" << col << "\", " << data << ')');

      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        values[it->second].setValue(data ? "T" : "F");
        paramFormats[it->second] = 0;
      }

      SET_TYPE(col, "bool");
    }

    void Statement::setInt(const std::string& col, int data)
    {
      log_debug("setInt(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "int");
    }

    void Statement::setLong(const std::string& col, long data)
    {
      log_debug("setLong(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "long");
    }

    void Statement::setUnsigned(const std::string& col, unsigned data)
    {
      log_debug("setUnsigned(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "unsigned");
    }

    void Statement::setUnsignedLong(const std::string& col, unsigned long data)
    {
      log_debug("setUnsignedLong(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "unsigned long");
    }

    void Statement::setInt32(const std::string& col, int32_t data)
    {
      log_debug("setInt32(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "int");
    }

    void Statement::setUnsigned32(const std::string& col, uint32_t data)
    {
      log_debug("setUnsigned32(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "int");
    }

    void Statement::setInt64(const std::string& col, int64_t data)
    {
      log_debug("setInt64(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "bigint");
    }

    void Statement::setUnsigned64(const std::string& col, uint64_t data)
    {
      log_debug("setUnsigned64(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "bigint");
    }

    void Statement::setDecimal(const std::string& col, const Decimal& data)
    {
      log_debug("setDecimal(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "numeric");
    }

    void Statement::setFloat(const std::string& col, float data)
    {
      log_debug("setFloat(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "numeric");
    }

    void Statement::setDouble(const std::string& col, double data)
    {
      log_debug("setDouble(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "numeric");
    }

    void Statement::setChar(const std::string& col, char data)
    {
      log_debug("setChar(\"" << col << "\", '" << data << "')");
      setStringValue(col, std::string(1, data));
      SET_TYPE(col, "text");
    }

    void Statement::setString(const std::string& col, const std::string& data)
    {
      log_debug("setString(\"" << col << "\", \"" << data << "\")");
      setStringValue(col, data);
      SET_TYPE(col, "text");
    }

    void Statement::setBlob(const std::string& col, const Blob& data)
    {
      log_debug("setBlob(\"" << col << "\", Blob)");
      setStringValue(col, std::string(data.data(), data.size()), true);
      SET_TYPE(col, "blob");
    }

    void Statement::setDate(const std::string& col, const Date& data)
    {
      log_debug("setDate(\"" << col << "\", " << data.getIso() << ')');
      setIsoValue(col, data);
      SET_TYPE(col, "date");
    }

    void Statement::setTime(const std::string& col, const Time& data)
    {
      log_debug("setTime(\"" << col << "\", " << data.getIso() << ')');
      setIsoValue(col, data);
      SET_TYPE(col, "time");
    }

    void Statement::setDatetime(const std::string& col, const Datetime& data)
    {
      log_debug("setDatetime(\"" << col << "\", " << data.getIso() << ')');
      setIsoValue(col, data);
      SET_TYPE(col, "datetime");
    }

    Statement::size_type Statement::execute()
    {
      log_debug("execute()");

      PGresult* result = execPrepared();

      std::istringstream tuples(PQcmdTuples(result));
      unsigned ret = 0;
      tuples >> ret;

      log_debug("PQclear(" << result << ')');
      PQclear(result);

      return ret;
    }

    tntdb::Result Statement::select()
    {
      log_debug("select()");
      PGresult* result = execPrepared();
      return tntdb::Result(new Result(tntdb::Connection(conn), result));
    }

    tntdb::Row Statement::selectRow()
    {
      tntdb::Result result = select();

      if (result.size() <= 0)
        throw NotFound();

      return result[0];
    }

    tntdb::Value Statement::selectValue()
    {
      tntdb::Result result = select();

      if (result.size() <= 0)
        throw NotFound();

      return result[0][0];
    }

    ICursor* Statement::createCursor(unsigned fetchsize)
    {
      return new Cursor(this, fetchsize);
    }

    const char* const* Statement::getParamValues()
    {
      for (unsigned n = 0; n < values.size(); ++n)
        paramValues[n] = values[n].getValue();
      return &paramValues[0];
    }

    const int* Statement::getParamLengths()
    {
      for (unsigned n = 0; n < values.size(); ++n)
        paramLengths[n] = values[n].getLength();
      return &paramLengths[0];
    }

    PGconn* Statement::getPGConn()
    {
      return conn->getPGConn();
    }
  }
}
<commit_msg>insert boolean value as 0 or 1 in postgresql driver<commit_after>/*
 * Copyright (C) 2005 Tommi Maekitalo
 *
 * 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.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <tntdb/postgresql/impl/statement.h>
#include <tntdb/postgresql/impl/connection.h>
#include <tntdb/postgresql/impl/result.h>
#include <tntdb/postgresql/impl/cursor.h>
#include <tntdb/postgresql/error.h>
#include <tntdb/bits/result.h>
#include <tntdb/bits/row.h>
#include <tntdb/bits/value.h>
#include <tntdb/stmtparser.h>
#include <sstream>
#include <cxxtools/log.h>
#include "config.h"

log_define("tntdb.postgresql.statement")

#ifdef HAVE_PQPREPARE
#  define SET_TYPE(pos, type)
#else
#  define SET_TYPE(pos, type)  setType(pos, type)
#endif

namespace tntdb
{
  namespace postgresql
  {
    typedef std::map<std::string, unsigned> hostvarMapType;

    namespace
    {
      class SE : public StmtEvent
      {
          hostvarMapType& hostvarMap;
          unsigned idx;

        public:
          SE(hostvarMapType& hm)
            : hostvarMap(hm),
              idx(0)
            { }
          std::string onHostVar(const std::string& name);
          unsigned getMaxIdx() const  { return idx; }
      };

      std::string SE::onHostVar(const std::string& name)
      {
        unsigned n;

        hostvarMapType::const_iterator it = hostvarMap.find(name);
        if (it == hostvarMap.end())
        {
          n = idx++;
          hostvarMap[name] = n;
        }
        else
          n = it->second;

        log_debug("hostvar :" << name << " => $" << (n + 1));

        std::ostringstream r;
        r << '$' << (n + 1);
        return r.str();
      }
    }

    Statement::Statement(Connection* conn_, const std::string& query_)
      : conn(conn_)
    {
      // parse hostvars
      StmtParser parser;
      SE se(hostvarMap);
      parser.parse(query_, se);

      values.resize(se.getMaxIdx());

      query = parser.getSql();

      paramValues.resize(se.getMaxIdx());
      paramLengths.resize(se.getMaxIdx());
      paramFormats.resize(se.getMaxIdx());
    }

    Statement::~Statement()
    {
      if (!stmtName.empty())
      {
        std::string sql = "DEALLOCATE " + stmtName;

        log_debug("PQexec(" << getPGConn() << ", \"" << sql << "\")");
        PGresult* result = PQexec(getPGConn(), sql.c_str());

        if (isError(result))
          log_error("error deallocating statement: " << PQresultErrorMessage(result));

        log_debug("PQclear(" << result << ')');
        PQclear(result);
      }
    }

    void Statement::doPrepare()
    {
      // create statementname
      std::ostringstream s;
      s << "tntdbstmt" << this;

      // prepare statement
#ifdef HAVE_PQPREPARE
      log_debug("PQprepare(" << getPGConn() << ", \"" << s.str()
        << "\", \"" << query << "\", 0, 0)");
      PGresult* result = PQprepare(getPGConn(),
        s.str().c_str(), query.c_str(), 0, 0);

      if (isError(result))
      {
        log_error(PQresultErrorMessage(result));
        throw PgSqlError(query, "PQprepare", result, true);
      }
#else
      std::ostringstream sql;
      sql << "PREPARE " << s.str();
      for (valuesType::const_iterator it = values.begin(); it != values.end(); ++it)
        sql << (it == values.begin() ? " (" : ", " ) << it->getType();
      if (!values.empty())
        sql << ')';
      sql << " AS " << query;

      log_debug("PQexec(" << getPGConn() << ", \"" << sql.str() << "\")");
      PGresult* result = PQexec(getPGConn(), sql.str().c_str());

      if (isError(result))
      {
        log_error(PQresultErrorMessage(result));
        throw PgSqlError(sql.str(), "PQexec", result, true);
      }
#endif

      stmtName = s.str();

      log_debug("PQclear(" << result << ')');
      PQclear(result);
    }

    PGresult* Statement::execPrepared()
    {
      if (stmtName.empty())
        doPrepare();

      log_debug("PQexecPrepared(" << getPGConn() << ", \"" << stmtName
        << "\", " << values.size() << ", paramValues, paramLengths, paramFormats, 0)");
      PGresult* result = PQexecPrepared(getPGConn(), stmtName.c_str(),
        getNParams(), getParamValues(), getParamLengths(), getParamFormats(), 0);

      if (isError(result))
      {
        log_error(PQresultErrorMessage(result));
        throw PgSqlError(query, "PQexecPrepared", result, true);
      }

      return result;
    }

    template <typename T>
    void Statement::setValue(const std::string& col, T data)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        std::ostringstream v;
        v << data;
        values[it->second].setValue(v.str());
        paramFormats[it->second] = 0;
      }
    }

    template <>
    void Statement::setValue(const std::string& col, float data)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        std::ostringstream v;
        v.precision(24);
        v << data;
        values[it->second].setValue(v.str());
        paramFormats[it->second] = 0;
      }
    }

    template <>
    void Statement::setValue(const std::string& col, double data)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        std::ostringstream v;
        v.precision(24);
        v << data;
        values[it->second].setValue(v.str());
        paramFormats[it->second] = 0;
      }
    }

    template <>
    void Statement::setValue(const std::string& col, Decimal data)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        std::ostringstream v;
        v.precision(24);
        v << data;
        values[it->second].setValue(v.str());
        paramFormats[it->second] = 0;
      }
    }

    template <typename T>
    void Statement::setStringValue(const std::string& col, T data, bool binary)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        values[it->second].setValue(data);
        paramFormats[it->second] = binary;
      }
    }

    template <typename T>
    void Statement::setIsoValue(const std::string& col, T data)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        values[it->second].setValue(data.getIso());
        paramFormats[it->second] = 0;
      }
    }

#ifndef HAVE_PQPREPARE
    void Statement::setType(const std::string& col, const std::string& type)
    {
      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it != hostvarMap.end())
        values[it->second].setType(type);
    }
#endif

    void Statement::clear()
    {
      log_debug("clear()");
      for (valuesType::iterator it = values.begin(); it != values.end(); ++it)
        it->setNull();
    }

    void Statement::setNull(const std::string& col)
    {
      log_debug("setNull(\"" << col << "\")");

      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        values[it->second].setNull();
        paramFormats[it->second] = 0;
      }
    }

    void Statement::setBool(const std::string& col, bool data)
    {
      log_debug("setBool(\"" << col << "\", " << data << ')');

      hostvarMapType::const_iterator it = hostvarMap.find(col);
      if (it == hostvarMap.end())
        log_warn("hostvariable :" << col << " not found");
      else
      {
        values[it->second].setValue(data ? "1" : "0");
        paramFormats[it->second] = 0;
      }

      SET_TYPE(col, "bool");
    }

    void Statement::setInt(const std::string& col, int data)
    {
      log_debug("setInt(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "int");
    }

    void Statement::setLong(const std::string& col, long data)
    {
      log_debug("setLong(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "long");
    }

    void Statement::setUnsigned(const std::string& col, unsigned data)
    {
      log_debug("setUnsigned(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "unsigned");
    }

    void Statement::setUnsignedLong(const std::string& col, unsigned long data)
    {
      log_debug("setUnsignedLong(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "unsigned long");
    }

    void Statement::setInt32(const std::string& col, int32_t data)
    {
      log_debug("setInt32(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "int");
    }

    void Statement::setUnsigned32(const std::string& col, uint32_t data)
    {
      log_debug("setUnsigned32(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "int");
    }

    void Statement::setInt64(const std::string& col, int64_t data)
    {
      log_debug("setInt64(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "bigint");
    }

    void Statement::setUnsigned64(const std::string& col, uint64_t data)
    {
      log_debug("setUnsigned64(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "bigint");
    }

    void Statement::setDecimal(const std::string& col, const Decimal& data)
    {
      log_debug("setDecimal(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "numeric");
    }

    void Statement::setFloat(const std::string& col, float data)
    {
      log_debug("setFloat(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "numeric");
    }

    void Statement::setDouble(const std::string& col, double data)
    {
      log_debug("setDouble(\"" << col << "\", " << data << ')');
      setValue(col, data);
      SET_TYPE(col, "numeric");
    }

    void Statement::setChar(const std::string& col, char data)
    {
      log_debug("setChar(\"" << col << "\", '" << data << "')");
      setStringValue(col, std::string(1, data));
      SET_TYPE(col, "text");
    }

    void Statement::setString(const std::string& col, const std::string& data)
    {
      log_debug("setString(\"" << col << "\", \"" << data << "\")");
      setStringValue(col, data);
      SET_TYPE(col, "text");
    }

    void Statement::setBlob(const std::string& col, const Blob& data)
    {
      log_debug("setBlob(\"" << col << "\", Blob)");
      setStringValue(col, std::string(data.data(), data.size()), true);
      SET_TYPE(col, "blob");
    }

    void Statement::setDate(const std::string& col, const Date& data)
    {
      log_debug("setDate(\"" << col << "\", " << data.getIso() << ')');
      setIsoValue(col, data);
      SET_TYPE(col, "date");
    }

    void Statement::setTime(const std::string& col, const Time& data)
    {
      log_debug("setTime(\"" << col << "\", " << data.getIso() << ')');
      setIsoValue(col, data);
      SET_TYPE(col, "time");
    }

    void Statement::setDatetime(const std::string& col, const Datetime& data)
    {
      log_debug("setDatetime(\"" << col << "\", " << data.getIso() << ')');
      setIsoValue(col, data);
      SET_TYPE(col, "datetime");
    }

    Statement::size_type Statement::execute()
    {
      log_debug("execute()");

      PGresult* result = execPrepared();

      std::istringstream tuples(PQcmdTuples(result));
      unsigned ret = 0;
      tuples >> ret;

      log_debug("PQclear(" << result << ')');
      PQclear(result);

      return ret;
    }

    tntdb::Result Statement::select()
    {
      log_debug("select()");
      PGresult* result = execPrepared();
      return tntdb::Result(new Result(tntdb::Connection(conn), result));
    }

    tntdb::Row Statement::selectRow()
    {
      tntdb::Result result = select();

      if (result.size() <= 0)
        throw NotFound();

      return result[0];
    }

    tntdb::Value Statement::selectValue()
    {
      tntdb::Result result = select();

      if (result.size() <= 0)
        throw NotFound();

      return result[0][0];
    }

    ICursor* Statement::createCursor(unsigned fetchsize)
    {
      return new Cursor(this, fetchsize);
    }

    const char* const* Statement::getParamValues()
    {
      for (unsigned n = 0; n < values.size(); ++n)
        paramValues[n] = values[n].getValue();
      return &paramValues[0];
    }

    const int* Statement::getParamLengths()
    {
      for (unsigned n = 0; n < values.size(); ++n)
        paramLengths[n] = values[n].getLength();
      return &paramLengths[0];
    }

    PGconn* Statement::getPGConn()
    {
      return conn->getPGConn();
    }
  }
}
<|endoftext|>


<commit_before>#include "networking/servernetworker.h"
#include "global_constants.h"

ServerNetworker::ServerNetworker() : Networker(true)
{
    ENetAddress address;
    address.host = ENET_HOST_ANY;
    address.port = 3224; // 3223-3230
    host = enet_host_create(&address, PLAYER_LIMIT, 1, 0, 0);
    if (host == NULL)
    {
        fprintf(stderr, "Fatal Error while attempting to create server host!");
        throw -1;
    }
}

ServerNetworker::~ServerNetworker()
{
    //dtor
}

void ServerNetworker::receive(Gamestate *state)
{
    ENetEvent event;
    while (enet_host_service(host, &event, 0))
    {
        if (event.type == ENET_EVENT_TYPE_CONNECT)
        {
            EntityPtr player = state->addplayer();
            event.peer->data = std::malloc(sizeof(int));
            reinterpret_cast<int*>(event.peer->data)[0] = state->playerlist[state->playerlist.size()-1];

            enet_peer_timeout(event.peer, 0, 2000, 3000);

            // Send full update
            WriteBuffer frame = WriteBuffer();
            frame.write<uint8_t>(SERVER_FULLUPDATE);
            state->serializefull(&frame);
            ENetPacket *eventpacket = enet_packet_create(frame.getdata(), frame.length(), ENET_PACKET_FLAG_RELIABLE);
            enet_peer_send(event.peer, 0, eventpacket);
            enet_host_flush(host);

            // Set the spawn timer for the new player so that they will spawn at next opportunity
            state->get<Player>(player)->spawntimer.timer = state->get<Player>(player)->spawntimer.duration;
            state->get<Player>(player)->spawntimer.active = true;
        }
        else if (event.type == ENET_EVENT_TYPE_DISCONNECT)
        {
            int i = state->findplayerid(reinterpret_cast<int*>(event.peer->data)[0]);
            state->removeplayer(i);
            std::free(event.peer->data);

            // Send disconnect event of that player
            sendbuffer.write<uint8_t>(PLAYER_LEFT);
            sendbuffer.write<uint8_t>(i);
        }
        else if (event.type == ENET_EVENT_TYPE_RECEIVE)
        {
            ReadBuffer data = ReadBuffer(event.packet->data, event.packet->dataLength);
            while (data.length() > 0)
            {
                int eventtype = data.read<uint8_t>();
                if (eventtype == CLIENT_INPUT)
                {
                    Player *p = state->get<Player>(reinterpret_cast<int*>(event.peer->data)[0]);
                    if (p->character != 0)
                    {
                        INPUT_CONTAINER pressedkeys = INPUT_CONTAINER();
                        INPUT_CONTAINER heldkeys = INPUT_CONTAINER();
                        pressedkeys.deserialize(&data);
                        heldkeys.deserialize(&data);
                        double mouse_x = data.read<int16_t>();
                        double mouse_y = data.read<int16_t>();
                        p->getcharacter(state)->setinput(state, pressedkeys, heldkeys, mouse_x, mouse_y);
                    }
                }
                else
                {
                    fprintf(stderr, "Invalid packet received on server: %i!", eventtype);
                }
            }
            enet_packet_destroy(event.packet);
        }
    }
}

void ServerNetworker::sendeventdata(Gamestate *state)
{
    if (sendbuffer.length() > 0)
    {
        ENetPacket *eventpacket = enet_packet_create(sendbuffer.getdata(), sendbuffer.length(), ENET_PACKET_FLAG_RELIABLE);
        enet_host_broadcast(host, 0, eventpacket);
        enet_host_flush(host);
        sendbuffer.reset();
    }
}

void ServerNetworker::sendframedata(Gamestate *state)
{
    WriteBuffer frame = WriteBuffer();
    frame.write<uint8_t>(SERVER_SNAPSHOTUPDATE);
    state->serializesnapshot(&frame);
    ENetPacket *framepacket = enet_packet_create(frame.getdata(), frame.length(), 0);
    enet_host_broadcast(host, 0, framepacket);
    enet_host_flush(host);
}
<commit_msg>Fixed player join not being synced at all.<commit_after>#include "networking/servernetworker.h"
#include "global_constants.h"

ServerNetworker::ServerNetworker() : Networker(true)
{
    ENetAddress address;
    address.host = ENET_HOST_ANY;
    address.port = 3224; // 3223-3230
    host = enet_host_create(&address, PLAYER_LIMIT, 1, 0, 0);
    if (host == NULL)
    {
        fprintf(stderr, "Fatal Error while attempting to create server host!");
        throw -1;
    }
}

ServerNetworker::~ServerNetworker()
{
    //dtor
}

void ServerNetworker::receive(Gamestate *state)
{
    ENetEvent event;
    while (enet_host_service(host, &event, 0))
    {
        if (event.type == ENET_EVENT_TYPE_CONNECT)
        {
            EntityPtr player = state->addplayer();
            event.peer->data = std::malloc(sizeof(int));
            reinterpret_cast<int*>(event.peer->data)[0] = state->playerlist[state->playerlist.size()-1];

            enet_peer_timeout(event.peer, 0, 2000, 3000);

            // Send full update
            WriteBuffer frame = WriteBuffer();
            frame.write<uint8_t>(SERVER_FULLUPDATE);
            state->serializefull(&frame);
            ENetPacket *eventpacket = enet_packet_create(frame.getdata(), frame.length(), ENET_PACKET_FLAG_RELIABLE);
            enet_peer_send(event.peer, 0, eventpacket);

            // Set the spawn timer for the new player so that they will spawn at next opportunity
            state->get<Player>(player)->spawntimer.timer = state->get<Player>(player)->spawntimer.duration;
            state->get<Player>(player)->spawntimer.active = true;

            // Tell everyone except the new player that a new player joined
            WriteBuffer tmpbuffer;
            tmpbuffer.write<uint8_t>(PLAYER_JOINED);
            eventpacket = enet_packet_create(tmpbuffer.getdata(), tmpbuffer.length(), ENET_PACKET_FLAG_RELIABLE);
            for (unsigned int i=0; i<host->connectedPeers; ++i)
            {
                if (&(host->peers[i]) != event.peer)
                {
                    enet_peer_send(&(host->peers[i]), 0, eventpacket);
                }
            }

            enet_host_flush(host);
        }
        else if (event.type == ENET_EVENT_TYPE_DISCONNECT)
        {
            int i = state->findplayerid(reinterpret_cast<int*>(event.peer->data)[0]);
            state->removeplayer(i);
            std::free(event.peer->data);

            // Send disconnect event of that player
            sendbuffer.write<uint8_t>(PLAYER_LEFT);
            sendbuffer.write<uint8_t>(i);
        }
        else if (event.type == ENET_EVENT_TYPE_RECEIVE)
        {
            ReadBuffer data = ReadBuffer(event.packet->data, event.packet->dataLength);
            while (data.length() > 0)
            {
                int eventtype = data.read<uint8_t>();
                if (eventtype == CLIENT_INPUT)
                {
                    Player *p = state->get<Player>(reinterpret_cast<int*>(event.peer->data)[0]);
                    if (p->character != 0)
                    {
                        INPUT_CONTAINER pressedkeys = INPUT_CONTAINER();
                        INPUT_CONTAINER heldkeys = INPUT_CONTAINER();
                        pressedkeys.deserialize(&data);
                        heldkeys.deserialize(&data);
                        double mouse_x = data.read<int16_t>();
                        double mouse_y = data.read<int16_t>();
                        p->getcharacter(state)->setinput(state, pressedkeys, heldkeys, mouse_x, mouse_y);
                    }
                }
                else
                {
                    fprintf(stderr, "Invalid packet received on server: %i!", eventtype);
                }
            }
            enet_packet_destroy(event.packet);
        }
    }
}

void ServerNetworker::sendeventdata(Gamestate *state)
{
    if (sendbuffer.length() > 0)
    {
        ENetPacket *eventpacket = enet_packet_create(sendbuffer.getdata(), sendbuffer.length(), ENET_PACKET_FLAG_RELIABLE);
        enet_host_broadcast(host, 0, eventpacket);
        enet_host_flush(host);
        sendbuffer.reset();
    }
}

void ServerNetworker::sendframedata(Gamestate *state)
{
    WriteBuffer frame = WriteBuffer();
    frame.write<uint8_t>(SERVER_SNAPSHOTUPDATE);
    state->serializesnapshot(&frame);
    ENetPacket *framepacket = enet_packet_create(frame.getdata(), frame.length(), 0);
    enet_host_broadcast(host, 0, framepacket);
    enet_host_flush(host);
}
<|endoftext|>