<commit_before>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * 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 "modules/map/relative_map/navigation_lane.h"

#include <algorithm>
#include <limits>

#include "modules/map/proto/map_lane.pb.h"

#include "modules/common/log.h"
#include "modules/common/math/math_utils.h"
#include "modules/common/math/vec2d.h"
#include "modules/common/util/util.h"
#include "modules/common/vehicle_state/vehicle_state_provider.h"
#include "modules/map/relative_map/common/relative_map_gflags.h"

namespace apollo {
namespace relative_map {

using apollo::common::VehicleStateProvider;
using apollo::common::math::Vec2d;
using apollo::common::util::DistanceXY;
using apollo::hdmap::Lane;
using apollo::common::util::operator+;
using apollo::perception::PerceptionObstacles;

NavigationLane::NavigationLane(const NavigationLaneConfig &config)
    : config_(config) {}

void NavigationLane::SetConfig(const NavigationLaneConfig &config) {
  config_ = config;
}

bool NavigationLane::GeneratePath() {
  // original_pose is in world coordination: ENU
  original_pose_ = VehicleStateProvider::instance()->original_pose();

  navigation_path_.Clear();
  auto *path = navigation_path_.mutable_path();
  const auto &lane_marker = perception_obstacles_.lane_marker();

  // priority: merge > navigation line > perception lane marker
  if (FLAGS_enable_navigation_line &&
      navigation_info_.navigation_path_size() > 0) {
    ConvertNavigationLineToPath(path);
    if (path->path_point().size() <= 0) {
      ConvertLaneMarkerToPath(lane_marker, path);
    }
  } else {
    ConvertLaneMarkerToPath(lane_marker, path);
  }
  return true;
}

double NavigationLane::EvaluateCubicPolynomial(const double c0, const double c1,
                                               const double c2, const double c3,
                                               const double z) const {
  return ((c3 * z + c2) * z + c1) * z + c0;
}

void NavigationLane::MergeNavigationLineAndLaneMarker(
    const perception::LaneMarkers &lane_marker, common::Path *path) {
  CHECK_NOTNULL(path);

  common::Path navigation_path;
  ConvertNavigationLineToPath(&navigation_path);

  common::Path lane_marker_path;
  ConvertLaneMarkerToPath(perception_obstacles_.lane_marker(),
                          &lane_marker_path);

  const double len = std::fmin(
      navigation_path.path_point(navigation_path.path_point_size() - 1).s(),
      lane_marker_path.path_point(lane_marker_path.path_point_size() - 1).s());

  const double ds = 1.0;
  int navigation_index = 0;
  int lane_marker_index = 0;
  for (double s = 0.0; s < len; s += ds) {
    auto p1 = GetPathPointByS(navigation_path, navigation_index, s,
                              &navigation_index);
    auto p2 = GetPathPointByS(lane_marker_path, lane_marker_index, s,
                              &lane_marker_index);
    auto *p = path->add_path_point();
    const double kWeight = 0.9;
    *p = common::util::GetWeightedAverageOfTwoPathPoints(p1, p2, kWeight,
                                                         1 - kWeight);
  }
}

common::PathPoint NavigationLane::GetPathPointByS(const common::Path &path,
                                                  const int start_index,
                                                  const double s,
                                                  int *matched_index) {
  CHECK_NOTNULL(matched_index);

  constexpr double kEpsilon = 1e-9;
  if (std::fabs(path.path_point(start_index).s() - s) < kEpsilon) {
    *matched_index = start_index;
    return path.path_point(start_index);
  }
  int i = start_index;
  while (i + 1 < path.path_point_size() && path.path_point(i + 1).s() < s) {
    ++i;
  }
  *matched_index = i;

  // x, y, z, theta, kappa, s, dkappa, ddkappa
  const double r = (s - path.path_point(i).s()) /
                   (path.path_point(i + 1).s() - path.path_point(i).s());
  auto p = common::util::GetWeightedAverageOfTwoPathPoints(
      path.path_point(i), path.path_point(i + 1), 1 - r, r);
  return p;
}

void NavigationLane::ConvertNavigationLineToPath(common::Path *path) {
  CHECK_NOTNULL(path);
  if (navigation_info_.navigation_path_size() == 0 ||
      !navigation_info_.navigation_path(0).has_path() ||
      navigation_info_.navigation_path(0).path().path_point_size() == 0) {
    // path is empty
    return;
  }
  path->set_name("Path from navigation.");
  if (!UpdateProjectionIndex()) {
    return;
  }

  // TODO(All): support multiple navigation path
  // currently, only 1 navigation path is supported
  const auto &navigation_path = navigation_info_.navigation_path(0).path();
  int curr_project_index = last_project_index_;

  double dist =
      navigation_path.path_point(navigation_path.path_point_size() - 1).s() -
      navigation_path.path_point(curr_project_index).s();
  if (dist < 20) {
    return;
  }

  // offset between the current vehicle state and navigation line
  const double dx = -original_pose_.position().x();
  const double dy = -original_pose_.position().y();
  const double ref_s = navigation_path.path_point(curr_project_index).s();
  for (int i = std::max(0, curr_project_index - 3);
       i < navigation_path.path_point_size(); ++i) {
    auto *point = path->add_path_point();
    point->CopyFrom(navigation_path.path_point(i));

    // shift to (0, 0)
    double enu_x = point->x() + dx;
    double enu_y = point->y() + dy;

    double flu_x = 0.0;
    double flu_y = 0.0;
    common::math::RotateAxis(original_pose_.heading(), enu_x, enu_y, &flu_x,
                             &flu_y);

    point->set_x(flu_x);
    point->set_y(flu_y);
    point->set_theta(common::math::NormalizeAngle(
        common::math::NormalizeAngle(point->theta()) -
        original_pose_.heading()));
    const double accumulated_s = navigation_path.path_point(i).s() - ref_s;
    point->set_s(accumulated_s);

    if (accumulated_s > FLAGS_max_len_from_navigation_line) {
      break;
    }
  }

  const perception::LaneMarkers &lane_marker =
      perception_obstacles_.lane_marker();
  const auto &left_lane = lane_marker.left_lane_marker();
  const auto &right_lane = lane_marker.right_lane_marker();
  left_width_ = (std::fabs(left_lane.c0_position()) +
                 std::fabs(right_lane.c0_position())) /
                2.0;
  right_width_ = left_width_;
}

// project adc_state_ onto path
bool NavigationLane::UpdateProjectionIndex() {
  // TODO(All): support multiple navigation path
  // currently, only 1 navigation path is supported
  const auto &path = navigation_info_.navigation_path(0).path();
  int index = 0;
  double min_d = std::numeric_limits<double>::max();
  for (int i = last_project_index_; i + 1 < path.path_point_size(); ++i) {
    const double d = DistanceXY(original_pose_.position(), path.path_point(i));
    if (d < min_d) {
      min_d = d;
      index = i;
    }
    const double kMaxDistance = 50.0;
    if (last_project_index_ != 0 && d > kMaxDistance) {
      break;
    }
  }
  if (min_d > FLAGS_max_distance_to_navigation_line) {
    return false;
  }
  last_project_index_ = index;
  return true;
}

void NavigationLane::ConvertLaneMarkerToPath(
    const perception::LaneMarkers &lane_marker, common::Path *path) {
  CHECK_NOTNULL(path);

  path->set_name("Path from lane markers.");
  const auto &left_lane = lane_marker.left_lane_marker();
  const auto &right_lane = lane_marker.right_lane_marker();

  double path_c0 = (left_lane.c0_position() + right_lane.c0_position()) / 2.0;

  double left_quality = left_lane.quality() + 0.001;
  double right_quality = right_lane.quality() + 0.001;

  double quality_divider = left_quality + right_quality;

  double path_c1 = (left_lane.c1_heading_angle() * left_quality +
                    right_lane.c1_heading_angle() * right_quality) /
                   quality_divider;

  double path_c2 = (left_lane.c2_curvature() * left_quality +
                    right_lane.c2_curvature() * right_quality) /
                   quality_divider;

  double path_c3 = (left_lane.c3_curvature_derivative() * left_quality +
                    right_lane.c3_curvature_derivative() * right_quality) /
                   quality_divider;

  const double current_speed =
      VehicleStateProvider::instance()->vehicle_state().linear_velocity();
  double path_range = current_speed * FLAGS_ratio_navigation_lane_len_to_speed;
  if (path_range <= FLAGS_min_len_for_navigation_lane) {
    path_range = FLAGS_min_len_for_navigation_lane;
  } else {
    path_range = FLAGS_max_len_for_navigation_lane;
  }

  const double unit_z = 1.0;
  const double start_s = -2.0;
  double accumulated_s = start_s;
  for (double z = start_s; z <= path_range; z += unit_z) {
    double x1 = z;
    double y1 = 0;
    if (left_lane.view_range() > FLAGS_min_view_range_to_use_lane_marker ||
        right_lane.view_range() > FLAGS_min_view_range_to_use_lane_marker) {
      y1 = EvaluateCubicPolynomial(path_c0, path_c1, path_c2, path_c3, z);
    }
    auto *point = path->add_path_point();
    point->set_x(x1);
    point->set_y(y1);

    if (path->path_point_size() > 1) {
      auto &pre_point = path->path_point(path->path_point_size() - 2);
      accumulated_s += std::hypot(x1 - pre_point.x(), y1 - pre_point.y());
    }
    point->set_s(accumulated_s);
  }

  left_width_ = (std::fabs(left_lane.c0_position()) +
                 std::fabs(right_lane.c0_position())) /
                2.0;
  right_width_ = left_width_;
}

bool NavigationLane::CreateMap(const MapGenerationParam &map_config,
                               MapMsg *map_msg) const {
  auto *navigation_info = map_msg->mutable_navigation_path();
  auto *hdmap = map_msg->mutable_hdmap();
  auto *lane_marker = map_msg->mutable_lane_marker();

  lane_marker->CopyFrom(perception_obstacles_.lane_marker());

  const auto &path = navigation_path_.path();
  if (path.path_point_size() < 2) {
    AERROR << "The path length is invalid";
    return false;
  }
  auto *lane = hdmap->add_lane();
  lane->mutable_id()->set_id(std::to_string(navigation_path_.path_priority()) +
                             "_" + path.name());
  (*navigation_info)[lane->id().id()] = navigation_path_;
  // lane types
  lane->set_type(Lane::CITY_DRIVING);
  lane->set_turn(Lane::NO_TURN);

  // speed limit
  lane->set_speed_limit(map_config.default_speed_limit());

  // center line
  auto *curve_segment = lane->mutable_central_curve()->add_segment();
  curve_segment->set_heading(path.path_point(0).theta());
  auto *line_segment = curve_segment->mutable_line_segment();
  // left boundary
  auto *left_boundary = lane->mutable_left_boundary();
  auto *left_boundary_type = left_boundary->add_boundary_type();
  left_boundary->set_virtual_(false);
  left_boundary_type->set_s(0.0);
  left_boundary_type->add_types(
      perception_obstacles_.lane_marker().left_lane_marker().lane_type());
  auto *left_segment =
      left_boundary->mutable_curve()->add_segment()->mutable_line_segment();
  // right boundary
  auto *right_boundary = lane->mutable_right_boundary();
  auto *right_boundary_type = right_boundary->add_boundary_type();
  right_boundary->set_virtual_(false);
  right_boundary_type->set_s(0.0);
  right_boundary_type->add_types(
      perception_obstacles_.lane_marker().right_lane_marker().lane_type());
  auto *right_segment =
      right_boundary->mutable_curve()->add_segment()->mutable_line_segment();
  const double lane_left_width =
      left_width_ > 0 ? left_width_ : map_config.default_left_width();
  const double lane_right_width =
      right_width_ > 0 ? right_width_ : map_config.default_right_width();
  for (const auto &path_point : path.path_point()) {
    auto *point = line_segment->add_point();
    point->set_x(path_point.x());
    point->set_y(path_point.y());
    point->set_z(path_point.z());
    auto *left_sample = lane->add_left_sample();
    left_sample->set_s(path_point.s());
    left_sample->set_width(lane_left_width);
    left_segment->add_point()->CopyFrom(
        *point +
        lane_left_width * Vec2d::CreateUnitVec2d(path_point.theta() + M_PI_2));
    auto *right_sample = lane->add_right_sample();
    right_sample->set_s(path_point.s());
    right_sample->set_width(lane_right_width);
    right_segment->add_point()->CopyFrom(
        *point +
        lane_right_width * Vec2d::CreateUnitVec2d(path_point.theta() - M_PI_2));
  }

  return true;
}

}  // namespace relative_map
}  // namespace apollo
<commit_msg>navi: added theta for lane marker based ref line.<commit_after>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * 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 "modules/map/relative_map/navigation_lane.h"

#include <algorithm>
#include <limits>

#include "modules/map/proto/map_lane.pb.h"

#include "modules/common/log.h"
#include "modules/common/math/math_utils.h"
#include "modules/common/math/vec2d.h"
#include "modules/common/util/util.h"
#include "modules/common/vehicle_state/vehicle_state_provider.h"
#include "modules/map/relative_map/common/relative_map_gflags.h"

namespace apollo {
namespace relative_map {

using apollo::common::VehicleStateProvider;
using apollo::common::math::Vec2d;
using apollo::common::util::DistanceXY;
using apollo::hdmap::Lane;
using apollo::common::util::operator+;
using apollo::perception::PerceptionObstacles;

NavigationLane::NavigationLane(const NavigationLaneConfig &config)
    : config_(config) {}

void NavigationLane::SetConfig(const NavigationLaneConfig &config) {
  config_ = config;
}

bool NavigationLane::GeneratePath() {
  // original_pose is in world coordination: ENU
  original_pose_ = VehicleStateProvider::instance()->original_pose();

  navigation_path_.Clear();
  auto *path = navigation_path_.mutable_path();
  const auto &lane_marker = perception_obstacles_.lane_marker();

  // priority: merge > navigation line > perception lane marker
  if (FLAGS_enable_navigation_line &&
      navigation_info_.navigation_path_size() > 0) {
    ConvertNavigationLineToPath(path);
    if (path->path_point().size() <= 0) {
      ConvertLaneMarkerToPath(lane_marker, path);
    }
  } else {
    ConvertLaneMarkerToPath(lane_marker, path);
  }
  return true;
}

double NavigationLane::EvaluateCubicPolynomial(const double c0, const double c1,
                                               const double c2, const double c3,
                                               const double z) const {
  return ((c3 * z + c2) * z + c1) * z + c0;
}

void NavigationLane::MergeNavigationLineAndLaneMarker(
    const perception::LaneMarkers &lane_marker, common::Path *path) {
  CHECK_NOTNULL(path);

  common::Path navigation_path;
  ConvertNavigationLineToPath(&navigation_path);

  common::Path lane_marker_path;
  ConvertLaneMarkerToPath(perception_obstacles_.lane_marker(),
                          &lane_marker_path);

  const double len = std::fmin(
      navigation_path.path_point(navigation_path.path_point_size() - 1).s(),
      lane_marker_path.path_point(lane_marker_path.path_point_size() - 1).s());

  const double ds = 1.0;
  int navigation_index = 0;
  int lane_marker_index = 0;
  for (double s = 0.0; s < len; s += ds) {
    auto p1 = GetPathPointByS(navigation_path, navigation_index, s,
                              &navigation_index);
    auto p2 = GetPathPointByS(lane_marker_path, lane_marker_index, s,
                              &lane_marker_index);
    auto *p = path->add_path_point();
    const double kWeight = 0.9;
    *p = common::util::GetWeightedAverageOfTwoPathPoints(p1, p2, kWeight,
                                                         1 - kWeight);
  }
}

common::PathPoint NavigationLane::GetPathPointByS(const common::Path &path,
                                                  const int start_index,
                                                  const double s,
                                                  int *matched_index) {
  CHECK_NOTNULL(matched_index);

  constexpr double kEpsilon = 1e-9;
  if (std::fabs(path.path_point(start_index).s() - s) < kEpsilon) {
    *matched_index = start_index;
    return path.path_point(start_index);
  }
  int i = start_index;
  while (i + 1 < path.path_point_size() && path.path_point(i + 1).s() < s) {
    ++i;
  }
  *matched_index = i;

  // x, y, z, theta, kappa, s, dkappa, ddkappa
  const double r = (s - path.path_point(i).s()) /
                   (path.path_point(i + 1).s() - path.path_point(i).s());
  auto p = common::util::GetWeightedAverageOfTwoPathPoints(
      path.path_point(i), path.path_point(i + 1), 1 - r, r);
  return p;
}

void NavigationLane::ConvertNavigationLineToPath(common::Path *path) {
  CHECK_NOTNULL(path);
  if (navigation_info_.navigation_path_size() == 0 ||
      !navigation_info_.navigation_path(0).has_path() ||
      navigation_info_.navigation_path(0).path().path_point_size() == 0) {
    // path is empty
    return;
  }
  path->set_name("Path from navigation.");
  if (!UpdateProjectionIndex()) {
    return;
  }

  // TODO(All): support multiple navigation path
  // currently, only 1 navigation path is supported
  const auto &navigation_path = navigation_info_.navigation_path(0).path();
  int curr_project_index = last_project_index_;

  double dist =
      navigation_path.path_point(navigation_path.path_point_size() - 1).s() -
      navigation_path.path_point(curr_project_index).s();
  if (dist < 20) {
    return;
  }

  // offset between the current vehicle state and navigation line
  const double dx = -original_pose_.position().x();
  const double dy = -original_pose_.position().y();
  const double ref_s = navigation_path.path_point(curr_project_index).s();
  for (int i = std::max(0, curr_project_index - 3);
       i < navigation_path.path_point_size(); ++i) {
    auto *point = path->add_path_point();
    point->CopyFrom(navigation_path.path_point(i));

    // shift to (0, 0)
    double enu_x = point->x() + dx;
    double enu_y = point->y() + dy;

    double flu_x = 0.0;
    double flu_y = 0.0;
    common::math::RotateAxis(original_pose_.heading(), enu_x, enu_y, &flu_x,
                             &flu_y);

    point->set_x(flu_x);
    point->set_y(flu_y);
    point->set_theta(common::math::NormalizeAngle(
        common::math::NormalizeAngle(point->theta()) -
        original_pose_.heading()));
    const double accumulated_s = navigation_path.path_point(i).s() - ref_s;
    point->set_s(accumulated_s);

    if (accumulated_s > FLAGS_max_len_from_navigation_line) {
      break;
    }
  }

  const perception::LaneMarkers &lane_marker =
      perception_obstacles_.lane_marker();
  const auto &left_lane = lane_marker.left_lane_marker();
  const auto &right_lane = lane_marker.right_lane_marker();
  left_width_ = (std::fabs(left_lane.c0_position()) +
                 std::fabs(right_lane.c0_position())) /
                2.0;
  right_width_ = left_width_;
}

// project adc_state_ onto path
bool NavigationLane::UpdateProjectionIndex() {
  // TODO(All): support multiple navigation path
  // currently, only 1 navigation path is supported
  const auto &path = navigation_info_.navigation_path(0).path();
  int index = 0;
  double min_d = std::numeric_limits<double>::max();
  for (int i = last_project_index_; i + 1 < path.path_point_size(); ++i) {
    const double d = DistanceXY(original_pose_.position(), path.path_point(i));
    if (d < min_d) {
      min_d = d;
      index = i;
    }
    const double kMaxDistance = 50.0;
    if (last_project_index_ != 0 && d > kMaxDistance) {
      break;
    }
  }
  if (min_d > FLAGS_max_distance_to_navigation_line) {
    return false;
  }
  last_project_index_ = index;
  return true;
}

void NavigationLane::ConvertLaneMarkerToPath(
    const perception::LaneMarkers &lane_marker, common::Path *path) {
  CHECK_NOTNULL(path);

  path->set_name("Path from lane markers.");
  const auto &left_lane = lane_marker.left_lane_marker();
  const auto &right_lane = lane_marker.right_lane_marker();

  double path_c0 = (left_lane.c0_position() + right_lane.c0_position()) / 2.0;

  double left_quality = left_lane.quality() + 0.001;
  double right_quality = right_lane.quality() + 0.001;

  double quality_divider = left_quality + right_quality;

  double path_c1 = (left_lane.c1_heading_angle() * left_quality +
                    right_lane.c1_heading_angle() * right_quality) /
                   quality_divider;

  double path_c2 = (left_lane.c2_curvature() * left_quality +
                    right_lane.c2_curvature() * right_quality) /
                   quality_divider;

  double path_c3 = (left_lane.c3_curvature_derivative() * left_quality +
                    right_lane.c3_curvature_derivative() * right_quality) /
                   quality_divider;

  const double current_speed =
      VehicleStateProvider::instance()->vehicle_state().linear_velocity();
  double path_range = current_speed * FLAGS_ratio_navigation_lane_len_to_speed;
  if (path_range <= FLAGS_min_len_for_navigation_lane) {
    path_range = FLAGS_min_len_for_navigation_lane;
  } else {
    path_range = FLAGS_max_len_for_navigation_lane;
  }

  const double unit_z = 1.0;
  const double start_s = -2.0;
  double accumulated_s = start_s;
  for (double z = start_s; z <= path_range; z += unit_z) {
    double x1 = z;
    double y1 = 0;
    if (left_lane.view_range() > FLAGS_min_view_range_to_use_lane_marker ||
        right_lane.view_range() > FLAGS_min_view_range_to_use_lane_marker) {
      y1 = EvaluateCubicPolynomial(path_c0, path_c1, path_c2, path_c3, z);
    }
    auto *point = path->add_path_point();
    point->set_x(x1);
    point->set_y(y1);

    if (path->path_point_size() > 1) {
      auto &pre_point = path->path_point(path->path_point_size() - 2);
      accumulated_s += std::hypot(x1 - pre_point.x(), y1 - pre_point.y());
    }
    point->set_s(accumulated_s);
    point->set_theta(
        std::atan2(3 * path_c3 * x1 * x1 + 2 * path_c2 * x1 + path_c1, 1));
  }

  left_width_ = (std::fabs(left_lane.c0_position()) +
                 std::fabs(right_lane.c0_position())) /
                2.0;
  right_width_ = left_width_;
}

bool NavigationLane::CreateMap(const MapGenerationParam &map_config,
                               MapMsg *map_msg) const {
  auto *navigation_info = map_msg->mutable_navigation_path();
  auto *hdmap = map_msg->mutable_hdmap();
  auto *lane_marker = map_msg->mutable_lane_marker();

  lane_marker->CopyFrom(perception_obstacles_.lane_marker());

  const auto &path = navigation_path_.path();
  if (path.path_point_size() < 2) {
    AERROR << "The path length is invalid";
    return false;
  }
  auto *lane = hdmap->add_lane();
  lane->mutable_id()->set_id(std::to_string(navigation_path_.path_priority()) +
                             "_" + path.name());
  (*navigation_info)[lane->id().id()] = navigation_path_;
  // lane types
  lane->set_type(Lane::CITY_DRIVING);
  lane->set_turn(Lane::NO_TURN);

  // speed limit
  lane->set_speed_limit(map_config.default_speed_limit());

  // center line
  auto *curve_segment = lane->mutable_central_curve()->add_segment();
  curve_segment->set_heading(path.path_point(0).theta());
  auto *line_segment = curve_segment->mutable_line_segment();
  // left boundary
  auto *left_boundary = lane->mutable_left_boundary();
  auto *left_boundary_type = left_boundary->add_boundary_type();
  left_boundary->set_virtual_(false);
  left_boundary_type->set_s(0.0);
  left_boundary_type->add_types(
      perception_obstacles_.lane_marker().left_lane_marker().lane_type());
  auto *left_segment =
      left_boundary->mutable_curve()->add_segment()->mutable_line_segment();
  // right boundary
  auto *right_boundary = lane->mutable_right_boundary();
  auto *right_boundary_type = right_boundary->add_boundary_type();
  right_boundary->set_virtual_(false);
  right_boundary_type->set_s(0.0);
  right_boundary_type->add_types(
      perception_obstacles_.lane_marker().right_lane_marker().lane_type());
  auto *right_segment =
      right_boundary->mutable_curve()->add_segment()->mutable_line_segment();
  const double lane_left_width =
      left_width_ > 0 ? left_width_ : map_config.default_left_width();
  const double lane_right_width =
      right_width_ > 0 ? right_width_ : map_config.default_right_width();
  for (const auto &path_point : path.path_point()) {
    auto *point = line_segment->add_point();
    point->set_x(path_point.x());
    point->set_y(path_point.y());
    point->set_z(path_point.z());
    auto *left_sample = lane->add_left_sample();
    left_sample->set_s(path_point.s());
    left_sample->set_width(lane_left_width);
    left_segment->add_point()->CopyFrom(
        *point +
        lane_left_width * Vec2d::CreateUnitVec2d(path_point.theta() + M_PI_2));
    auto *right_sample = lane->add_right_sample();
    right_sample->set_s(path_point.s());
    right_sample->set_width(lane_right_width);
    right_segment->add_point()->CopyFrom(
        *point +
        lane_right_width * Vec2d::CreateUnitVec2d(path_point.theta() - M_PI_2));
  }

  return true;
}

}  // namespace relative_map
}  // namespace apollo
<|endoftext|>


<commit_before>#pragma once

#include "common/dep.hpp"

struct syntaxTest : public ::testing::Test {
    void SetUp() {}
    void TearDown() {}

    wrd::str parse(const wrd::wchar* src) {
        wrd::parser p;
        wrd::errReport rpt;
        wrd::str ret = p.setReport(rpt).parse(src);
        EXPECT_TRUE(!rpt && ret) << "test code: " << src << "\n";
        return ret;
    }

    void parseFail(const wrd::wchar* src) {
        wrd::parser p;
        wrd::errReport rpt;
        wrd::str ret = p.setReport(rpt).parse(src);
        EXPECT_TRUE(rpt || !ret) << "test code: " << src << "\n";
    }

    wrd::wbool assertSame(wrd::str unit, const wrd::wchar* expect) {
        // TODO: run unit and gather output and compare it to expect
        return true;
    }
};
<commit_msg>wrd: test: syntaxTest can examine warning reports and test<commit_after>#pragma once

#include "common/dep.hpp"

struct syntaxTest : public ::testing::Test {
    void SetUp() {}
    void TearDown() {}

    wrd::str parse(const wrd::wchar* src) {
        wrd::errReport rpt;
        return parse(src, rpt);
    }

    wrd::str parse(const wrd::wchar* src, wrd::errReport& rpt) {
        wrd::parser p;
        wrd::str ret = p.setReport(rpt).parse(src);
        EXPECT_TRUE(!rpt && ret) << "test code: " << src << "\n";
        return ret;
    }

    void parseFail(const wrd::wchar* src) {
        wrd::errReport rpt;
        parseFail(src, rpt);
    }

    void parseFail(const wrd::wchar* src, wrd::errReport& rpt) {
        wrd::parser p;
        wrd::str ret = p.setReport(rpt).parse(src);
        EXPECT_TRUE(rpt || !ret) << "test code: " << src << "\n";
    }

    wrd::wbool assertSame(wrd::str unit, const wrd::wchar* expect) {
        // TODO: run unit and gather output and compare it to expect
        return true;
    }
};
<|endoftext|>


<commit_before>#line 2 "togo/core/lua/lua.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief Scripting interface.
@ingroup lib_core_lua
*/

#pragma once

#include <togo/core/config.hpp>
#include <togo/core/types.hpp>
#include <togo/core/error/assert.hpp>
#include <togo/core/utility/traits.hpp>
#include <togo/core/utility/utility.hpp>
#include <togo/core/memory/types.hpp>
#include <togo/core/string/string.hpp>
#include <togo/core/lua/types.hpp>

extern "C" {
	#include <luajit-2.0/lua.h>
	#include <luajit-2.0/lauxlib.h>
	#include <luajit-2.0/lualib.h>
}

#include <togo/core/lua/lua.gen_interface>

namespace togo {
namespace lua {

/**
	@addtogroup lib_core_lua
	@{
*/

/// Push nil to the stack.
inline void push_value(lua_State* L, null_tag const) {
	lua_pushnil(L);
}

/// Push an integral value to the stack.
template<class T>
inline enable_if<is_integral<T>::value, void> push_value(lua_State* L, T value) {
	lua_pushinteger(L, value);
}

/// Get an argument from the stack as an integer.
inline LuaInt get_integer(lua_State* L, signed narg) {
	return luaL_checkinteger(L, narg);
}

/// Push a floating-point value to the stack.
template<class T>
inline enable_if<is_floating_point<T>::value, void> push_value(lua_State* L, T value) {
	lua_pushinteger(L, value);
}

/// Get an argument from the stack as an integer.
inline LuaFloat get_float(lua_State* L, signed narg) {
	return luaL_checknumber(L, narg);
}

// NB: Using template to avoid implicit cast from pointers and integrals.
/// Push a bool to the stack.
template<class T>
inline enable_if<is_same<T, bool>::value, void> push_value(lua_State* L, T value) {
	lua_pushboolean(L, value);
}

/// Get an argument from the stack as a boolean.
inline bool get_boolean(lua_State* L, signed narg) {
	luaL_checktype(L, narg, LUA_TBOOLEAN);
	return lua_toboolean(L, narg);
}

/// Push a string to the stack.
inline void push_value(lua_State* L, StringRef str) {
	lua_pushlstring(L, str.data ? str.data : "", unsigned_cast(str.size));
}

/// Get a string from the stack as a string reference.
inline StringRef get_string(lua_State* L, signed narg) {
	size_t size = 0;
	auto data = luaL_checklstring(L, narg, &size);
	return {data, static_cast<unsigned>(size)};
}

/// Push a C function to the stack.
inline void push_value(lua_State* L, LuaCFunction value) {
	lua_pushcfunction(L, value);
}

/// Get a C function from the stack.
inline LuaCFunction* get_cfunction(lua_State* L, signed narg) {
	luaL_checktype(L, narg, LUA_TFUNCTION);
	return lua_tocfunction(L, narg);
}

/// Set table[name] = value (with settable).
template<class T>
inline void table_set(lua_State* L, signed table, StringRef name, T value) {
	lua::push_value(L, name);
	lua::push_value(L, value);
	lua_settable(L, table);
}

/// Set top_of_stack[name] = value (with settable).
template<class T>
inline void table_set(lua_State* L, StringRef name, T value) {
	lua::table_set(L, -3, name, value);
}

/// Set table[name] = value (with rawset).
template<class T>
inline void table_set_raw(lua_State* L, signed table, StringRef name, T value) {
	lua::push_value(L, name);
	lua::push_value(L, value);
	lua_rawset(L, table);
}

/// Set top_of_stack[name] = value (with rawset).
template<class T>
inline void table_set_raw(lua_State* L, StringRef name, T value) {
	lua::table_set_raw(L, -3, name, value);
}

/// Fetch the value of table[name] and push it on the stack (with gettable).
inline void table_get(lua_State* L, signed table, StringRef name) {
	lua::push_value(L, name);
	lua_gettable(L, table);
}

/// Fetch the value of top_of_stack[name] and push it on the stack (with gettable).
inline void table_get(lua_State* L, StringRef name) {
	lua::table_get(L, -2, name);
}

/// Fetch the value of table[name] and push it on the stack (with rawget).
inline void table_get_raw(lua_State* L, signed table, StringRef name) {
	lua::push_value(L, name);
	lua_rawget(L, table);
}

/// Fetch the value of top_of_stack[name] and push it on the stack (with rawget).
inline void table_get_raw(lua_State* L, StringRef name) {
	lua::table_get_raw(L, -2, name);
}

/// Set table[index] = value (with settable).
template<class T>
inline void table_set_index(lua_State* L, signed table, signed index, T value) {
	lua::push_value(L, index);
	lua::push_value(L, value);
	lua_settable(L, table);
}

/// Set top_of_stack[index] = value (with settable).
template<class T>
inline void table_set_index(lua_State* L, signed index, T value) {
	lua::table_set_index(L, -3, index, value);
}

/// Set table[index] = value (with rawset).
template<class T>
inline void table_set_index_raw(lua_State* L, signed table, signed index, T value) {
	lua::push_value(L, value);
	lua_rawseti(L, table, index);
}

/// Set top_of_stack[index] = value (with rawset).
template<class T>
inline void table_set_index_raw(lua_State* L, signed index, T value) {
	lua::table_set_index_raw(L, -2, index, value);
}

/// Fetch the value of table[index] and push it on the stack (with rawget).
inline void table_get_index(lua_State* L, signed table, signed index) {
	lua::push_value(L, index);
	lua_gettable(L, table);
}

/// Fetch the value of top_of_stack[index] and push it on the stack (with rawget).
inline void table_get_index(lua_State* L, signed index) {
	lua::table_get_index(L, -2, index);
}

/// Fetch the value of table[index] and push it on the stack (with rawget).
inline void table_get_index_raw(lua_State* L, signed table, signed index) {
	lua_rawgeti(L, table, index);
}

/// Fetch the value of top_of_stack[index] and push it on the stack (with rawget).
inline void table_get_index_raw(lua_State* L, signed index) {
	lua::table_get_index_raw(L, -1, index);
}

/// Set table[name] = stack[value] (with settable).
inline void table_set_copy(lua_State* L, signed table, StringRef name, signed value) {
	lua::push_value(L, name);
	lua_pushvalue(L, value - 1);
	lua_settable(L, table);
}

/// Set top_of_stack[name] = stack[value] (with settable).
inline void table_set_copy(lua_State* L, StringRef name, signed value) {
	lua::table_set_copy(L, -3, name, value);
}

/// Set table[name] = stack[value] (with rawset).
inline void table_set_copy_raw(lua_State* L, signed table, StringRef name, signed value) {
	lua::push_value(L, name);
	lua_pushvalue(L, value - 1);
	lua_rawset(L, table);
}

/// Set top_of_stack[name] = stack[value] (with rawset).
inline void table_set_copy_raw(lua_State* L, StringRef name, signed value) {
	lua::table_set_copy_raw(L, -3, name, value);
}

/// Set table[index] = stack[value] (with settable).
inline void table_set_copy_index(lua_State* L, signed table, signed index, signed value) {
	lua::push_value(L, index);
	lua_pushvalue(L, value - 1);
	lua_settable(L, table);
}

/// Set top_of_stack[index] = stack[value] (with settable).
inline void table_set_copy_index(lua_State* L, signed index, signed value) {
	lua::table_set_copy_index(L, -3, index, value);
}

/// Set table[index] = stack[value] (with rawset).
inline void table_set_copy_index_raw(lua_State* L, signed table, signed index, signed value) {
	lua_pushvalue(L, value);
	lua_rawseti(L, table, index);
}

/// Set top_of_stack[index] = stack[value] (with rawset).
inline void table_set_copy_index_raw(lua_State* L, signed index, signed value) {
	lua::table_set_copy_index_raw(L, -2, index, value);
}

/// Register userdata.
///
/// If keep_metatable is true, the new metatable is kept at the top of the
/// stack.
template<class T>
inline void register_userdata(lua_State* L, LuaCFunction destroy, bool keep_metatable = false) {
	lua::table_get_raw(L, LUA_REGISTRYINDEX, "togo_class");
	TOGO_ASSERT(!lua_isnil(L, -1), "core was not registered");

	lua::table_get_raw(L, T::lua_metatable_name);
	TOGO_ASSERT(lua_isnil(L, -1), "class metatable was already registered");
	lua_pop(L, 1);

	lua_createtable(L, 0, 1);
	lua::table_set_copy_raw(L, "__index", -1);
	if (destroy) {
		lua::table_set_raw(L, "__gc", destroy);
	}

	// togo_class[T::lua_metatable_name] = metatable
	lua::table_set_copy_raw(L, -4, T::lua_metatable_name, -1);
	lua_remove(L, -2); // togo_class

	if (!keep_metatable) {
		lua_pop(L, 1);
	}
}

/// Push a new userdata to the stack and setup its metatable.
template<class T, class... P>
inline T* new_userdata(lua_State* L, P&&... p) {
	auto* ptr = lua_newuserdata(L, sizeof(T));
	TOGO_DEBUG_ASSERTE(ptr);

	lua::table_get_raw(L, LUA_REGISTRYINDEX, "togo_class");
	TOGO_ASSERT(!lua_isnil(L, -1), "core was not registered");
	lua::table_get_raw(L, T::lua_metatable_name);
	TOGO_ASSERT(!lua_isnil(L, -1), "class metatable was not registered");
	lua_setmetatable(L, -3);
	lua_pop(L, 1);

	return new(ptr) T(p...);
}

/// Get an argument from the stack as userdata (typed).
template<class T>
inline T* get_userdata(lua_State* L, signed narg, bool require = true) {
	{auto type = lua_type(L, narg);
	if (type != LUA_TUSERDATA && type != LUA_TNIL) {
		luaL_argerror(L, narg, "expected userdata");
	}}
	auto p = lua_touserdata(L, narg);
	if (require && !p) {
		luaL_argerror(L, narg, "value must be non-null");
	} else {
		if (!lua_getmetatable(L, narg)) {
			luaL_argerror(L, narg, "expected a metatable for userdata, but it has none");
		}
		lua::table_get_raw(L, LUA_REGISTRYINDEX, "togo_class");
		TOGO_ASSERT(!lua_isnil(L, -1), "core was not registered");
		lua::table_get_raw(L, T::lua_metatable_name);
		TOGO_ASSERT(!lua_isnil(L, -1), "class metatable was not registered");
		if (!lua_rawequal(L, -1, -3)) {
			luaL_argerror(L, narg, "userdata metatable does not match the expected one");
		}
		lua_pop(L, 3);
	}
	return static_cast<T*>(p);
}

/// Push a light userdata to the stack or nil if the pointer is null.
inline void push_lightuserdata(lua_State* L, void* p) {
	if (p) {
		lua_pushlightuserdata(L, p);
	} else {
		lua_pushnil(L);
	}
}

/// Get an argument from the stack as light userdata.
inline void* get_lightuserdata(lua_State* L, signed narg, bool require = true) {
	{auto type = lua_type(L, narg);
	if (type != LUA_TLIGHTUSERDATA && type != LUA_TNIL) {
		luaL_argerror(L, narg, "expected light userdata");
	}}
	auto p = lua_touserdata(L, narg);
	if (require && !p) {
		luaL_argerror(L, narg, "value must be non-null");
	}
	return p;
}

/// Get an argument from the stack as light userdata (typed).
///
/// This is an unchecked cast.
template<class T>
inline T* get_lightuserdata_typed(lua_State* L, signed narg, bool require = true) {
	return static_cast<T*>(get_lightuserdata(L, narg, require));
}

/// Get an argument from the stack as userdata or light userdata (typed).
///
/// This is an unchecked cast for light userdata.
template<class T>
inline T* get_pointer(lua_State* L, signed narg, bool require = true) {
	if (lua_type(L, narg) == LUA_TUSERDATA) {
		return get_userdata<T>(L, narg, require);
	} else {
		return get_lightuserdata_typed<T>(L, narg, require);
	}
}

/** @} */ // end of doc-group lib_core_lua

} // namespace lua
} // namespace togo
<commit_msg>lib/core/lua: push floating-point value as number, not integer!!<commit_after>#line 2 "togo/core/lua/lua.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief Scripting interface.
@ingroup lib_core_lua
*/

#pragma once

#include <togo/core/config.hpp>
#include <togo/core/types.hpp>
#include <togo/core/error/assert.hpp>
#include <togo/core/utility/traits.hpp>
#include <togo/core/utility/utility.hpp>
#include <togo/core/memory/types.hpp>
#include <togo/core/string/string.hpp>
#include <togo/core/lua/types.hpp>

extern "C" {
	#include <luajit-2.0/lua.h>
	#include <luajit-2.0/lauxlib.h>
	#include <luajit-2.0/lualib.h>
}

#include <togo/core/lua/lua.gen_interface>

namespace togo {
namespace lua {

/**
	@addtogroup lib_core_lua
	@{
*/

/// Push nil to the stack.
inline void push_value(lua_State* L, null_tag const) {
	lua_pushnil(L);
}

/// Push an integral value to the stack.
template<class T>
inline enable_if<is_integral<T>::value, void> push_value(lua_State* L, T value) {
	lua_pushinteger(L, value);
}

/// Get an argument from the stack as an integer.
inline LuaInt get_integer(lua_State* L, signed narg) {
	return luaL_checkinteger(L, narg);
}

/// Push a floating-point value to the stack.
template<class T>
inline enable_if<is_floating_point<T>::value, void> push_value(lua_State* L, T value) {
	lua_pushnumber(L, value);
}

/// Get an argument from the stack as an integer.
inline LuaFloat get_float(lua_State* L, signed narg) {
	return luaL_checknumber(L, narg);
}

// NB: Using template to avoid implicit cast from pointers and integrals.
/// Push a bool to the stack.
template<class T>
inline enable_if<is_same<T, bool>::value, void> push_value(lua_State* L, T value) {
	lua_pushboolean(L, value);
}

/// Get an argument from the stack as a boolean.
inline bool get_boolean(lua_State* L, signed narg) {
	luaL_checktype(L, narg, LUA_TBOOLEAN);
	return lua_toboolean(L, narg);
}

/// Push a string to the stack.
inline void push_value(lua_State* L, StringRef str) {
	lua_pushlstring(L, str.data ? str.data : "", unsigned_cast(str.size));
}

/// Get a string from the stack as a string reference.
inline StringRef get_string(lua_State* L, signed narg) {
	size_t size = 0;
	auto data = luaL_checklstring(L, narg, &size);
	return {data, static_cast<unsigned>(size)};
}

/// Push a C function to the stack.
inline void push_value(lua_State* L, LuaCFunction value) {
	lua_pushcfunction(L, value);
}

/// Get a C function from the stack.
inline LuaCFunction* get_cfunction(lua_State* L, signed narg) {
	luaL_checktype(L, narg, LUA_TFUNCTION);
	return lua_tocfunction(L, narg);
}

/// Set table[name] = value (with settable).
template<class T>
inline void table_set(lua_State* L, signed table, StringRef name, T value) {
	lua::push_value(L, name);
	lua::push_value(L, value);
	lua_settable(L, table);
}

/// Set top_of_stack[name] = value (with settable).
template<class T>
inline void table_set(lua_State* L, StringRef name, T value) {
	lua::table_set(L, -3, name, value);
}

/// Set table[name] = value (with rawset).
template<class T>
inline void table_set_raw(lua_State* L, signed table, StringRef name, T value) {
	lua::push_value(L, name);
	lua::push_value(L, value);
	lua_rawset(L, table);
}

/// Set top_of_stack[name] = value (with rawset).
template<class T>
inline void table_set_raw(lua_State* L, StringRef name, T value) {
	lua::table_set_raw(L, -3, name, value);
}

/// Fetch the value of table[name] and push it on the stack (with gettable).
inline void table_get(lua_State* L, signed table, StringRef name) {
	lua::push_value(L, name);
	lua_gettable(L, table);
}

/// Fetch the value of top_of_stack[name] and push it on the stack (with gettable).
inline void table_get(lua_State* L, StringRef name) {
	lua::table_get(L, -2, name);
}

/// Fetch the value of table[name] and push it on the stack (with rawget).
inline void table_get_raw(lua_State* L, signed table, StringRef name) {
	lua::push_value(L, name);
	lua_rawget(L, table);
}

/// Fetch the value of top_of_stack[name] and push it on the stack (with rawget).
inline void table_get_raw(lua_State* L, StringRef name) {
	lua::table_get_raw(L, -2, name);
}

/// Set table[index] = value (with settable).
template<class T>
inline void table_set_index(lua_State* L, signed table, signed index, T value) {
	lua::push_value(L, index);
	lua::push_value(L, value);
	lua_settable(L, table);
}

/// Set top_of_stack[index] = value (with settable).
template<class T>
inline void table_set_index(lua_State* L, signed index, T value) {
	lua::table_set_index(L, -3, index, value);
}

/// Set table[index] = value (with rawset).
template<class T>
inline void table_set_index_raw(lua_State* L, signed table, signed index, T value) {
	lua::push_value(L, value);
	lua_rawseti(L, table, index);
}

/// Set top_of_stack[index] = value (with rawset).
template<class T>
inline void table_set_index_raw(lua_State* L, signed index, T value) {
	lua::table_set_index_raw(L, -2, index, value);
}

/// Fetch the value of table[index] and push it on the stack (with rawget).
inline void table_get_index(lua_State* L, signed table, signed index) {
	lua::push_value(L, index);
	lua_gettable(L, table);
}

/// Fetch the value of top_of_stack[index] and push it on the stack (with rawget).
inline void table_get_index(lua_State* L, signed index) {
	lua::table_get_index(L, -2, index);
}

/// Fetch the value of table[index] and push it on the stack (with rawget).
inline void table_get_index_raw(lua_State* L, signed table, signed index) {
	lua_rawgeti(L, table, index);
}

/// Fetch the value of top_of_stack[index] and push it on the stack (with rawget).
inline void table_get_index_raw(lua_State* L, signed index) {
	lua::table_get_index_raw(L, -1, index);
}

/// Set table[name] = stack[value] (with settable).
inline void table_set_copy(lua_State* L, signed table, StringRef name, signed value) {
	lua::push_value(L, name);
	lua_pushvalue(L, value - 1);
	lua_settable(L, table);
}

/// Set top_of_stack[name] = stack[value] (with settable).
inline void table_set_copy(lua_State* L, StringRef name, signed value) {
	lua::table_set_copy(L, -3, name, value);
}

/// Set table[name] = stack[value] (with rawset).
inline void table_set_copy_raw(lua_State* L, signed table, StringRef name, signed value) {
	lua::push_value(L, name);
	lua_pushvalue(L, value - 1);
	lua_rawset(L, table);
}

/// Set top_of_stack[name] = stack[value] (with rawset).
inline void table_set_copy_raw(lua_State* L, StringRef name, signed value) {
	lua::table_set_copy_raw(L, -3, name, value);
}

/// Set table[index] = stack[value] (with settable).
inline void table_set_copy_index(lua_State* L, signed table, signed index, signed value) {
	lua::push_value(L, index);
	lua_pushvalue(L, value - 1);
	lua_settable(L, table);
}

/// Set top_of_stack[index] = stack[value] (with settable).
inline void table_set_copy_index(lua_State* L, signed index, signed value) {
	lua::table_set_copy_index(L, -3, index, value);
}

/// Set table[index] = stack[value] (with rawset).
inline void table_set_copy_index_raw(lua_State* L, signed table, signed index, signed value) {
	lua_pushvalue(L, value);
	lua_rawseti(L, table, index);
}

/// Set top_of_stack[index] = stack[value] (with rawset).
inline void table_set_copy_index_raw(lua_State* L, signed index, signed value) {
	lua::table_set_copy_index_raw(L, -2, index, value);
}

/// Register userdata.
///
/// If keep_metatable is true, the new metatable is kept at the top of the
/// stack.
template<class T>
inline void register_userdata(lua_State* L, LuaCFunction destroy, bool keep_metatable = false) {
	lua::table_get_raw(L, LUA_REGISTRYINDEX, "togo_class");
	TOGO_ASSERT(!lua_isnil(L, -1), "core was not registered");

	lua::table_get_raw(L, T::lua_metatable_name);
	TOGO_ASSERT(lua_isnil(L, -1), "class metatable was already registered");
	lua_pop(L, 1);

	lua_createtable(L, 0, 1);
	lua::table_set_copy_raw(L, "__index", -1);
	if (destroy) {
		lua::table_set_raw(L, "__gc", destroy);
	}

	// togo_class[T::lua_metatable_name] = metatable
	lua::table_set_copy_raw(L, -4, T::lua_metatable_name, -1);
	lua_remove(L, -2); // togo_class

	if (!keep_metatable) {
		lua_pop(L, 1);
	}
}

/// Push a new userdata to the stack and setup its metatable.
template<class T, class... P>
inline T* new_userdata(lua_State* L, P&&... p) {
	auto* ptr = lua_newuserdata(L, sizeof(T));
	TOGO_DEBUG_ASSERTE(ptr);

	lua::table_get_raw(L, LUA_REGISTRYINDEX, "togo_class");
	TOGO_ASSERT(!lua_isnil(L, -1), "core was not registered");
	lua::table_get_raw(L, T::lua_metatable_name);
	TOGO_ASSERT(!lua_isnil(L, -1), "class metatable was not registered");
	lua_setmetatable(L, -3);
	lua_pop(L, 1);

	return new(ptr) T(p...);
}

/// Get an argument from the stack as userdata (typed).
template<class T>
inline T* get_userdata(lua_State* L, signed narg, bool require = true) {
	{auto type = lua_type(L, narg);
	if (type != LUA_TUSERDATA && type != LUA_TNIL) {
		luaL_argerror(L, narg, "expected userdata");
	}}
	auto p = lua_touserdata(L, narg);
	if (require && !p) {
		luaL_argerror(L, narg, "value must be non-null");
	} else {
		if (!lua_getmetatable(L, narg)) {
			luaL_argerror(L, narg, "expected a metatable for userdata, but it has none");
		}
		lua::table_get_raw(L, LUA_REGISTRYINDEX, "togo_class");
		TOGO_ASSERT(!lua_isnil(L, -1), "core was not registered");
		lua::table_get_raw(L, T::lua_metatable_name);
		TOGO_ASSERT(!lua_isnil(L, -1), "class metatable was not registered");
		if (!lua_rawequal(L, -1, -3)) {
			luaL_argerror(L, narg, "userdata metatable does not match the expected one");
		}
		lua_pop(L, 3);
	}
	return static_cast<T*>(p);
}

/// Push a light userdata to the stack or nil if the pointer is null.
inline void push_lightuserdata(lua_State* L, void* p) {
	if (p) {
		lua_pushlightuserdata(L, p);
	} else {
		lua_pushnil(L);
	}
}

/// Get an argument from the stack as light userdata.
inline void* get_lightuserdata(lua_State* L, signed narg, bool require = true) {
	{auto type = lua_type(L, narg);
	if (type != LUA_TLIGHTUSERDATA && type != LUA_TNIL) {
		luaL_argerror(L, narg, "expected light userdata");
	}}
	auto p = lua_touserdata(L, narg);
	if (require && !p) {
		luaL_argerror(L, narg, "value must be non-null");
	}
	return p;
}

/// Get an argument from the stack as light userdata (typed).
///
/// This is an unchecked cast.
template<class T>
inline T* get_lightuserdata_typed(lua_State* L, signed narg, bool require = true) {
	return static_cast<T*>(get_lightuserdata(L, narg, require));
}

/// Get an argument from the stack as userdata or light userdata (typed).
///
/// This is an unchecked cast for light userdata.
template<class T>
inline T* get_pointer(lua_State* L, signed narg, bool require = true) {
	if (lua_type(L, narg) == LUA_TUSERDATA) {
		return get_userdata<T>(L, narg, require);
	} else {
		return get_lightuserdata_typed<T>(L, narg, require);
	}
}

/** @} */ // end of doc-group lib_core_lua

} // namespace lua
} // namespace togo
<|endoftext|>


<commit_before>//
//  tokenizer.cpp
//  koberi-c
//
//  Created by Filip Peterek on 31/10/2016.
//  Copyright © 2016 Filip Peterek. All rights reserved.
//

#include "tokenizer.hpp"

Tokenizer::Tokenizer(std::vector<token> & vectorRef) : _tokens(vectorRef) /* Call the reference constructor */ {

}

void Tokenizer::openFile(const std::string & filename) {

    _input.open(filename);
    if (not _input) { throw file_not_opened(filename); }

    // _filename = filename; /* Pointless now, but it might be necessary in the future */

}

void Tokenizer::readLine() {

    std::getline(_input, _line);
    _lineLen = _line.length();

}

void Tokenizer::identifierCheck() {

    std::string str(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
    ++_iter;

    while ( syntax::isValidIdChar(_line[_iter]) or syntax::isNum(_line[_iter]) ) {

        str += std::string(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
        ++_iter;

    }

    _tokens.emplace_back(tokType::id, str);

}

void Tokenizer::operatorCheck() {

    std::string str(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
    ++_iter;

    while ( syntax::isOperatorChar(_line[_iter]) ) {

        str += std::string(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
        ++_iter;

    }

    if ( syntax::isOperator(str) ) {

        _tokens.emplace_back(tokType::id, str);

    }
    else {

        throw invalid_operator(str);

    }

}

void Tokenizer::numberLiteral() {

    std::string str(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
    ++_iter;

    bool isNum = false;

    while ( syntax::isNum(_line[_iter]) or (( _line[_iter] == '.' ) and not isNum) ) {

        if (_line[_iter] == '.' and isNum == false) { isNum = true; }
        str += std::string(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
        ++_iter;

    }

    if (str.back() == '.') { throw unexpected_token('.'); }

    if (isNum) {
        _tokens.emplace_back(tokType::numLit, str);
    } else {
        _tokens.emplace_back(tokType::intLit, str);
    }

}

void Tokenizer::strLiteral() {

    std::string str;
    bool isEscape = false;

    ++_iter; /* First " character */

    while ( _line[_iter] != '"' or isEscape ) {

        if ( _line[_iter] == '\\' ) {

            isEscape = not isEscape;

            str += "\\";
            ++_iter;
            if (_iter >= _lineLen) { throw missing_token('"'); }

        }
        else {

            isEscape = false;

            str += std::string(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
            ++_iter;
            if (_iter >= _lineLen) { throw missing_token('"'); }

        }

    }

    ++_iter; /* Last " character */
    _tokens.emplace_back(tokType::strLit, str);

}

void Tokenizer::parseLine() {

    for (_iter = 0; _iter < _lineLen; /* Don't increment here, iter is incremented inside loop */) {

        /* Check for single line comment, if found, break out of loop  */
        /* The content of a comment is none of the compiler's bussines */

        if ( _line[_iter] == ';' ) {  break;  }

        /* Ignore whitespace, it's not important anymore, just increment iterator */

        else if ( syntax::isWhiteSpace(_line[_iter]) ) {  ++_iter;  }

        /* Check for brackets */

        else if ( _line[_iter] == '[' ) {

            _tokens.emplace_back( tokType::openingBra, std::string("[") );
            ++_iter;

        }
        else if ( _line[_iter] == ']' ) {

            _tokens.emplace_back( tokType::closingBra, std::string("]") );
            ++_iter;

        }

        /* Check for parenthesis */

        else if ( _line[_iter] == '(' ) {

            _tokens.emplace_back( tokType::openingPar, std::string("(") );
            ++_iter;

        }
        else if ( _line[_iter] == ')' ) {

            _tokens.emplace_back(tokType::closingPar, std::string(")") );
            ++_iter;

        }

        /* Check for an identifier */

        else if ( syntax::isValidIdChar(_line[_iter]) ) {  identifierCheck();  }

        /* Check for a num or flt literal */

        else if ( syntax::isNum(_line[_iter]) or _line[_iter] == '-' ) {  numberLiteral();  }

        /* Check for operator */

        else if ( syntax::isOperatorChar(_line[_iter]) ) {  operatorCheck();  }

        /* Check for a str literal */

        else if ( _line[_iter] == '"' ) {  strLiteral();  }

        else {  throw unexpected_token(_line[_iter]);  }

    } /* for */

} /* parseLine() */

void Tokenizer::tokenizeFile(const std::string & filename) {

    openFile(filename);

    while ( not _input.eof() ) {

        readLine();

#ifdef PRINT_LINE
        print(_line);
#endif

        parseLine();

    }

}
<commit_msg>Integer literals are now compiled to long long literals.<commit_after>//
//  tokenizer.cpp
//  koberi-c
//
//  Created by Filip Peterek on 31/10/2016.
//  Copyright © 2016 Filip Peterek. All rights reserved.
//

#include "tokenizer.hpp"

Tokenizer::Tokenizer(std::vector<token> & vectorRef) : _tokens(vectorRef) /* Call the reference constructor */ {

}

void Tokenizer::openFile(const std::string & filename) {

    _input.open(filename);
    if (not _input) { throw file_not_opened(filename); }

    // _filename = filename; /* Pointless now, but it might be necessary in the future */

}

void Tokenizer::readLine() {

    std::getline(_input, _line);
    _lineLen = _line.length();

}

void Tokenizer::identifierCheck() {

    std::string str(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
    ++_iter;

    while ( syntax::isValidIdChar(_line[_iter]) or syntax::isNum(_line[_iter]) ) {

        str += std::string(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
        ++_iter;

    }

    _tokens.emplace_back(tokType::id, str);

}

void Tokenizer::operatorCheck() {

    std::string str(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
    ++_iter;

    while ( syntax::isOperatorChar(_line[_iter]) ) {

        str += std::string(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
        ++_iter;

    }

    if ( syntax::isOperator(str) ) {

        _tokens.emplace_back(tokType::id, str);

    }
    else {

        throw invalid_operator(str);

    }

}

void Tokenizer::numberLiteral() {

    std::string str(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
    ++_iter;

    bool isNum = false;

    while ( syntax::isNum(_line[_iter]) or (( _line[_iter] == '.' ) and not isNum) ) {

        if (_line[_iter] == '.' and isNum == false) { isNum = true; }
        str += std::string(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
        ++_iter;

    }

    if (str.back() == '.') { throw unexpected_token('.'); }

    if (isNum) {
        _tokens.emplace_back(tokType::numLit, str);
    } else {
        _tokens.emplace_back(tokType::intLit, str + "ll");
    }

}

void Tokenizer::strLiteral() {

    std::string str;
    bool isEscape = false;

    ++_iter; /* First " character */

    while ( _line[_iter] != '"' or isEscape ) {

        if ( _line[_iter] == '\\' ) {

            isEscape = not isEscape;

            str += "\\";
            ++_iter;
            if (_iter >= _lineLen) { throw missing_token('"'); }

        }
        else {

            isEscape = false;

            str += std::string(1, _line[_iter]); /* std::string constructor(repeat: int, character: char) */
            ++_iter;
            if (_iter >= _lineLen) { throw missing_token('"'); }

        }

    }

    ++_iter; /* Last " character */
    _tokens.emplace_back(tokType::strLit, str);

}

void Tokenizer::parseLine() {

    for (_iter = 0; _iter < _lineLen; /* Don't increment here, iter is incremented inside loop */) {

        /* Check for single line comment, if found, break out of loop  */
        /* The content of a comment is none of the compiler's bussines */

        if ( _line[_iter] == ';' ) {  break;  }

        /* Ignore whitespace, it's not important anymore, just increment iterator */

        else if ( syntax::isWhiteSpace(_line[_iter]) ) {  ++_iter;  }

        /* Check for brackets */

        else if ( _line[_iter] == '[' ) {

            _tokens.emplace_back( tokType::openingBra, std::string("[") );
            ++_iter;

        }
        else if ( _line[_iter] == ']' ) {

            _tokens.emplace_back( tokType::closingBra, std::string("]") );
            ++_iter;

        }

        /* Check for parenthesis */

        else if ( _line[_iter] == '(' ) {

            _tokens.emplace_back( tokType::openingPar, std::string("(") );
            ++_iter;

        }
        else if ( _line[_iter] == ')' ) {

            _tokens.emplace_back(tokType::closingPar, std::string(")") );
            ++_iter;

        }

        /* Check for an identifier */

        else if ( syntax::isValidIdChar(_line[_iter]) ) {  identifierCheck();  }

        /* Check for a num or flt literal */

        else if ( syntax::isNum(_line[_iter]) or _line[_iter] == '-' ) {  numberLiteral();  }

        /* Check for operator */

        else if ( syntax::isOperatorChar(_line[_iter]) ) {  operatorCheck();  }

        /* Check for a str literal */

        else if ( _line[_iter] == '"' ) {  strLiteral();  }

        else {  throw unexpected_token(_line[_iter]);  }

    } /* for */

} /* parseLine() */

void Tokenizer::tokenizeFile(const std::string & filename) {

    openFile(filename);

    while ( not _input.eof() ) {

        readLine();

#ifdef PRINT_LINE
        print(_line);
#endif

        parseLine();

    }

}
<|endoftext|>


<commit_before>/*
    This file is part of KXForms.

    Copyright (c) 2006 Cornelius Schumacher <schumacher@kde.org>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "hints.h"

#include <common/qname.h>

#include <kdebug.h>
#include <QDomDocument>
#include <QDomElement>
#include <QTextDocument>

using namespace KXForms;

Hint::Hint()
{
}

Hint::Hint( const Reference &ref )
  : mRef( ref )
{
  if( !mRef.isAbsolute() && !mRef.toString().contains( '@' ) )
    mRef.fromString( '/' + mRef.toString() );
}

bool Hint::isValid() const
{
  return !mRef.isEmpty();
}

void Hint::setRef( const Reference &ref )
{
  mRef = ref;

  if( !mRef.isAbsolute() && !mRef.toString().contains( '@' ) )
    mRef.fromString( '/' + mRef.toString() );
}

Reference Hint::ref() const
{
  return mRef;
}

void Hint::setValue( Type key, const QString &value )
{
  if( mValues.contains( key ) ) {
    mValues.remove( key );
  }
  mValues[key] = value;
}

QString Hint::value( Type key) const
{
  return mValues[key];
}

bool Hint::hasValue( Type key) const
{
  return ( mValues.contains( key ) || mElements.contains( key ) );
}

void Hint::setEnumValue( const QString &value, const QString &replacement )
{
  mEnums.insert( value, replacement );
}

QString Hint::enumValue( const QString &value ) const
{
  if ( mEnums.contains( value ) ) return mEnums[ value ];
  else return QString();
}

void Hint::addElement( Type type, const QDomElement e )
{
  mElements[type].append( e.cloneNode().toElement() );
}

QList<QDomElement> Hint::elements( Type type) const
{
  return mElements[type];
}

QMap< Hint::Type, QList<QDomElement> > Hint::allElements() const
{
  return mElements;
}

void Hint::merge( const Hint &h )
{
  QMap<Type, QString> values = h.values();
  QMap<Type, QString>::iterator it;
  for( it = values.begin(); it != values.end(); ++it ) {
    setValue( it.key(), it.value() );
  }

  foreach( Type type, h.allElements().keys() ) {
      mElements[ type ] = h.elements( type );
  }
}

QString Hint::nameForType( Type t )
{
  QString s;
  switch( t ) {
    case Label:
      s = "label";
      break;
    case ListShowHeader:
      s = "listShowHeader";
      break;
    case ListHeader:
      s = "listHeader";
      break;
    case ListShowSearch:
      s = "listShowSearch";
      break;
    case ListItemLabel:
      s = "listItemLabel";
      break;
    case ListItemList:
      s = "listItemList";
      break;
    case Groups:
      s = "groups";
      break;
    case GroupReference:
      s = "groupReference";
      break;
    case Appearance:
      s = "appearance";
      break;
    case Position:
      s = "position";
      break;
    case LayoutStyle:
      s = "layoutStyle";
      break;
    case ReadOnly:
      s = "readonly";
      break;
    case InputType:
      s = "type";
      break;
    default:
      s = "unknown";
  }

  return s;
}

Hints::Hints()
{
}

bool Hints::parseFile( QFile &file )
{
  kDebug() << "---Hints::parseFile() " << file.fileName() << endl;

  QDomDocument doc;
  doc.setContent( &file );

  return parse( doc );
}

bool Hints::parseString( const QString &data )
{
  kDebug() << "---Hints::parseString() " << endl;

  QDomDocument doc;
  doc.setContent( data );

  return parse( doc );
}

bool Hints::parse( const QDomDocument &doc )
{
  QDomElement documentElement = doc.documentElement();
  QDomNode n;
  for( n = documentElement.firstChild(); !n.isNull(); n = n.nextSibling() ) {
    QDomElement e = n.toElement();
    parseHint( e );
  }

  kDebug() << "---Hints::parse() done" << endl;

  return true;
}

void Hints::parseHint( const QDomElement &element, const Reference &refPrefix )
{
//  kDebug() << "Hints::parseHint()" << element.tagName() << refPrefix << endl;

  Reference ref( element.attribute( "ref" ) );

//  kDebug() << "  REF:" << ref << endl;

  if ( ref.isEmpty() ) ref = refPrefix;
  if ( ref.isEmpty() ) {
    kDebug() << "Error: No reference attribute in hint tag." << endl;
    return;
  }
  if ( !refPrefix.isEmpty() && ref.isRelative() ) {
    ref = refPrefix + ref;
  }

  Hint hint( ref );

//  kDebug() << "Hints::parseHint()" << ref << endl;

  QDomNode n;
  for( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
    QDomElement e = n.toElement();
    QName name = e.tagName();
    if ( name.localName() == "enum" ) {
      hint.setEnumValue( e.attribute( "value" ), contentAsString( e ) );
    } else if (name.localName() == "label" ) {
      hint.setValue( Hint::Label, contentAsString( e ) );
    } else if (name.localName() == "listHeader" ) {
      hint.setValue( Hint::ListHeader, contentAsString( e ) );
    } else if (name.localName() == "listSearch" ) {
      hint.setValue( Hint::ListShowSearch, contentAsString( e ) );
    } else if (name.localName() == "listItemLabels" ) {
      QDomNode child = n.firstChild();
      while( !child.isNull() ) {
        if( child.nodeName() == "listItemLabel" ) {
          QDomElement e = child.toElement();
          if( !e.isNull() )
            hint.addElement( Hint::ListItemLabel, e );
        }
        child = child.nextSibling();
      }
    } else if (name.localName() == "listItemList" ) {
      hint.setValue( Hint::ListItemList, contentAsString( e ) );
    } else if (name.localName() == "groupRef" ) {
      hint.setValue( Hint::GroupReference, contentAsString( e ) );
    } else if (name.localName() == "appearance" ) {
      hint.setValue( Hint::Appearance, contentAsString( e ) );
    } else if (name.localName() == "layoutstyle" ) {
      hint.setValue( Hint::LayoutStyle, contentAsString( e ) );
    } else if (name.localName() == "position" ) {
      QDomNode child = n.firstChild();
      while( !child.isNull() ) {
        QDomElement e = child.toElement();
        if( !e.isNull() )
          hint.addElement( Hint::Position, e );
        child = child.nextSibling();
      }
    } else if (name.localName() == "groups" ) {
      QDomNode child = n.firstChild();
      while( !child.isNull() ) {
        if( child.nodeName() == "group" ) {
          QDomElement e = child.toElement();
          if( !e.isNull() )
            hint.addElement( Hint::Groups, e );
        }
        child = child.nextSibling();
      }
    } else if (name.localName() == "listShowHeader" ) {
      hint.setValue( Hint::ListShowHeader, contentAsString( e ) );
    } else if (name.localName() == "readonly" ) {
      hint.setValue( Hint::ReadOnly, contentAsString( e ) );
    } else if (name.localName() == "type" ) {
      hint.setValue( Hint::InputType, contentAsString( e ) );
    } else {
      kDebug() << "Unknown hint type: " << name.localName() << endl;
    }
  }

  mHints[ ref.toString() ] = hint;
}

QString Hints::toXml()
{
  QString xml;
  xml = "<ugh>\n";

  Hint::List theHints = hints();
  foreach( Hint h, theHints) {
    xml.append( QString( "  <hint ref=\"%1\">\n" ).arg( h.ref().toString() ) );

    QMap<Hint::Type, QString>::iterator it;
    QMap<Hint::Type, QString> values = h.values();
    for( it = values.begin(); it != values.end(); ++it ) {
      xml.append( QString( "    <%1>%2</%1>\n" ).arg( Hint::nameForType( it.key() ), it.value() ) );
    }

    QMap< Hint::Type, QList<QDomElement> >::iterator it2;
    QMap< Hint::Type, QList<QDomElement> > elements = h.allElements();
    for( it2 = elements.begin(); it2 != elements.end(); ++it2 ) {
      xml.append( QString( "    <%1>\n").arg( Hint::nameForType( it2.key() ) ) );

      foreach( QDomElement e, it2.value() ) {
        QString s;
        QTextStream stream( &s );
        e.save( stream, 6);
        xml.append( s );
      }

      xml.append( QString( "    </%1>\n").arg( Hint::nameForType( it2.key() ) ) );
    }
    xml.append( QString( "  </hint>\n") );
  }

  xml.append( "<ugh>" );

  kDebug() << k_funcinfo << xml << endl;

  return xml;
}

void Hints::merge( const Hints &hints )
{
  foreach( Hint h, hints.hints() ) {
    merge( h );
  }
}

void Hints::merge( const Hint &hint )
{
  if( mHints.contains( hint.ref().toString() ) )
    mHints[hint.ref().toString()].merge( hint );
  else
    insertHint( hint );
}

// TODO: Share with snippet from TextArea::loadData()
QString Hints::contentAsString( const QDomElement &element )
{
  QString txt;
  QTextStream ts( &txt, QIODevice::WriteOnly );

  QDomNode n;
  for( n = element.firstChild(); ! n.isNull(); n = n.nextSibling() ) {
    n.save( ts, 0 );
  }

  if ( txt.endsWith( "\n" ) ) txt = txt.left( txt.length() - 1 );

  return txt;
}

Hint Hints::hint( const Reference &ref ) const
{
  // Try to find an exact match
  if( mHints.contains( ref.toString() ) )
    return mHints[ ref.toString() ];

  // Try to find a partial match if there was no exact one
  foreach( Hint h, mHints ) {
    if( ref.matches( h.ref(), false ) ) {
      return h;
    }
  }

  return Hint();
}

Hint::List Hints::hints() const
{
  Hint::List result;

  foreach( Hint h, mHints ) {
    result.append( h );
  }

  return result;
}

void Hints::extractHints( const Schema::Document &schemaDocument )
{
  extractHints( schemaDocument.annotations() );

  foreach( Schema::Element e, schemaDocument.elements() ) {
    extractHints( e.annotations(), e.identifier() );
  }
  foreach( Schema::Attribute a, schemaDocument.attributes() ) {
    extractHints( a.annotations(), a.identifier() );
  }
}

void Hints::extractHints( const QList<QDomElement> &annotations,
  const Reference &refPrefix )
{
  foreach( QDomElement element, annotations ) {
    for( QDomElement e = element.firstChildElement(); !e.isNull();
         e = e.nextSiblingElement() ) {
      QName name = e.tagName();
      if ( name.localName() == "hint" ) {
        parseHint( e, refPrefix );
      }
    }
  }
}

void Hints::insertHint( const Hint &hint )
{
  mHints[ hint.ref().toString() ] = hint;
}

QString Hints::toRichText() const
{
  QString s;

  foreach( Hint h, mHints ) {
    s += QString( "%1
" ).arg( h.ref().toString() );

    QMap<Hint::Type, QString> values = h.values();
    foreach( Hint::Type t, values.keys() ) {
      s += QString( "   %1: \"%2\"
" ).arg( Hint::nameForType( t ), values[t] );
    }
    QMap< Hint::Type, QList<QDomElement> > elementValues = h.allElements();
    foreach( Hint::Type t, elementValues.keys() ) {
      QList<QDomElement> list = elementValues[t];
      foreach( QDomElement e, list ) {
        QString tmp;
        QTextStream stream( &tmp );
        e.save( stream, 0 );
        s += QString( "   %1: \"%2\"
" ).arg( Hint::nameForType( t ), Qt::escape( tmp.simplified() ) );
      }
    }
  }
  s = QString("<qt>Hints:
%1</qt>").arg( s );
  return s;
}

void Hints::dump() const
{
  kDebug() << "---Hints::dump()" << endl;
  foreach( Hint h, mHints ) {
    kDebug() << "HINT:" << h.ref().toString() << endl;
  }
  kDebug() << "---Hints::dump() done" << endl << endl;
}
<commit_msg>Fix the saving of some hints.<commit_after>/*
    This file is part of KXForms.

    Copyright (c) 2006 Cornelius Schumacher <schumacher@kde.org>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "hints.h"

#include <common/qname.h>

#include <kdebug.h>
#include <QDomDocument>
#include <QDomElement>
#include <QTextDocument>

using namespace KXForms;

Hint::Hint()
{
}

Hint::Hint( const Reference &ref )
  : mRef( ref )
{
  if( !mRef.isAbsolute() && !mRef.toString().contains( '@' ) )
    mRef.fromString( '/' + mRef.toString() );
}

bool Hint::isValid() const
{
  return !mRef.isEmpty();
}

void Hint::setRef( const Reference &ref )
{
  mRef = ref;

  if( !mRef.isAbsolute() && !mRef.toString().contains( '@' ) )
    mRef.fromString( '/' + mRef.toString() );
}

Reference Hint::ref() const
{
  return mRef;
}

void Hint::setValue( Type key, const QString &value )
{
  if( mValues.contains( key ) ) {
    mValues.remove( key );
  }
  mValues[key] = value;
}

QString Hint::value( Type key) const
{
  return mValues[key];
}

bool Hint::hasValue( Type key) const
{
  return ( mValues.contains( key ) || mElements.contains( key ) );
}

void Hint::setEnumValue( const QString &value, const QString &replacement )
{
  mEnums.insert( value, replacement );
}

QString Hint::enumValue( const QString &value ) const
{
  if ( mEnums.contains( value ) ) return mEnums[ value ];
  else return QString();
}

void Hint::addElement( Type type, const QDomElement e )
{
  mElements[type].append( e.cloneNode().toElement() );
}

QList<QDomElement> Hint::elements( Type type) const
{
  return mElements[type];
}

QMap< Hint::Type, QList<QDomElement> > Hint::allElements() const
{
  return mElements;
}

void Hint::merge( const Hint &h )
{
  QMap<Type, QString> values = h.values();
  QMap<Type, QString>::iterator it;
  for( it = values.begin(); it != values.end(); ++it ) {
    setValue( it.key(), it.value() );
  }

  foreach( Type type, h.allElements().keys() ) {
      mElements[ type ] = h.elements( type );
  }
}

QString Hint::nameForType( Type t )
{
  QString s;
  switch( t ) {
    case Label:
      s = "label";
      break;
    case ListShowHeader:
      s = "listShowHeader";
      break;
    case ListHeader:
      s = "listHeader";
      break;
    case ListShowSearch:
      s = "listShowSearch";
      break;
    case ListItemLabel:
      s = "listItemLabel";
      break;
    case ListItemList:
      s = "listItemList";
      break;
    case Groups:
      s = "groups";
      break;
    case GroupReference:
      s = "groupRef";
      break;
    case Appearance:
      s = "appearance";
      break;
    case Position:
      s = "position";
      break;
    case LayoutStyle:
      s = "layoutStyle";
      break;
    case ReadOnly:
      s = "readonly";
      break;
    case InputType:
      s = "type";
      break;
    default:
      s = "unknown";
  }

  return s;
}

Hints::Hints()
{
}

bool Hints::parseFile( QFile &file )
{
  kDebug() << "---Hints::parseFile() " << file.fileName() << endl;

  QDomDocument doc;
  doc.setContent( &file );

  return parse( doc );
}

bool Hints::parseString( const QString &data )
{
  kDebug() << "---Hints::parseString() " << endl;

  QDomDocument doc;
  doc.setContent( data );

  return parse( doc );
}

bool Hints::parse( const QDomDocument &doc )
{
  QDomElement documentElement = doc.documentElement();
  QDomNode n;
  for( n = documentElement.firstChild(); !n.isNull(); n = n.nextSibling() ) {
    QDomElement e = n.toElement();
    parseHint( e );
  }

  kDebug() << "---Hints::parse() done" << endl;

  return true;
}

void Hints::parseHint( const QDomElement &element, const Reference &refPrefix )
{
//  kDebug() << "Hints::parseHint()" << element.tagName() << refPrefix << endl;

  Reference ref( element.attribute( "ref" ) );

//  kDebug() << "  REF:" << ref << endl;

  if ( ref.isEmpty() ) ref = refPrefix;
  if ( ref.isEmpty() ) {
    kDebug() << "Error: No reference attribute in hint tag." << endl;
    return;
  }
  if ( !refPrefix.isEmpty() && ref.isRelative() ) {
    ref = refPrefix + ref;
  }

  Hint hint( ref );

//  kDebug() << "Hints::parseHint()" << ref << endl;

  QDomNode n;
  for( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
    QDomElement e = n.toElement();
    QName name = e.tagName();
    if ( name.localName() == "enum" ) {
      hint.setEnumValue( e.attribute( "value" ), contentAsString( e ) );
    } else if (name.localName() == "label" ) {
      hint.setValue( Hint::Label, contentAsString( e ) );
    } else if (name.localName() == "listHeader" ) {
      hint.setValue( Hint::ListHeader, contentAsString( e ) );
    } else if (name.localName() == "listSearch" ) {
      hint.setValue( Hint::ListShowSearch, contentAsString( e ) );
    } else if (name.localName() == "listItemLabels" ) {
      QDomNode child = n.firstChild();
      while( !child.isNull() ) {
        if( child.nodeName() == "listItemLabel" ) {
          QDomElement e = child.toElement();
          if( !e.isNull() )
            hint.addElement( Hint::ListItemLabel, e );
        }
        child = child.nextSibling();
      }
    } else if (name.localName() == "listItemList" ) {
      hint.setValue( Hint::ListItemList, contentAsString( e ) );
    } else if (name.localName() == "groupRef" ) {
      hint.setValue( Hint::GroupReference, contentAsString( e ) );
    } else if (name.localName() == "appearance" ) {
      hint.setValue( Hint::Appearance, contentAsString( e ) );
    } else if (name.localName() == "layoutStyle" ) {
      hint.setValue( Hint::LayoutStyle, contentAsString( e ) );
    } else if (name.localName() == "position" ) {
      QDomNode child = n.firstChild();
      while( !child.isNull() ) {
        QDomElement e = child.toElement();
        if( !e.isNull() )
          hint.addElement( Hint::Position, e );
        child = child.nextSibling();
      }
    } else if (name.localName() == "groups" ) {
      QDomNode child = n.firstChild();
      while( !child.isNull() ) {
        if( child.nodeName() == "group" ) {
          QDomElement e = child.toElement();
          if( !e.isNull() )
            hint.addElement( Hint::Groups, e );
        }
        child = child.nextSibling();
      }
    } else if (name.localName() == "listShowHeader" ) {
      hint.setValue( Hint::ListShowHeader, contentAsString( e ) );
    } else if (name.localName() == "readonly" ) {
      hint.setValue( Hint::ReadOnly, contentAsString( e ) );
    } else if (name.localName() == "type" ) {
      hint.setValue( Hint::InputType, contentAsString( e ) );
    } else {
      kDebug() << "Unknown hint type: " << name.localName() << endl;
    }
  }

  mHints[ ref.toString() ] = hint;
}

QString Hints::toXml()
{
  QString xml;
  xml = "<ugh>\n";

  Hint::List theHints = hints();
  foreach( Hint h, theHints) {
    xml.append( QString( "  <hint ref=\"%1\">\n" ).arg( h.ref().toString() ) );

    QMap<Hint::Type, QString>::iterator it;
    QMap<Hint::Type, QString> values = h.values();
    for( it = values.begin(); it != values.end(); ++it ) {
      xml.append( QString( "    <%1>%2</%1>\n" ).arg( Hint::nameForType( it.key() ), it.value() ) );
    }

    QMap< Hint::Type, QList<QDomElement> >::iterator it2;
    QMap< Hint::Type, QList<QDomElement> > elements = h.allElements();
    for( it2 = elements.begin(); it2 != elements.end(); ++it2 ) {
      xml.append( QString( "    <%1>\n").arg( Hint::nameForType( it2.key() ) ) );

      foreach( QDomElement e, it2.value() ) {
        QString s;
        QTextStream stream( &s );
        e.save( stream, 6);
        xml.append( s );
      }

      xml.append( QString( "    </%1>\n").arg( Hint::nameForType( it2.key() ) ) );
    }
    xml.append( QString( "  </hint>\n") );
  }

  xml.append( "<ugh>" );

  kDebug() << k_funcinfo << xml << endl;

  return xml;
}

void Hints::merge( const Hints &hints )
{
  foreach( Hint h, hints.hints() ) {
    merge( h );
  }
}

void Hints::merge( const Hint &hint )
{
  if( mHints.contains( hint.ref().toString() ) )
    mHints[hint.ref().toString()].merge( hint );
  else
    insertHint( hint );
}

// TODO: Share with snippet from TextArea::loadData()
QString Hints::contentAsString( const QDomElement &element )
{
  QString txt;
  QTextStream ts( &txt, QIODevice::WriteOnly );

  QDomNode n;
  for( n = element.firstChild(); ! n.isNull(); n = n.nextSibling() ) {
    n.save( ts, 0 );
  }

  if ( txt.endsWith( "\n" ) ) txt = txt.left( txt.length() - 1 );

  return txt;
}

Hint Hints::hint( const Reference &ref ) const
{
  // Try to find an exact match
  if( mHints.contains( ref.toString() ) )
    return mHints[ ref.toString() ];

  // Try to find a partial match if there was no exact one
  foreach( Hint h, mHints ) {
    if( ref.matches( h.ref(), false ) ) {
      return h;
    }
  }

  return Hint();
}

Hint::List Hints::hints() const
{
  Hint::List result;

  foreach( Hint h, mHints ) {
    result.append( h );
  }

  return result;
}

void Hints::extractHints( const Schema::Document &schemaDocument )
{
  extractHints( schemaDocument.annotations() );

  foreach( Schema::Element e, schemaDocument.elements() ) {
    extractHints( e.annotations(), e.identifier() );
  }
  foreach( Schema::Attribute a, schemaDocument.attributes() ) {
    extractHints( a.annotations(), a.identifier() );
  }
}

void Hints::extractHints( const QList<QDomElement> &annotations,
  const Reference &refPrefix )
{
  foreach( QDomElement element, annotations ) {
    for( QDomElement e = element.firstChildElement(); !e.isNull();
         e = e.nextSiblingElement() ) {
      QName name = e.tagName();
      if ( name.localName() == "hint" ) {
        parseHint( e, refPrefix );
      }
    }
  }
}

void Hints::insertHint( const Hint &hint )
{
  mHints[ hint.ref().toString() ] = hint;
}

QString Hints::toRichText() const
{
  QString s;

  foreach( Hint h, mHints ) {
    s += QString( "%1
" ).arg( h.ref().toString() );

    QMap<Hint::Type, QString> values = h.values();
    foreach( Hint::Type t, values.keys() ) {
      s += QString( "   %1: \"%2\"
" ).arg( Hint::nameForType( t ), values[t] );
    }
    QMap< Hint::Type, QList<QDomElement> > elementValues = h.allElements();
    foreach( Hint::Type t, elementValues.keys() ) {
      QList<QDomElement> list = elementValues[t];
      foreach( QDomElement e, list ) {
        QString tmp;
        QTextStream stream( &tmp );
        e.save( stream, 0 );
        s += QString( "   %1: \"%2\"
" ).arg( Hint::nameForType( t ), Qt::escape( tmp.simplified() ) );
      }
    }
  }
  s = QString("<qt>Hints:
%1</qt>").arg( s );
  return s;
}

void Hints::dump() const
{
  kDebug() << "---Hints::dump()" << endl;
  foreach( Hint h, mHints ) {
    kDebug() << "HINT:" << h.ref().toString() << endl;
  }
  kDebug() << "---Hints::dump() done" << endl << endl;
}
<|endoftext|>


<commit_before>/* This file is part of the KDE project
   Copyright (C) 2003-2005 Hamish Rodda <rodda@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

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

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "cursor.h"

#include "range.h"

using namespace KTextEditor;

Cursor::Cursor( )
  : m_line(0)
  , m_column(0)
  , m_range(0L)
{
}

Cursor::Cursor( int _line, int _column )
  : m_line(_line)
  , m_column(_column)
  , m_range(0L)
{
}

Cursor::Cursor(const Cursor& copy)
  : m_line(copy.line())
  , m_column(copy.column())
  , m_range(0L)
{
}

bool Cursor::isValid() const
{
  return m_line >= 0 && m_column >= 0;
}

Cursor Cursor::invalid( )
{
  return Cursor (-1,-1);
}

Cursor Cursor::start()
{
  return Cursor (0, 0);
}

int Cursor::line() const
{
  return m_line;
}

void Cursor::setLine( int line )
{
  if (line == this->line())
    return;

  Cursor old = *this;

  m_line = line;

  cursorChangedDirectly(old);
}

int Cursor::column() const
{
    return m_column;
}

void Cursor::setColumn( int column )
{
  if (column == this->column())
    return;

  Cursor old = *this;

  m_column = column;

  cursorChangedDirectly(old);
}

void Cursor::setPosition( const Cursor & pos )
{
  if (pos == *this)
    return;

  Cursor old = *this;

  m_line = pos.line();
  m_column = pos.column();

  cursorChangedDirectly(old);
}

bool Cursor::isSmartCursor( ) const
{
  return false;
}

void Cursor::setPosition(int line, int column)
{
    setPosition(Cursor(line, column));
}

void Cursor::position (int &_line, int &_column) const
{
  _line = line(); _column = column();
}

Range* Cursor::range() const
{
    return m_range;
}

Cursor::~ Cursor( )
{
}

void Cursor::setRange( Range * range )
{
  m_range = range;
}

void KTextEditor::Cursor::cursorChangedDirectly(const Cursor& from)
{
  if (m_range) {
    if (this == &m_range->start())
      m_range->rangeChanged(this, Range(from, m_range->end()));
    else
      m_range->rangeChanged(this, Range(m_range->start(), from));
  }
}

bool KTextEditor::Cursor::atStartOfLine( ) const
{
  return m_column == 0;
}

bool KTextEditor::Cursor::atStartOfDocument( ) const
{
  return line() == 0 && m_column == 0;
}

SmartCursor * KTextEditor::Cursor::toSmartCursor( ) const
{
  return 0L;
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<commit_msg>- lgplv2+:    goutte (   2 LOC): 485351    zwabel (   0 LOC): 701507,701504<commit_after>/* This file is part of the KDE project
   Copyright (C) 2003-2005 Hamish Rodda <rodda@kde.org>

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

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

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "cursor.h"

#include "range.h"

using namespace KTextEditor;

Cursor::Cursor( )
  : m_line(0)
  , m_column(0)
  , m_range(0L)
{
}

Cursor::Cursor( int _line, int _column )
  : m_line(_line)
  , m_column(_column)
  , m_range(0L)
{
}

Cursor::Cursor(const Cursor& copy)
  : m_line(copy.line())
  , m_column(copy.column())
  , m_range(0L)
{
}

bool Cursor::isValid() const
{
  return m_line >= 0 && m_column >= 0;
}

Cursor Cursor::invalid( )
{
  return Cursor (-1,-1);
}

Cursor Cursor::start()
{
  return Cursor (0, 0);
}

int Cursor::line() const
{
  return m_line;
}

void Cursor::setLine( int line )
{
  if (line == this->line())
    return;

  Cursor old = *this;

  m_line = line;

  cursorChangedDirectly(old);
}

int Cursor::column() const
{
    return m_column;
}

void Cursor::setColumn( int column )
{
  if (column == this->column())
    return;

  Cursor old = *this;

  m_column = column;

  cursorChangedDirectly(old);
}

void Cursor::setPosition( const Cursor & pos )
{
  if (pos == *this)
    return;

  Cursor old = *this;

  m_line = pos.line();
  m_column = pos.column();

  cursorChangedDirectly(old);
}

bool Cursor::isSmartCursor( ) const
{
  return false;
}

void Cursor::setPosition(int line, int column)
{
    setPosition(Cursor(line, column));
}

void Cursor::position (int &_line, int &_column) const
{
  _line = line(); _column = column();
}

Range* Cursor::range() const
{
    return m_range;
}

Cursor::~ Cursor( )
{
}

void Cursor::setRange( Range * range )
{
  m_range = range;
}

void KTextEditor::Cursor::cursorChangedDirectly(const Cursor& from)
{
  if (m_range) {
    if (this == &m_range->start())
      m_range->rangeChanged(this, Range(from, m_range->end()));
    else
      m_range->rangeChanged(this, Range(m_range->start(), from));
  }
}

bool KTextEditor::Cursor::atStartOfLine( ) const
{
  return m_column == 0;
}

bool KTextEditor::Cursor::atStartOfDocument( ) const
{
  return line() == 0 && m_column == 0;
}

SmartCursor * KTextEditor::Cursor::toSmartCursor( ) const
{
  return 0L;
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<|endoftext|>


<commit_before>// This #include statement was automatically added by the Spark IDE.
#include "application.h"
#include "libraries/AES/AES.h"
#include "libraries/AnalogSensor/AnalogSensor.h"
#include "libraries/DHT/DHT.h"
#include "libraries/HttpClient/HttpClient.h"

#define LOGGING;

SYSTEM_MODE(MANUAL);

IPAddress server(192,168,1,174);

DHT dht(D0, DHT22);
AnalogSensor light(A2, 1);
AnalogSensor pot(A4, 2);
String myIDStr = Spark.deviceID();
HttpClient http;
char path[64];

http_request_t request;
http_response_t response;
http_header_t headers[] = {
    { "Content-Type", "application/json" },
    { "Accept" , "application/json" },
    { NULL, NULL } // NOTE: Always terminate headers will NULL
};

unsigned char KEY[16] = "111111111111111";

void connect_wifi(){
    while(!WiFi.ready()){
        WiFi.connect();
        Serial.println("Connecting to Wifi...");
        delay(500);
    }
}

void setup() {
    Serial.begin(9600);
    light.init();
    pot.init();
    dht.begin();
    RGB.control(true);
    RGB.brightness(5);
    connect_wifi();
    Serial.println("running");
    Serial.println(request.path);
    String s_path = String("/node/"+myIDStr+"/sensors");
    s_path.toCharArray(path, 64);
    request.ip = server;
    request.hostname = NULL;
    request.port = 80;
    request.path = path;
}

char l_out[10];
char p_out[10];
char h_out[10];
char t_out[10];
char json_body[128];
unsigned int nextTime = 0;
void loop() {
    light.read();
    pot.read();
    if (nextTime > millis()) return;
    if(WiFi.ready()){
        sprintf(json_body, "{\"light\":%d , \"pot\":%d, \"temperature\":%.2f, \"humidity\":%.2f}", light.read(), pot.read(), dht.readTemperature(false), dht.readHumidity());
        Serial.println("Body: ");
        Serial.println(json_body);
        request.body = json_body;
        http.post(request, response, headers);
        Serial.print("Application>\tResponse status: ");
        Serial.println(response.status);
        Serial.print("Application>\tHTTP Response Body: ");
        Serial.println(response.body);
        nextTime = millis() + 100;
    }else{
        connect_wifi();
    }
}
<commit_msg>update to dev server<commit_after>// This #include statement was automatically added by the Spark IDE.
#include "application.h"
#include "libraries/AES/AES.h"
#include "libraries/AnalogSensor/AnalogSensor.h"
#include "libraries/DHT/DHT.h"
#include "libraries/HttpClient/HttpClient.h"

#define LOGGING;

SYSTEM_MODE(MANUAL);

IPAddress server(192,168,1,174);

DHT dht(D0, DHT22);
AnalogSensor light(A2, 1);
AnalogSensor pot(A4, 2);
String myIDStr = Spark.deviceID();
HttpClient http;
char path[64];

http_request_t request;
http_response_t response;
http_header_t headers[] = {
    { "Content-Type", "application/json" },
    { "Accept" , "application/json" },
    { NULL, NULL } // NOTE: Always terminate headers will NULL
};

unsigned char KEY[16] = "111111111111111";

void connect_wifi(){
    while(!WiFi.ready()){
        WiFi.connect();
        Serial.println("Connecting to Wifi...");
        delay(500);
    }
}

void setup() {
    Serial.begin(9600);
    light.init();
    pot.init();
    dht.begin();
    RGB.control(true);
    RGB.brightness(5);
    connect_wifi();
    Serial.println("running");
    Serial.println(request.path);
    String s_path = String("/node/"+myIDStr+"/sensors");
    s_path.toCharArray(path, 64);
    //request.ip = server;
    request.hostname = "crtlabsdev.realtors.org";
    request.port = 80;
    request.path = path;
}

char l_out[10];
char p_out[10];
char h_out[10];
char t_out[10];
char json_body[128];
unsigned int nextTime = 0;
void loop() {
    light.read();
    pot.read();
    if (nextTime > millis()) return;
    if(WiFi.ready()){
        sprintf(json_body, "{\"light\":%d , \"pot\":%d, \"temperature\":%.2f, \"humidity\":%.2f}", light.read(), pot.read(), dht.readTemperature(false), dht.readHumidity());
        Serial.println("Body: ");
        Serial.println(json_body);
        request.body = json_body;
        http.post(request, response, headers);
        Serial.print("Application>\tResponse status: ");
        Serial.println(response.status);
        Serial.print("Application>\tHTTP Response Body: ");
        Serial.println(response.body);
        nextTime = millis() + 100;
    }else{
        connect_wifi();
    }
}
<|endoftext|>