<commit_before>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

int main (int argc, char** argv) {

/*****
 begin camera setup
*****/

 CvCapture* capture = 0;
 int width, height;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream config_file (".config");

 if (config_file.is_open()) {
// does not support corrupted .config

  string line;
  getline(config_file, line);
  istringstream(line)>>width;
  getline(config_file, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  config_file.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream config_file_out(".config");
  config_file_out << width;
  config_file_out << "\n";
  config_file_out << height;
  config_file_out << "\n";
  config_file_out.close();
 }

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

/*****
 end camera setup
*****/

/*****
 filter setup
*****/

 Mat acbg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated background
 Mat acbg_m(256, 256, CV_8UC1, Scalar(0));
// accumulated background mask

 Mat acfg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated foreground
 Mat acfg_t(256, 256, CV_8UC3, Scalar(0));
// accumulated foreground threshold

 Mat img_256_p(256, 256, CV_8UC3, Scalar(0,0,0));
// previous image
 Mat haar_t_p(256, 256, CV_8UC1, Scalar(1));
// previous possible locations for mouth

/*****
 end filter setup
*****/

/*****
 misc
*****/

 unsigned long long times[100];
 for (int i=0; i<100; i++)
  times[i] = 0;

 int tracker1, tracker2, tracker3, tracker4;
 namedWindow("settings",1);
 createTrackbar("1","settings",&tracker1,100);
 createTrackbar("2","settings",&tracker2,100);
 createTrackbar("3","settings",&tracker3,100);
 createTrackbar("4","settings",&tracker4,100);

 unsigned long long timenow = getMilliseconds();

 bool keep_going = true;

 CascadeClassifier mouth_cascade;
 mouth_cascade.load("Mouth.xml");

/*****
 begin filter loop
*****/

 while (keep_going) {

  Mat image(cvQueryFrame(capture));
//  imshow("webcam", image);
// at some point preprocess by rotating according to OVR roll
// right now really annoying because of state variables

  Mat gray, img_256, gray_256;
  resize(image, img_256, Size(256, 256));
  cvtColor(image, gray, CV_RGB2GRAY);
  cvtColor(img_256, gray_256, CV_RGB2GRAY);

// this mask gets anything kind of dark (DK2) and dilates
// should work *great*
  Mat gr_m;
// gray mask
  equalizeHist(gray_256, gr_m);
  threshold(gr_m, gr_m, 215, 1, THRESH_BINARY);
  dilate(gr_m, gr_m, ellipticKernel(23));
  erode(gr_m, gr_m, ellipticKernel(45));

//  imshow("gray mask", gray_256.mul(1-gr_m));

  bitwise_or(acbg_m, gr_m, acbg_m);
//  imshow("accumulated bg mask", gray_256.mul(1-acbg_m));

// this mask watches for flow against accumulated bg
  Mat fl_m;
// flow mask
  absdiff(img_256, acbg, fl_m);
  cvtColor(fl_m, fl_m, CV_BGR2GRAY);
  fl_m = acbg_m.mul(fl_m);
  threshold(fl_m, fl_m, 45, 1, THRESH_BINARY_INV);
  erode(fl_m, fl_m, ellipticKernel(51));
//  imshow("flow mask", fl_m*255);

  Mat bg_m;
  bitwise_and(acbg_m, fl_m, bg_m);
  bitwise_or(gr_m, bg_m, bg_m);
//  imshow("bgm", bg_m*255);

// maybe do some morphological operations on bg_m?
// previously combined bg_m with its opening

// ugly way to compute:
// acbg = [acbg'.(1-bg_m)]+[((acbg'+img_256)/2).bg_m]
// find a nicer way later
// problem is masks are 1 channel while images are 3 channel

  Mat bg_m3;
  Mat tmp0[3];
  tmp0[0] = tmp0[1] = tmp0[2] = bg_m;
  merge(tmp0, 3, bg_m3);
//  imshow("bg_m3", bg_m3*255);
  acbg = acbg.mul(Scalar(1,1,1)-bg_m3) + (acbg/2+img_256/2).mul(bg_m3);
//  imshow("acbg", acbg);

//  imshow("bg mask", gray_256.mul(1-bg_m));

  Mat df_m;
// delta flow mask
  absdiff(img_256, img_256_p, df_m);
  cvtColor(df_m, df_m, CV_BGR2GRAY);
  int t1,t2;
  t1 = tracker1+1-(tracker1%2);
  if (t1<3) t1=3;
  if (t1>90) t1=91;
  t2 = tracker2+1-(tracker2%2);
  if (t2<3) t2=3;
  if (t2>90) t2=91;
  blur(df_m, df_m, Size(10, 10));
  threshold(df_m, df_m, tracker3, 1, THRESH_BINARY);

for (int j=0; j<tracker4; j++) {
  dilate(df_m, df_m, ellipticKernel(t1, t2));
  erode(df_m, df_m, ellipticKernel(t1, t2));
}

  imshow("delta flow mask", df_m*255);
  img_256_p = img_256.clone();

  Mat haar_m;
// bitwise_and(1 - bg_m, fg_m, haar_m);
  haar_m = 1 - bg_m;

// run haar classifier
  int scale = width/300;
  if (scale < 1)
   scale = 1;
// can't use 256x256 since haar isn't stretch invariant

  Mat thingy;
  resize(gray, thingy, Size(width/scale, height/scale));
  equalizeHist(thingy, thingy);
///////////////////
// need to change this after foreground stuff gets written

  vector<Rect> mouth_rects;
  resize(haar_m, haar_m, Size(width/scale, height/scale));

  thingy = thingy.mul(haar_m);
/////////////////

  mouth_cascade.detectMultiScale(thingy, mouth_rects, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  Mat rect_image(height, width, CV_8UC1, Scalar(0));

  for (size_t i=0; i<mouth_rects.size(); i++) {
   Rect scaled(mouth_rects[i].x*scale, mouth_rects[i].y*scale, mouth_rects[i].width*scale,mouth_rects[i].height*scale);
   Mat new_rect(height, width, CV_8UC1, Scalar(0));
   rectangle(new_rect, scaled, Scalar(1), CV_FILLED);
   rect_image += new_rect;
  }

  double min_val, max_val;
  minMaxLoc(rect_image, &min_val, &max_val);

// or maybe equalize? this whole thing needs to be rewritten
// with the new fg and temporal coherence ideas

  Mat rect_thresh;
  threshold(rect_image, rect_thresh, max_val*0.9, 1, THRESH_BINARY);
  imshow("mouth", rect_thresh.mul(gray));

/*
  Moments m = moments(rect_thresh, 1);
  circle(image, Point(m.m10/m.m00,m.m01/m.m00),20,Scalar(128),30);
  imshow("centroid", image);
*/

  keep_going = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}

<commit_msg>hacking<commit_after>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

int main (int argc, char** argv) {

/*****
 begin camera setup
*****/

 CvCapture* capture = 0;
 int width, height;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream config_file (".config");

 if (config_file.is_open()) {
// does not support corrupted .config

  string line;
  getline(config_file, line);
  istringstream(line)>>width;
  getline(config_file, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  config_file.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream config_file_out(".config");
  config_file_out << width;
  config_file_out << "\n";
  config_file_out << height;
  config_file_out << "\n";
  config_file_out.close();
 }

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

/*****
 end camera setup
*****/

/*****
 filter setup
*****/

 Mat acbg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated background
 Mat acbg_m(256, 256, CV_8UC1, Scalar(0));
// accumulated background mask

 Mat acfg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated foreground

 Mat img_256_p(256, 256, CV_8UC3, Scalar(0,0,0));
// previous image
 Mat haar_t_p(256, 256, CV_8UC1, Scalar(1));
// previous possible locations for mouth

/*****
 end filter setup
*****/

/*****
 misc
*****/

 unsigned long long times[100];
 for (int i=0; i<100; i++)
  times[i] = 0;

 int tracker1, tracker2, tracker3, tracker4;
 namedWindow("settings",1);
 createTrackbar("1","settings",&tracker1,100);
 createTrackbar("2","settings",&tracker2,100);
 createTrackbar("3","settings",&tracker3,100);
 createTrackbar("4","settings",&tracker4,100);

 unsigned long long timenow = getMilliseconds();

 bool keep_going = true;

 CascadeClassifier mouth_cascade;
 mouth_cascade.load("Mouth.xml");

/*****
 begin filter loop
*****/

 while (keep_going) {

  Mat image(cvQueryFrame(capture));
//  imshow("webcam", image);
// at some point preprocess by rotating according to OVR roll
// right now really annoying because of state variables

  Mat gray, img_256, gray_256;
  resize(image, img_256, Size(256, 256));
  cvtColor(image, gray, CV_RGB2GRAY);
  cvtColor(img_256, gray_256, CV_RGB2GRAY);

// this mask gets anything kind of dark (DK2) and dilates
// should work *great*
  Mat gr_m;
// gray mask
  equalizeHist(gray_256, gr_m);
  threshold(gr_m, gr_m, 215, 1, THRESH_BINARY);
  dilate(gr_m, gr_m, ellipticKernel(23));
  erode(gr_m, gr_m, ellipticKernel(45));

//  imshow("gray mask", gray_256.mul(1-gr_m));

  bitwise_or(acbg_m, gr_m, acbg_m);
//  imshow("accumulated bg mask", gray_256.mul(1-acbg_m));

// this mask watches for flow against accumulated bg
  Mat fl_m;
// flow mask
  absdiff(img_256, acbg, fl_m);
  cvtColor(fl_m, fl_m, CV_BGR2GRAY);
  fl_m = acbg_m.mul(fl_m);
  threshold(fl_m, fl_m, 45, 1, THRESH_BINARY_INV);
  erode(fl_m, fl_m, ellipticKernel(51));
//  imshow("flow mask", fl_m*255);

  Mat bg_m;
  bitwise_and(acbg_m, fl_m, bg_m);
  bitwise_or(gr_m, bg_m, bg_m);
//  imshow("bgm", bg_m*255);

// maybe do some morphological operations on bg_m?
// previously combined bg_m with its opening

// ugly way to compute:
// acbg = [acbg'.(1-bg_m)]+[((acbg'+img_256)/2).bg_m]
// find a nicer way later
// problem is masks are 1 channel while images are 3 channel

  Mat bg_m3;
  Mat tmp0[3];
  tmp0[0] = tmp0[1] = tmp0[2] = bg_m;
  merge(tmp0, 3, bg_m3);
//  imshow("bg_m3", bg_m3*255);
  acbg = acbg.mul(Scalar(1,1,1)-bg_m3) + (acbg/2+img_256/2).mul(bg_m3);
//  imshow("acbg", acbg);

//  imshow("bg mask", gray_256.mul(1-bg_m));

  Mat df_m;
// delta flow mask
  absdiff(img_256, img_256_p, df_m);
  cvtColor(df_m, df_m, CV_BGR2GRAY);
  blur(df_m, df_m, Size(10, 10));
  threshold(df_m, df_m, 5, 1, THRESH_BINARY);

  dilate(df_m, df_m, ellipticKernel(25, 25));
  erode(df_m, df_m, ellipticKernel(25, 25));

  imshow("delta flow mask", df_m*255);
  img_256_p = img_256.clone();

  Mat fg_m;
  bitwise_or(haar_t_p, df_m, fg_m);

  Mat haar_m;
  bitwise_and(1 - bg_m, fg_m, haar_m);

// run haar classifier
  int scale = width/300;
  if (scale < 1)
   scale = 1;
// can't use 256x256 since haar isn't stretch invariant

  Mat gray_haar;
  resize(gray, gray_haar, Size(width/scale, height/scale));
  equalizeHist(gray_haar, gray_haar);

  vector<Rect> mouth_rects;
  resize(haar_m, haar_m, Size(width/scale, height/scale));

  gray_haar = gray_haar.mul(haar_m);

  mouth_cascade.detectMultiScale(thingy, mouth_rects, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  Mat fg(height, width, CV_8UC1, Scalar(0));

  for (size_t i=0; i<mouth_rects.size(); i++) {
   Rect scaled(mouth_rects[i].x*scale, mouth_rects[i].y*scale, mouth_rects[i].width*scale,mouth_rects[i].height*scale);
   Mat new_rect(height, width, CV_8UC1, Scalar(0));
   rectangle(new_rect, scaled, Scalar(1), CV_FILLED);
   fg += new_rect;
  }

// or maybe equalize? this whole thing needs to be rewritten
// with the new fg and temporal coherence ideas

// very interesting idea:
// if nothing moved in some place over the past frame,
// and nothing was detected last frame, whatever is
// detected now is more likely to be bogus

  acfg = acfg*0.25 + fg;

  double min_val, max_val;
  minMaxLoc(fg, &min_val, &max_val);

  Mat rect_thresh;
  threshold(acfg, rect_thresh, max_val*0.9, 1, THRESH_BINARY);
  imshow("mouth", rect_thresh.mul(gray));

  threshold(acfg, haar_t_p, max_val*0.5, 1, THRESH_BINARY);

/*
  Moments m = moments(rect_thresh, 1);
  circle(image, Point(m.m10/m.m00,m.m01/m.m00),20,Scalar(128),30);
  imshow("centroid", image);
*/

  keep_going = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}

<|endoftext|>


<commit_before>#include <initializer_list>
#include <string>

#include <gtk/gtk.h>

namespace
{

void initAmount(GtkWidget* grid)
{
    GtkWidget* amount = gtk_entry_new();
    gtk_grid_attach(GTK_GRID(grid), amount, 0, 0, 1, 1);
}

void initUnit(GtkWidget* grid, int active, int top)
{
    GtkWidget* unitCombo = gtk_combo_box_text_new();
    std::initializer_list<std::string> units = {"inch",  "point", "twip",

                                                "m",     "cm",    "mm",
                                                "mm100",

                                                "emu"};
    for (const auto& unit : units)
        gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(unitCombo), nullptr,
                                  unit.c_str());
    gtk_combo_box_set_active(GTK_COMBO_BOX(unitCombo), active);
    gtk_grid_attach(GTK_GRID(grid), unitCombo, 1, top, 1, 1);
}

void initResult(GtkWidget* grid)
{
    GtkWidget* result = gtk_label_new("");
    gtk_label_set_selectable(GTK_LABEL(result), TRUE);
    gtk_grid_attach(GTK_GRID(grid), result, 0, 1, 1, 1);
}

void initConvert(GtkWidget* grid)
{
    GtkWidget* convert = gtk_button_new_with_label("Convert");
    gtk_grid_attach(GTK_GRID(grid), convert, 0, 2, 1, 1);
}

void initQuit(GtkWidget* grid)
{
    GtkWidget* quit = gtk_button_new_with_label("Quit");
    g_signal_connect(quit, "clicked", G_CALLBACK(gtk_main_quit), nullptr);
    gtk_grid_attach(GTK_GRID(grid), quit, 1, 2, 1, 1);
}

void initControls(GtkWidget* window)
{
    GtkWidget* grid = gtk_grid_new();
    initAmount(grid);
    initUnit(grid, 0, 0);
    initUnit(grid, 1, 1);
    initResult(grid);
    initConvert(grid);
    initQuit(grid);
    gtk_container_add(GTK_CONTAINER(window), grid);
}

} // anonymous namespace

int main(int argc, char** argv)
{
    gtk_init(&argc, &argv);
    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "gtktpconv");
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), nullptr);

    initControls(window);

    gtk_widget_show_all(window);

    gtk_main();

    return 0;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>gtktpconv: add actual convert() stub<commit_after>#include <initializer_list>
#include <string>

#include <gtk/gtk.h>

/// Hold references to all data needed to perform a conversion.
class Conversion
{
  public:
    GtkEntry* _amount;
    GtkComboBox* _from;
    GtkComboBox* _to;
    GtkLabel* _result;

    Conversion();
};

Conversion::Conversion()
    : _amount(nullptr), _from(nullptr), _to(nullptr), _result(nullptr)
{
}

namespace
{

void initAmount(GtkWidget* grid, Conversion& conversion)
{
    GtkWidget* amount = gtk_entry_new();
    conversion._amount = GTK_ENTRY(amount);
    gtk_grid_attach(GTK_GRID(grid), amount, 0, 0, 1, 1);
}

GtkComboBox* initUnit(GtkWidget* grid, int active, int top)
{
    GtkWidget* unitCombo = gtk_combo_box_text_new();
    std::initializer_list<std::string> units = {"inch",  "point", "twip",

                                                "m",     "cm",    "mm",
                                                "mm100",

                                                "emu"};
    for (const auto& unit : units)
        gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(unitCombo), nullptr,
                                  unit.c_str());
    gtk_combo_box_set_active(GTK_COMBO_BOX(unitCombo), active);
    gtk_grid_attach(GTK_GRID(grid), unitCombo, 1, top, 1, 1);
    return GTK_COMBO_BOX(unitCombo);
}

void initResult(GtkWidget* grid, Conversion& conversion)
{
    GtkWidget* result = gtk_label_new("");
    conversion._result = GTK_LABEL(result);
    gtk_label_set_selectable(conversion._result, TRUE);
    gtk_grid_attach(GTK_GRID(grid), result, 0, 1, 1, 1);
}

void convert(GtkWidget* /*widget*/, gpointer userData)
{
    Conversion* conversion = static_cast<Conversion*>(userData);
    // TODO
    (void)conversion;
}

void initConvert(GtkWidget* grid, Conversion& conversion)
{
    GtkWidget* convertButton = gtk_button_new_with_label("Convert");
    gtk_grid_attach(GTK_GRID(grid), convertButton, 0, 2, 1, 1);
    g_signal_connect(convertButton, "clicked", G_CALLBACK(convert),
                     &conversion);
}

void initQuit(GtkWidget* grid)
{
    GtkWidget* quit = gtk_button_new_with_label("Quit");
    g_signal_connect(quit, "clicked", G_CALLBACK(gtk_main_quit), nullptr);
    gtk_grid_attach(GTK_GRID(grid), quit, 1, 2, 1, 1);
}

void initControls(GtkWidget* window, Conversion& conversion)
{
    GtkWidget* grid = gtk_grid_new();
    initAmount(grid, conversion);
    conversion._from = initUnit(grid, 0, 0);
    conversion._to = initUnit(grid, 1, 1);
    initResult(grid, conversion);
    initConvert(grid, conversion);
    initQuit(grid);
    gtk_container_add(GTK_CONTAINER(window), grid);
}

} // anonymous namespace

int main(int argc, char** argv)
{
    gtk_init(&argc, &argv);
    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "gtktpconv");
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), nullptr);

    Conversion conversion;
    initControls(window, conversion);

    gtk_widget_show_all(window);

    gtk_main();

    return 0;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 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.
 *****************************************************************************/

/**
 * @file socket_can_client.cc
 * @brief the encapsulate call the api of socket can card according to
 *can_client.h interface
 **/

#include "modules/drivers/canbus/can_client/socket/socket_can_client_raw.h"

namespace apollo {
namespace drivers {
namespace canbus {
namespace can {

using apollo::common::ErrorCode;

bool SocketCanClientRaw::Init(const CANCardParameter &parameter) {
  if (!parameter.has_channel_id()) {
    AERROR << "Init CAN failed: parameter does not have channel id. The "
              "parameter is "
           << parameter.DebugString();
    return false;
  }

  port_ = parameter.channel_id();
  return true;
}

ErrorCode SocketCanClientRaw::Start() {
  if (is_started_) {
    return ErrorCode::OK;
  }
  struct sockaddr_can addr;
  struct ifreq ifr;

  // open device
  // guss net is the device minor number, if one card is 0,1
  // if more than one card, when install driver u can specify the minior id
  // int32_t ret = canOpen(net, pCtx->mode, txbufsize, rxbufsize, 0, 0,
  // &dev_handler_);
  if (port_ > MAX_CAN_PORT || port_ < 0) {
    AERROR << "can port number [" << port_ << "] is out of the range [0,"
           << MAX_CAN_PORT << "]";
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  dev_handler_ = socket(PF_CAN, SOCK_RAW, CAN_RAW);
  if (dev_handler_ < 0) {
    AERROR << "open device error code [" << dev_handler_ << "]: ";
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  // init config and state
  // 1. set receive message_id filter, ie white list
  struct can_filter filter[2048];
  for (int i = 0; i < 2048; ++i) {
    filter[i].can_id = 0x000 + i;
    filter[i].can_mask = CAN_SFF_MASK;
  }

  int ret = setsockopt(dev_handler_, SOL_CAN_RAW, CAN_RAW_FILTER, &filter,
                       sizeof(filter));
  if (ret < 0) {
    AERROR << "add receive msg id filter error code: " << ret;
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  // 2. enable reception of can frames.
  int enable = 1;
  ret = ::setsockopt(dev_handler_, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable,
                     sizeof(enable));
  if (ret < 0) {
    AERROR << "enable reception of can frame error code: " << ret;
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  // strcpy(ifr.ifr_name, "can0");
  std::strncpy(ifr.ifr_name, "can0", IFNAMSIZ);
  if (ioctl(dev_handler_, SIOCGIFINDEX, &ifr) < 0) {
    AERROR << "ioctl error";
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  // bind socket to network interface

  addr.can_family = AF_CAN;
  addr.can_ifindex = ifr.ifr_ifindex;
  ret = ::bind(dev_handler_, reinterpret_cast<struct sockaddr *>(&addr),
               sizeof(addr));

  if (ret < 0) {
    AERROR << "bind socket to network interface error code: " << ret;
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  is_started_ = true;
  return ErrorCode::OK;
}

void SocketCanClientRaw::Stop() {
  if (is_started_) {
    is_started_ = false;

    int ret = close(dev_handler_);
    if (ret < 0) {
      AERROR << "close error code:" << ret << ", " << GetErrorString(ret);
    } else {
      AINFO << "close socket can ok. port:" << port_;
    }
  }
}

// Synchronous transmission of CAN messages
ErrorCode SocketCanClientRaw::Send(const std::vector<CanFrame> &frames,
                                   int32_t *const frame_num) {
  CHECK_NOTNULL(frame_num);
  CHECK_EQ(frames.size(), static_cast<size_t>(*frame_num));

  if (!is_started_) {
    AERROR << "Nvidia can client has not been initiated! Please init first!";
    return ErrorCode::CAN_CLIENT_ERROR_SEND_FAILED;
  }
  for (size_t i = 0; i < frames.size() && i < MAX_CAN_SEND_FRAME_LEN; ++i) {
    send_frames_[i].can_id = frames[i].id;
    send_frames_[i].can_dlc = frames[i].len;
    std::memcpy(send_frames_[i].data, frames[i].data, frames[i].len);

    // Synchronous transmission of CAN messages
    int ret = write(dev_handler_, &send_frames_[i], sizeof(send_frames_[i]));
    if (ret <= 0) {
      AERROR << "send message failed, error code: " << ret;
      return ErrorCode::CAN_CLIENT_ERROR_BASE;
    }
  }

  return ErrorCode::OK;
}

// buf size must be 8 bytes, every time, we receive only one frame
ErrorCode SocketCanClientRaw::Receive(std::vector<CanFrame> *const frames,
                                      int32_t *const frame_num) {
  if (!is_started_) {
    AERROR << "Nvidia can client is not init! Please init first!";
    return ErrorCode::CAN_CLIENT_ERROR_RECV_FAILED;
  }

  if (*frame_num > MAX_CAN_RECV_FRAME_LEN || *frame_num < 0) {
    AERROR << "recv can frame num not in range[0, " << MAX_CAN_RECV_FRAME_LEN
           << "], frame_num:" << *frame_num;
    // TODO(Authors): check the difference of returning frame_num/error_code
    return ErrorCode::CAN_CLIENT_ERROR_FRAME_NUM;
  }

  for (int32_t i = 0; i < *frame_num && i < MAX_CAN_RECV_FRAME_LEN; ++i) {
    CanFrame cf;
    int ret = read(dev_handler_, &recv_frames_[i], sizeof(recv_frames_[i]));

    if (ret < 0) {
      AERROR << "receive message failed, error code: " << ret;
      return ErrorCode::CAN_CLIENT_ERROR_BASE;
    }
    cf.id = recv_frames_[i].can_id;
    cf.len = recv_frames_[i].can_dlc;
    std::memcpy(cf.data, recv_frames_[i].data, recv_frames_[i].can_dlc);
    frames->push_back(cf);
  }

  return ErrorCode::OK;
}

std::string SocketCanClientRaw::GetErrorString(const int32_t /*status*/) {
  return "";
}

}  // namespace can
}  // namespace canbus
}  // namespace drivers
}  // namespace apollo
<commit_msg>Planning: fixed a safety bug in socket_can_client_raw.cc -- do not memcy when the returned can msg length is invalid.<commit_after>/******************************************************************************
 * Copyright 2017 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.
 *****************************************************************************/

/**
 * @file socket_can_client.cc
 * @brief the encapsulate call the api of socket can card according to
 *can_client.h interface
 **/

#include "modules/drivers/canbus/can_client/socket/socket_can_client_raw.h"

namespace apollo {
namespace drivers {
namespace canbus {
namespace can {

using apollo::common::ErrorCode;

bool SocketCanClientRaw::Init(const CANCardParameter &parameter) {
  if (!parameter.has_channel_id()) {
    AERROR << "Init CAN failed: parameter does not have channel id. The "
              "parameter is "
           << parameter.DebugString();
    return false;
  }

  port_ = parameter.channel_id();
  return true;
}

ErrorCode SocketCanClientRaw::Start() {
  if (is_started_) {
    return ErrorCode::OK;
  }
  struct sockaddr_can addr;
  struct ifreq ifr;

  // open device
  // guss net is the device minor number, if one card is 0,1
  // if more than one card, when install driver u can specify the minior id
  // int32_t ret = canOpen(net, pCtx->mode, txbufsize, rxbufsize, 0, 0,
  // &dev_handler_);
  if (port_ > MAX_CAN_PORT || port_ < 0) {
    AERROR << "can port number [" << port_ << "] is out of the range [0,"
           << MAX_CAN_PORT << "]";
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  dev_handler_ = socket(PF_CAN, SOCK_RAW, CAN_RAW);
  if (dev_handler_ < 0) {
    AERROR << "open device error code [" << dev_handler_ << "]: ";
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  // init config and state
  // 1. set receive message_id filter, ie white list
  struct can_filter filter[2048];
  for (int i = 0; i < 2048; ++i) {
    filter[i].can_id = 0x000 + i;
    filter[i].can_mask = CAN_SFF_MASK;
  }

  int ret = setsockopt(dev_handler_, SOL_CAN_RAW, CAN_RAW_FILTER, &filter,
                       sizeof(filter));
  if (ret < 0) {
    AERROR << "add receive msg id filter error code: " << ret;
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  // 2. enable reception of can frames.
  int enable = 1;
  ret = ::setsockopt(dev_handler_, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable,
                     sizeof(enable));
  if (ret < 0) {
    AERROR << "enable reception of can frame error code: " << ret;
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  // strcpy(ifr.ifr_name, "can0");
  std::strncpy(ifr.ifr_name, "can0", IFNAMSIZ);
  if (ioctl(dev_handler_, SIOCGIFINDEX, &ifr) < 0) {
    AERROR << "ioctl error";
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  // bind socket to network interface

  addr.can_family = AF_CAN;
  addr.can_ifindex = ifr.ifr_ifindex;
  ret = ::bind(dev_handler_, reinterpret_cast<struct sockaddr *>(&addr),
               sizeof(addr));

  if (ret < 0) {
    AERROR << "bind socket to network interface error code: " << ret;
    return ErrorCode::CAN_CLIENT_ERROR_BASE;
  }

  is_started_ = true;
  return ErrorCode::OK;
}

void SocketCanClientRaw::Stop() {
  if (is_started_) {
    is_started_ = false;

    int ret = close(dev_handler_);
    if (ret < 0) {
      AERROR << "close error code:" << ret << ", " << GetErrorString(ret);
    } else {
      AINFO << "close socket can ok. port:" << port_;
    }
  }
}

// Synchronous transmission of CAN messages
ErrorCode SocketCanClientRaw::Send(const std::vector<CanFrame> &frames,
                                   int32_t *const frame_num) {
  CHECK_NOTNULL(frame_num);
  CHECK_EQ(frames.size(), static_cast<size_t>(*frame_num));

  if (!is_started_) {
    AERROR << "Nvidia can client has not been initiated! Please init first!";
    return ErrorCode::CAN_CLIENT_ERROR_SEND_FAILED;
  }
  for (size_t i = 0; i < frames.size() && i < MAX_CAN_SEND_FRAME_LEN; ++i) {
    send_frames_[i].can_id = frames[i].id;
    send_frames_[i].can_dlc = frames[i].len;
    std::memcpy(send_frames_[i].data, frames[i].data, frames[i].len);

    // Synchronous transmission of CAN messages
    int ret = write(dev_handler_, &send_frames_[i], sizeof(send_frames_[i]));
    if (ret <= 0) {
      AERROR << "send message failed, error code: " << ret;
      return ErrorCode::CAN_CLIENT_ERROR_BASE;
    }
  }

  return ErrorCode::OK;
}

// buf size must be 8 bytes, every time, we receive only one frame
ErrorCode SocketCanClientRaw::Receive(std::vector<CanFrame> *const frames,
                                      int32_t *const frame_num) {
  if (!is_started_) {
    AERROR << "Nvidia can client is not init! Please init first!";
    return ErrorCode::CAN_CLIENT_ERROR_RECV_FAILED;
  }

  if (*frame_num > MAX_CAN_RECV_FRAME_LEN || *frame_num < 0) {
    AERROR << "recv can frame num not in range[0, " << MAX_CAN_RECV_FRAME_LEN
           << "], frame_num:" << *frame_num;
    // TODO(Authors): check the difference of returning frame_num/error_code
    return ErrorCode::CAN_CLIENT_ERROR_FRAME_NUM;
  }

  for (int32_t i = 0; i < *frame_num && i < MAX_CAN_RECV_FRAME_LEN; ++i) {
    CanFrame cf;
    int ret = read(dev_handler_, &recv_frames_[i], sizeof(recv_frames_[i]));

    if (ret < 0) {
      AERROR << "receive message failed, error code: " << ret;
      return ErrorCode::CAN_CLIENT_ERROR_BASE;
    }
    cf.id = recv_frames_[i].can_id;
    cf.len = recv_frames_[i].can_dlc;
    if (recv_frames_[i].can_dlc <= MAX_CAN_RECV_FRAME_LEN) {
      std::memcpy(cf.data, recv_frames_[i].data, recv_frames_[i].can_dlc);
    } else {
      AERROR << "recv_frames_[" << i << "].can_dlc = " << cf.len
             << ", which exceeds max can received frame length ("
             << MAX_CAN_RECV_FRAME_LEN;
    }
    frames->push_back(cf);
  }

  return ErrorCode::OK;
}

std::string SocketCanClientRaw::GetErrorString(const int32_t /*status*/) {
  return "";
}

}  // namespace can
}  // namespace canbus
}  // namespace drivers
}  // namespace apollo
<|endoftext|>


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

#include "base/string_util.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h"

using content::WebContents;

class ExtensionInstallUIBrowserTest : public ExtensionBrowserTest {
 public:
  // Checks that a theme info bar is currently visible and issues an undo to
  // revert to the previous theme.
  void VerifyThemeInfoBarAndUndoInstall() {
    TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
    ASSERT_TRUE(tab);
    InfoBarTabHelper* infobar_helper = tab->infobar_tab_helper();
    ASSERT_EQ(1U, infobar_helper->infobar_count());
    ConfirmInfoBarDelegate* delegate = infobar_helper->
        GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
    ASSERT_TRUE(delegate);
    delegate->Cancel();
    ASSERT_EQ(0U, infobar_helper->infobar_count());
  }

  const Extension* GetTheme() const {
    return ThemeServiceFactory::GetThemeForProfile(browser()->profile());
  }
};

// Flaky on linux. See http://crbug.com/86105
#if defined(OS_LINUX)
#define MAYBE_TestThemeInstallUndoResetsToDefault \
DISABLED_TestThemeInstallUndoResetsToDefault
#else
#define MAYBE_TestThemeInstallUndoResetsToDefault \
TestThemeInstallUndoResetsToDefault
#endif
IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       MAYBE_TestThemeInstallUndoResetsToDefault) {
  // Install theme once and undo to verify we go back to default theme.
  FilePath theme_crx = PackExtension(test_data_dir_.AppendASCII("theme"));
  ASSERT_TRUE(InstallExtensionWithUI(theme_crx, 1));
  const Extension* theme = GetTheme();
  ASSERT_TRUE(theme);
  std::string theme_id = theme->id();
  VerifyThemeInfoBarAndUndoInstall();
  ASSERT_EQ(NULL, GetTheme());

  // Set the same theme twice and undo to verify we go back to default theme.
  // We set the |expected_change| to zero in these 'InstallExtensionWithUI'
  // calls since the theme has already been installed above and this is an
  // overinstall to set the active theme.
  ASSERT_TRUE(InstallExtensionWithUI(theme_crx, 0));
  theme = GetTheme();
  ASSERT_TRUE(theme);
  ASSERT_EQ(theme_id, theme->id());
  ASSERT_TRUE(InstallExtensionWithUI(theme_crx, 0));
  theme = GetTheme();
  ASSERT_TRUE(theme);
  ASSERT_EQ(theme_id, theme->id());
  VerifyThemeInfoBarAndUndoInstall();
  ASSERT_EQ(NULL, GetTheme());
}

// Flaky on linux. See http://crbug.com/86105
#if defined(OS_LINUX)
#define MAYBE_TestThemeInstallUndoResetsToPreviousTheme \
DISABLED_TestThemeInstallUndoResetsToPreviousTheme
#else
#define MAYBE_TestThemeInstallUndoResetsToPreviousTheme \
TestThemeInstallUndoResetsToPreviousTheme
#endif
IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       MAYBE_TestThemeInstallUndoResetsToPreviousTheme) {
  // Install first theme.
  FilePath theme_path = test_data_dir_.AppendASCII("theme");
  ASSERT_TRUE(InstallExtensionWithUI(theme_path, 1));
  const Extension* theme = GetTheme();
  ASSERT_TRUE(theme);
  std::string theme_id = theme->id();

  // Then install second theme.
  FilePath theme_path2 = test_data_dir_.AppendASCII("theme2");
  ASSERT_TRUE(InstallExtensionWithUI(theme_path2, 1));
  const Extension* theme2 = GetTheme();
  ASSERT_TRUE(theme2);
  EXPECT_FALSE(theme_id == theme2->id());

  // Undo second theme will revert to first theme.
  VerifyThemeInfoBarAndUndoInstall();
  EXPECT_EQ(theme, GetTheme());
}

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       AppInstallConfirmation) {
  int num_tabs = browser()->tab_count();

  FilePath app_dir = test_data_dir_.AppendASCII("app");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1,
                                                browser()->profile()));

  EXPECT_EQ(num_tabs + 1, browser()->tab_count());
  WebContents* web_contents = browser()->GetSelectedWebContents();
  ASSERT_TRUE(web_contents);
  EXPECT_TRUE(StartsWithASCII(web_contents->GetURL().spec(),
                              "chrome://newtab/", false));
}

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       AppInstallConfirmation_Incognito) {
  Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile();
  Browser* incognito_browser = Browser::GetOrCreateTabbedBrowser(
      incognito_profile);

  int num_incognito_tabs = incognito_browser->tab_count();
  int num_normal_tabs = browser()->tab_count();

  FilePath app_dir = test_data_dir_.AppendASCII("app");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1,
                                                incognito_profile));

  EXPECT_EQ(num_incognito_tabs, incognito_browser->tab_count());
  EXPECT_EQ(num_normal_tabs + 1, browser()->tab_count());
  WebContents* web_contents = browser()->GetSelectedWebContents();
  ASSERT_TRUE(web_contents);
  EXPECT_TRUE(StartsWithASCII(web_contents->GetURL().spec(),
                              "chrome://newtab/", false));
}
<commit_msg>ExtensionInstallUIBrowserTest theme tests no longer flaky<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/string_util.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h"

using content::WebContents;

class ExtensionInstallUIBrowserTest : public ExtensionBrowserTest {
 public:
  // Checks that a theme info bar is currently visible and issues an undo to
  // revert to the previous theme.
  void VerifyThemeInfoBarAndUndoInstall() {
    TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
    ASSERT_TRUE(tab);
    InfoBarTabHelper* infobar_helper = tab->infobar_tab_helper();
    ASSERT_EQ(1U, infobar_helper->infobar_count());
    ConfirmInfoBarDelegate* delegate = infobar_helper->
        GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
    ASSERT_TRUE(delegate);
    delegate->Cancel();
    ASSERT_EQ(0U, infobar_helper->infobar_count());
  }

  const Extension* GetTheme() const {
    return ThemeServiceFactory::GetThemeForProfile(browser()->profile());
  }
};

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       TestThemeInstallUndoResetsToDefault) {
  // Install theme once and undo to verify we go back to default theme.
  FilePath theme_crx = PackExtension(test_data_dir_.AppendASCII("theme"));
  ASSERT_TRUE(InstallExtensionWithUI(theme_crx, 1));
  const Extension* theme = GetTheme();
  ASSERT_TRUE(theme);
  std::string theme_id = theme->id();
  VerifyThemeInfoBarAndUndoInstall();
  ASSERT_EQ(NULL, GetTheme());

  // Set the same theme twice and undo to verify we go back to default theme.
  // We set the |expected_change| to zero in these 'InstallExtensionWithUI'
  // calls since the theme has already been installed above and this is an
  // overinstall to set the active theme.
  ASSERT_TRUE(InstallExtensionWithUI(theme_crx, 0));
  theme = GetTheme();
  ASSERT_TRUE(theme);
  ASSERT_EQ(theme_id, theme->id());
  ASSERT_TRUE(InstallExtensionWithUI(theme_crx, 0));
  theme = GetTheme();
  ASSERT_TRUE(theme);
  ASSERT_EQ(theme_id, theme->id());
  VerifyThemeInfoBarAndUndoInstall();
  ASSERT_EQ(NULL, GetTheme());
}

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       TestThemeInstallUndoResetsToPreviousTheme) {
  // Install first theme.
  FilePath theme_path = test_data_dir_.AppendASCII("theme");
  ASSERT_TRUE(InstallExtensionWithUI(theme_path, 1));
  const Extension* theme = GetTheme();
  ASSERT_TRUE(theme);
  std::string theme_id = theme->id();

  // Then install second theme.
  FilePath theme_path2 = test_data_dir_.AppendASCII("theme2");
  ASSERT_TRUE(InstallExtensionWithUI(theme_path2, 1));
  const Extension* theme2 = GetTheme();
  ASSERT_TRUE(theme2);
  EXPECT_FALSE(theme_id == theme2->id());

  // Undo second theme will revert to first theme.
  VerifyThemeInfoBarAndUndoInstall();
  EXPECT_EQ(theme, GetTheme());
}

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       AppInstallConfirmation) {
  int num_tabs = browser()->tab_count();

  FilePath app_dir = test_data_dir_.AppendASCII("app");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1,
                                                browser()->profile()));

  EXPECT_EQ(num_tabs + 1, browser()->tab_count());
  WebContents* web_contents = browser()->GetSelectedWebContents();
  ASSERT_TRUE(web_contents);
  EXPECT_TRUE(StartsWithASCII(web_contents->GetURL().spec(),
                              "chrome://newtab/", false));
}

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       AppInstallConfirmation_Incognito) {
  Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile();
  Browser* incognito_browser = Browser::GetOrCreateTabbedBrowser(
      incognito_profile);

  int num_incognito_tabs = incognito_browser->tab_count();
  int num_normal_tabs = browser()->tab_count();

  FilePath app_dir = test_data_dir_.AppendASCII("app");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1,
                                                incognito_profile));

  EXPECT_EQ(num_incognito_tabs, incognito_browser->tab_count());
  EXPECT_EQ(num_normal_tabs + 1, browser()->tab_count());
  WebContents* web_contents = browser()->GetSelectedWebContents();
  ASSERT_TRUE(web_contents);
  EXPECT_TRUE(StartsWithASCII(web_contents->GetURL().spec(),
                              "chrome://newtab/", false));
}
<|endoftext|>


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

#include "base/string_util.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h"

using content::WebContents;
using extensions::Extension;

class ExtensionInstallUIBrowserTest : public ExtensionBrowserTest {
 public:
  // Checks that a theme info bar is currently visible and issues an undo to
  // revert to the previous theme.
  void VerifyThemeInfoBarAndUndoInstall() {
    TabContents* tab = browser()->GetActiveTabContents();
    ASSERT_TRUE(tab);
    InfoBarTabHelper* infobar_helper = tab->infobar_tab_helper();
    ASSERT_EQ(1U, infobar_helper->infobar_count());
    ConfirmInfoBarDelegate* delegate = infobar_helper->
        GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
    ASSERT_TRUE(delegate);
    delegate->Cancel();
    ASSERT_EQ(0U, infobar_helper->infobar_count());
  }

  const Extension* GetTheme() const {
    return ThemeServiceFactory::GetThemeForProfile(browser()->profile());
  }
};

#if defined(OS_LINUX)
// Fails consistently on bot chromium.chromiumos \ Linux.
// See: http://crbug.com/120647.
#define MAYBE_TestThemeInstallUndoResetsToDefault DISABLED_TestThemeInstallUndoResetsToDefault
#else
#define MAYBE_TestThemeInstallUndoResetsToDefault TestThemeInstallUndoResetsToDefault
#endif

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       MAYBE_TestThemeInstallUndoResetsToDefault) {
  // Install theme once and undo to verify we go back to default theme.
  FilePath theme_crx = PackExtension(test_data_dir_.AppendASCII("theme"));
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
      theme_crx, 1, browser()->profile()));
  const Extension* theme = GetTheme();
  ASSERT_TRUE(theme);
  std::string theme_id = theme->id();
  VerifyThemeInfoBarAndUndoInstall();
  ASSERT_EQ(NULL, GetTheme());

  // Set the same theme twice and undo to verify we go back to default theme.
  // We set the |expected_change| to zero in these 'InstallExtensionWithUI'
  // calls since the theme has already been installed above and this is an
  // overinstall to set the active theme.
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
      theme_crx, 0, browser()->profile()));
  theme = GetTheme();
  ASSERT_TRUE(theme);
  ASSERT_EQ(theme_id, theme->id());
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
      theme_crx, 0, browser()->profile()));
  theme = GetTheme();
  ASSERT_TRUE(theme);
  ASSERT_EQ(theme_id, theme->id());
  VerifyThemeInfoBarAndUndoInstall();
  ASSERT_EQ(NULL, GetTheme());
}

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       TestThemeInstallUndoResetsToPreviousTheme) {
  // Install first theme.
  FilePath theme_path = test_data_dir_.AppendASCII("theme");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
      theme_path, 1, browser()->profile()));
  const Extension* theme = GetTheme();
  ASSERT_TRUE(theme);
  std::string theme_id = theme->id();

  // Then install second theme.
  FilePath theme_path2 = test_data_dir_.AppendASCII("theme2");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
      theme_path2, 1, browser()->profile()));
  const Extension* theme2 = GetTheme();
  ASSERT_TRUE(theme2);
  EXPECT_FALSE(theme_id == theme2->id());

  // Undo second theme will revert to first theme.
  VerifyThemeInfoBarAndUndoInstall();
  EXPECT_EQ(theme, GetTheme());
}

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       AppInstallConfirmation) {
  int num_tabs = browser()->tab_count();

  FilePath app_dir = test_data_dir_.AppendASCII("app");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1,
                                                browser()->profile()));

  if (NewTabUI::ShouldShowApps()) {
    EXPECT_EQ(num_tabs + 1, browser()->tab_count());
    WebContents* web_contents = browser()->GetActiveWebContents();
    ASSERT_TRUE(web_contents);
    EXPECT_TRUE(StartsWithASCII(web_contents->GetURL().spec(),
                                "chrome://newtab/", false));
  } else {
    // TODO(xiyuan): Figure out how to test extension installed bubble?
  }
}

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       AppInstallConfirmation_Incognito) {
  Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile();
  Browser* incognito_browser = browser::FindOrCreateTabbedBrowser(
      incognito_profile);

  int num_incognito_tabs = incognito_browser->tab_count();
  int num_normal_tabs = browser()->tab_count();

  FilePath app_dir = test_data_dir_.AppendASCII("app");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1,
                                                incognito_profile));

  EXPECT_EQ(num_incognito_tabs, incognito_browser->tab_count());
  if (NewTabUI::ShouldShowApps()) {
    EXPECT_EQ(num_normal_tabs + 1, browser()->tab_count());
    WebContents* web_contents = browser()->GetActiveWebContents();
    ASSERT_TRUE(web_contents);
    EXPECT_TRUE(StartsWithASCII(web_contents->GetURL().spec(),
                                "chrome://newtab/", false));
  } else {
    // TODO(xiyuan): Figure out how to test extension installed bubble?
  }
}
<commit_msg>Close all infobars before testing the count, otherwise the count will be wrong.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/string_util.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h"

using content::WebContents;
using extensions::Extension;

class ExtensionInstallUIBrowserTest : public ExtensionBrowserTest {
 public:
  // The test counts infobars, so make sure nothing else has opened one.
  void CloseAllInfobars() {
    TabContents* tab = browser()->GetActiveTabContents();
    ASSERT_TRUE(tab);

    InfoBarTabHelper* infobar_helper = tab->infobar_tab_helper();
    while (infobar_helper->infobar_count() > 0)
      infobar_helper->RemoveInfoBar(infobar_helper->GetInfoBarDelegateAt(0));
  }

  // Checks that a theme info bar is currently visible and issues an undo to
  // revert to the previous theme.
  void VerifyThemeInfoBarAndUndoInstall() {
    TabContents* tab = browser()->GetActiveTabContents();
    ASSERT_TRUE(tab);
    InfoBarTabHelper* infobar_helper = tab->infobar_tab_helper();
    ASSERT_EQ(1U, infobar_helper->infobar_count());
    ConfirmInfoBarDelegate* delegate = infobar_helper->
        GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
    ASSERT_TRUE(delegate);
    delegate->Cancel();
    ASSERT_EQ(0U, infobar_helper->infobar_count());
  }

  const Extension* GetTheme() const {
    return ThemeServiceFactory::GetThemeForProfile(browser()->profile());
  }
};

#if defined(OS_LINUX)
// Fails consistently on bot chromium.chromiumos \ Linux.
// See: http://crbug.com/120647.
#define MAYBE_TestThemeInstallUndoResetsToDefault DISABLED_TestThemeInstallUndoResetsToDefault
#else
#define MAYBE_TestThemeInstallUndoResetsToDefault TestThemeInstallUndoResetsToDefault
#endif

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       MAYBE_TestThemeInstallUndoResetsToDefault) {
  CloseAllInfobars();

  // Install theme once and undo to verify we go back to default theme.
  FilePath theme_crx = PackExtension(test_data_dir_.AppendASCII("theme"));
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
      theme_crx, 1, browser()->profile()));
  const Extension* theme = GetTheme();
  ASSERT_TRUE(theme);
  std::string theme_id = theme->id();
  VerifyThemeInfoBarAndUndoInstall();
  ASSERT_EQ(NULL, GetTheme());

  // Set the same theme twice and undo to verify we go back to default theme.
  // We set the |expected_change| to zero in these 'InstallExtensionWithUI'
  // calls since the theme has already been installed above and this is an
  // overinstall to set the active theme.
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
      theme_crx, 0, browser()->profile()));
  theme = GetTheme();
  ASSERT_TRUE(theme);
  ASSERT_EQ(theme_id, theme->id());
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
      theme_crx, 0, browser()->profile()));
  theme = GetTheme();
  ASSERT_TRUE(theme);
  ASSERT_EQ(theme_id, theme->id());
  VerifyThemeInfoBarAndUndoInstall();
  ASSERT_EQ(NULL, GetTheme());
}

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       TestThemeInstallUndoResetsToPreviousTheme) {
  CloseAllInfobars();

  // Install first theme.
  FilePath theme_path = test_data_dir_.AppendASCII("theme");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
      theme_path, 1, browser()->profile()));
  const Extension* theme = GetTheme();
  ASSERT_TRUE(theme);
  std::string theme_id = theme->id();

  // Then install second theme.
  FilePath theme_path2 = test_data_dir_.AppendASCII("theme2");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
      theme_path2, 1, browser()->profile()));
  const Extension* theme2 = GetTheme();
  ASSERT_TRUE(theme2);
  EXPECT_FALSE(theme_id == theme2->id());

  // Undo second theme will revert to first theme.
  VerifyThemeInfoBarAndUndoInstall();
  EXPECT_EQ(theme, GetTheme());
}

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       AppInstallConfirmation) {
  int num_tabs = browser()->tab_count();

  FilePath app_dir = test_data_dir_.AppendASCII("app");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1,
                                                browser()->profile()));

  if (NewTabUI::ShouldShowApps()) {
    EXPECT_EQ(num_tabs + 1, browser()->tab_count());
    WebContents* web_contents = browser()->GetActiveWebContents();
    ASSERT_TRUE(web_contents);
    EXPECT_TRUE(StartsWithASCII(web_contents->GetURL().spec(),
                                "chrome://newtab/", false));
  } else {
    // TODO(xiyuan): Figure out how to test extension installed bubble?
  }
}

IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
                       AppInstallConfirmation_Incognito) {
  Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile();
  Browser* incognito_browser = browser::FindOrCreateTabbedBrowser(
      incognito_profile);

  int num_incognito_tabs = incognito_browser->tab_count();
  int num_normal_tabs = browser()->tab_count();

  FilePath app_dir = test_data_dir_.AppendASCII("app");
  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1,
                                                incognito_profile));

  EXPECT_EQ(num_incognito_tabs, incognito_browser->tab_count());
  if (NewTabUI::ShouldShowApps()) {
    EXPECT_EQ(num_normal_tabs + 1, browser()->tab_count());
    WebContents* web_contents = browser()->GetActiveWebContents();
    ASSERT_TRUE(web_contents);
    EXPECT_TRUE(StartsWithASCII(web_contents->GetURL().spec(),
                                "chrome://newtab/", false));
  } else {
    // TODO(xiyuan): Figure out how to test extension installed bubble?
  }
}
<|endoftext|>


<commit_before>#include <cstdio>

using namespace std;

int main() {
    int c, n;

    scanf("%d", &c);

    while (c--) {
        scanf("%d", &n);

        if (n % 2 == 0) puts("0");
        else puts("1");
    }
    return 0;
}
<commit_msg>Arruma lint.<commit_after>#include <iostream>

int main() {
    int c, n;

    std::cin >> c;

    while (c--) {
        std::cin >> n;

        if (n % 2 == 0) {
            std::cout << 0 << std::endl;
        } else {
            std::cout << 1 << std::endl;
        }
    }
    return 0;
}
<|endoftext|>


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

#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_parser.h"
#include "chrome/common/chrome_paths.h"
#include "testing/gtest/include/gtest/gtest.h"

class TemplateURLParserTest : public testing::Test {
 public:
  TemplateURLParserTest() : parse_result_(true) {
  }

  virtual void SetUp() {
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &full_path_));
    full_path_ = full_path_.AppendASCII("osdd");
    if (!file_util::PathExists(full_path_)) {
      LOG(ERROR) <<
          L"This test can't be run without some non-redistributable data";
      full_path_ = FilePath();
    }
  }

  bool IsDisabled() {
    return full_path_.empty();
  }

  // Parses the OpenSearch description document at file_name (relative to
  // the data dir). The TemplateURL is placed in template_url_.
  // The result of Parse is stored in the field parse_result_ (this doesn't
  // use a return value due to internally using ASSERT_).
  void ParseFile(const std::string& file_name,
                 TemplateURLParser::ParameterFilter* filter) {
    FilePath full_path;
    parse_result_ = false;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &full_path));
    full_path = full_path.AppendASCII("osdd");
    full_path = full_path.AppendASCII(file_name);
    ASSERT_TRUE(file_util::PathExists(full_path));

    std::string contents;
    file_util::ReadFileToString(full_path, &contents);
    parse_result_ = TemplateURLParser::Parse(
        reinterpret_cast<const unsigned char*>(contents.c_str()),
        contents.length(), filter, &template_url_);
  }

  // ParseFile parses the results into this template_url.
  TemplateURL template_url_;

  FilePath full_path_;

  // Result of the parse.
  bool parse_result_;
};

TEST_F(TemplateURLParserTest, FailOnBogusURL) {
  if (IsDisabled())
    return;
  ParseFile("bogus.xml", NULL);
  EXPECT_FALSE(parse_result_);
}

TEST_F(TemplateURLParserTest, PassOnHTTPS) {
  if (IsDisabled())
    return;
  ParseFile("https.xml", NULL);
  EXPECT_TRUE(parse_result_);
}

TEST_F(TemplateURLParserTest, FailOnPost) {
  if (IsDisabled())
    return;
  ParseFile("post.xml", NULL);
  EXPECT_FALSE(parse_result_);
}

TEST_F(TemplateURLParserTest, TestDictionary) {
  if (IsDisabled())
    return;
  ParseFile("dictionary.xml", NULL);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Dictionary.com", template_url_.short_name());
  EXPECT_TRUE(template_url_.GetFavIconURL() ==
              GURL("http://cache.lexico.com/g/d/favicon.ico"));
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_EQ(template_url_.url()->url(),
            L"http://dictionary.reference.com/browse/{searchTerms}?r=75");
}

TEST_F(TemplateURLParserTest, TestMSDN) {
  if (IsDisabled())
    return;
  ParseFile("msdn.xml", NULL);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Search \" MSDN", template_url_.short_name());
  EXPECT_TRUE(template_url_.GetFavIconURL() ==
              GURL("http://search.msdn.microsoft.com/search/favicon.ico"));
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_EQ(template_url_.url()->url(),
            L"http://search.msdn.microsoft.com/search/default.aspx?Query={searchTerms}&brand=msdn&locale=en-US");
}

TEST_F(TemplateURLParserTest, TestWikipedia) {
  if (IsDisabled())
    return;
  ParseFile("wikipedia.xml", NULL);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Wikipedia (English)", template_url_.short_name());
  EXPECT_TRUE(template_url_.GetFavIconURL() ==
              GURL("http://en.wikipedia.org/favicon.ico"));
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_EQ(template_url_.url()->url(),
      L"http://en.wikipedia.org/w/index.php?title=Special:Search&search={searchTerms}");
  EXPECT_TRUE(template_url_.suggestions_url() != NULL);
  EXPECT_TRUE(template_url_.suggestions_url()->SupportsReplacement());
  EXPECT_EQ(template_url_.suggestions_url()->url(),
      L"http://en.wikipedia.org/w/api.php?action=opensearch&search={searchTerms}");
  ASSERT_EQ(2U, template_url_.input_encodings().size());
  EXPECT_EQ("UTF-8", template_url_.input_encodings()[0]);
  EXPECT_EQ("Shift_JIS", template_url_.input_encodings()[1]);
}

TEST_F(TemplateURLParserTest, NoCrashOnEmptyAttributes) {
  if (IsDisabled())
    return;
  ParseFile("url_with_no_attributes.xml", NULL);
}

// Filters any param which as an occurrence of name_str_ in its name or an
// occurrence of value_str_ in its value.
class ParamFilterImpl : public TemplateURLParser::ParameterFilter {
 public:
  ParamFilterImpl(std::string name_str, std::string value_str)
     : name_str_(name_str),
       value_str_(value_str) {
  }

  bool KeepParameter(const std::string& key, const std::string& value) {
    return (name_str_.empty() || key.find(name_str_) == std::string::npos) &&
           (value_str_.empty() || value.find(value_str_) == std::string::npos);
  }

 private:
  std::string name_str_;
  std::string value_str_;

  DISALLOW_EVIL_CONSTRUCTORS(ParamFilterImpl);
};

TEST_F(TemplateURLParserTest, TestFirefoxEbay) {
  if (IsDisabled())
    return;
  // This file uses the Parameter extension
  // (see http://www.opensearch.org/Specifications/OpenSearch/Extensions/Parameter/1.0)
  ParamFilterImpl filter("ebay", "ebay");
  ParseFile("firefox_ebay.xml", &filter);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"eBay", template_url_.short_name());
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  std::wstring exp_url =
      L"http://search.ebay.com/search/search.dll?query={searchTerms}&"
      L"MfcISAPICommand=GetResult&ht=1&srchdesc=n&maxRecordsReturned=300&"
      L"maxRecordsPerPage=50&SortProperty=MetaEndSort";
  EXPECT_EQ(exp_url, template_url_.url()->url());
  ASSERT_EQ(1U, template_url_.input_encodings().size());
  EXPECT_EQ("ISO-8859-1", template_url_.input_encodings()[0]);
  EXPECT_EQ(GURL("http://search.ebay.com/favicon.ico"),
            template_url_.GetFavIconURL());
}

TEST_F(TemplateURLParserTest, TestFirefoxWebster) {
  if (IsDisabled())
    return;
  // This XML file uses a namespace.
  ParamFilterImpl filter("", "Mozilla");
  ParseFile("firefox_webster.xml", &filter);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Webster", template_url_.short_name());
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_EQ(L"http://www.webster.com/cgi-bin/dictionary?va={searchTerms}",
            template_url_.url()->url());
  ASSERT_EQ(1U, template_url_.input_encodings().size());
  EXPECT_EQ("ISO-8859-1", template_url_.input_encodings()[0]);
  EXPECT_EQ(GURL("http://www.webster.com/favicon.ico"),
            template_url_.GetFavIconURL());
}

TEST_F(TemplateURLParserTest, TestFirefoxYahoo) {
  if (IsDisabled())
    return;
  // This XML file uses a namespace.
  ParamFilterImpl filter("", "Mozilla");
  ParseFile("firefox_yahoo.xml", &filter);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Yahoo", template_url_.short_name());
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_EQ(L"http://ff.search.yahoo.com/gossip?"
            L"output=fxjson&command={searchTerms}",
            template_url_.suggestions_url()->url());
  EXPECT_EQ(L"http://search.yahoo.com/search?p={searchTerms}&ei=UTF-8",
            template_url_.url()->url());
  ASSERT_EQ(1U, template_url_.input_encodings().size());
  EXPECT_EQ("UTF-8", template_url_.input_encodings()[0]);
  EXPECT_EQ(GURL("http://search.yahoo.com/favicon.ico"),
            template_url_.GetFavIconURL());
}

// Make sure we ignore POST suggestions (this is the same XML file as
// firefox_yahoo.xml, the suggestion method was just changed to POST).
TEST_F(TemplateURLParserTest, TestPostSuggestion) {
  if (IsDisabled())
    return;
  // This XML file uses a namespace.
  ParamFilterImpl filter("", "Mozilla");
  ParseFile("post_suggestion.xml", &filter);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Yahoo", template_url_.short_name());
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_TRUE(template_url_.suggestions_url() == NULL);
  EXPECT_EQ(L"http://search.yahoo.com/search?p={searchTerms}&ei=UTF-8",
            template_url_.url()->url());
  ASSERT_EQ(1U, template_url_.input_encodings().size());
  EXPECT_EQ("UTF-8", template_url_.input_encodings()[0]);
  EXPECT_EQ(GURL("http://search.yahoo.com/favicon.ico"),
            template_url_.GetFavIconURL());
}
<commit_msg>Coverity: check file_util::ReadFileToString return.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_parser.h"
#include "chrome/common/chrome_paths.h"
#include "testing/gtest/include/gtest/gtest.h"

class TemplateURLParserTest : public testing::Test {
 public:
  TemplateURLParserTest() : parse_result_(true) {
  }

  virtual void SetUp() {
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &full_path_));
    full_path_ = full_path_.AppendASCII("osdd");
    if (!file_util::PathExists(full_path_)) {
      LOG(ERROR) <<
          L"This test can't be run without some non-redistributable data";
      full_path_ = FilePath();
    }
  }

  bool IsDisabled() {
    return full_path_.empty();
  }

  // Parses the OpenSearch description document at file_name (relative to
  // the data dir). The TemplateURL is placed in template_url_.
  // The result of Parse is stored in the field parse_result_ (this doesn't
  // use a return value due to internally using ASSERT_).
  void ParseFile(const std::string& file_name,
                 TemplateURLParser::ParameterFilter* filter) {
    FilePath full_path;
    parse_result_ = false;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &full_path));
    full_path = full_path.AppendASCII("osdd");
    full_path = full_path.AppendASCII(file_name);
    ASSERT_TRUE(file_util::PathExists(full_path));

    std::string contents;
    ASSERT_TRUE(file_util::ReadFileToString(full_path, &contents));
    parse_result_ = TemplateURLParser::Parse(
        reinterpret_cast<const unsigned char*>(contents.c_str()),
        contents.length(), filter, &template_url_);
  }

  // ParseFile parses the results into this template_url.
  TemplateURL template_url_;

  FilePath full_path_;

  // Result of the parse.
  bool parse_result_;
};

TEST_F(TemplateURLParserTest, FailOnBogusURL) {
  if (IsDisabled())
    return;
  ParseFile("bogus.xml", NULL);
  EXPECT_FALSE(parse_result_);
}

TEST_F(TemplateURLParserTest, PassOnHTTPS) {
  if (IsDisabled())
    return;
  ParseFile("https.xml", NULL);
  EXPECT_TRUE(parse_result_);
}

TEST_F(TemplateURLParserTest, FailOnPost) {
  if (IsDisabled())
    return;
  ParseFile("post.xml", NULL);
  EXPECT_FALSE(parse_result_);
}

TEST_F(TemplateURLParserTest, TestDictionary) {
  if (IsDisabled())
    return;
  ParseFile("dictionary.xml", NULL);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Dictionary.com", template_url_.short_name());
  EXPECT_TRUE(template_url_.GetFavIconURL() ==
              GURL("http://cache.lexico.com/g/d/favicon.ico"));
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_EQ(template_url_.url()->url(),
            L"http://dictionary.reference.com/browse/{searchTerms}?r=75");
}

TEST_F(TemplateURLParserTest, TestMSDN) {
  if (IsDisabled())
    return;
  ParseFile("msdn.xml", NULL);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Search \" MSDN", template_url_.short_name());
  EXPECT_TRUE(template_url_.GetFavIconURL() ==
              GURL("http://search.msdn.microsoft.com/search/favicon.ico"));
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_EQ(template_url_.url()->url(),
            L"http://search.msdn.microsoft.com/search/default.aspx?Query={searchTerms}&brand=msdn&locale=en-US");
}

TEST_F(TemplateURLParserTest, TestWikipedia) {
  if (IsDisabled())
    return;
  ParseFile("wikipedia.xml", NULL);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Wikipedia (English)", template_url_.short_name());
  EXPECT_TRUE(template_url_.GetFavIconURL() ==
              GURL("http://en.wikipedia.org/favicon.ico"));
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_EQ(template_url_.url()->url(),
      L"http://en.wikipedia.org/w/index.php?title=Special:Search&search={searchTerms}");
  EXPECT_TRUE(template_url_.suggestions_url() != NULL);
  EXPECT_TRUE(template_url_.suggestions_url()->SupportsReplacement());
  EXPECT_EQ(template_url_.suggestions_url()->url(),
      L"http://en.wikipedia.org/w/api.php?action=opensearch&search={searchTerms}");
  ASSERT_EQ(2U, template_url_.input_encodings().size());
  EXPECT_EQ("UTF-8", template_url_.input_encodings()[0]);
  EXPECT_EQ("Shift_JIS", template_url_.input_encodings()[1]);
}

TEST_F(TemplateURLParserTest, NoCrashOnEmptyAttributes) {
  if (IsDisabled())
    return;
  ParseFile("url_with_no_attributes.xml", NULL);
}

// Filters any param which as an occurrence of name_str_ in its name or an
// occurrence of value_str_ in its value.
class ParamFilterImpl : public TemplateURLParser::ParameterFilter {
 public:
  ParamFilterImpl(std::string name_str, std::string value_str)
     : name_str_(name_str),
       value_str_(value_str) {
  }

  bool KeepParameter(const std::string& key, const std::string& value) {
    return (name_str_.empty() || key.find(name_str_) == std::string::npos) &&
           (value_str_.empty() || value.find(value_str_) == std::string::npos);
  }

 private:
  std::string name_str_;
  std::string value_str_;

  DISALLOW_EVIL_CONSTRUCTORS(ParamFilterImpl);
};

TEST_F(TemplateURLParserTest, TestFirefoxEbay) {
  if (IsDisabled())
    return;
  // This file uses the Parameter extension
  // (see http://www.opensearch.org/Specifications/OpenSearch/Extensions/Parameter/1.0)
  ParamFilterImpl filter("ebay", "ebay");
  ParseFile("firefox_ebay.xml", &filter);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"eBay", template_url_.short_name());
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  std::wstring exp_url =
      L"http://search.ebay.com/search/search.dll?query={searchTerms}&"
      L"MfcISAPICommand=GetResult&ht=1&srchdesc=n&maxRecordsReturned=300&"
      L"maxRecordsPerPage=50&SortProperty=MetaEndSort";
  EXPECT_EQ(exp_url, template_url_.url()->url());
  ASSERT_EQ(1U, template_url_.input_encodings().size());
  EXPECT_EQ("ISO-8859-1", template_url_.input_encodings()[0]);
  EXPECT_EQ(GURL("http://search.ebay.com/favicon.ico"),
            template_url_.GetFavIconURL());
}

TEST_F(TemplateURLParserTest, TestFirefoxWebster) {
  if (IsDisabled())
    return;
  // This XML file uses a namespace.
  ParamFilterImpl filter("", "Mozilla");
  ParseFile("firefox_webster.xml", &filter);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Webster", template_url_.short_name());
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_EQ(L"http://www.webster.com/cgi-bin/dictionary?va={searchTerms}",
            template_url_.url()->url());
  ASSERT_EQ(1U, template_url_.input_encodings().size());
  EXPECT_EQ("ISO-8859-1", template_url_.input_encodings()[0]);
  EXPECT_EQ(GURL("http://www.webster.com/favicon.ico"),
            template_url_.GetFavIconURL());
}

TEST_F(TemplateURLParserTest, TestFirefoxYahoo) {
  if (IsDisabled())
    return;
  // This XML file uses a namespace.
  ParamFilterImpl filter("", "Mozilla");
  ParseFile("firefox_yahoo.xml", &filter);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Yahoo", template_url_.short_name());
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_EQ(L"http://ff.search.yahoo.com/gossip?"
            L"output=fxjson&command={searchTerms}",
            template_url_.suggestions_url()->url());
  EXPECT_EQ(L"http://search.yahoo.com/search?p={searchTerms}&ei=UTF-8",
            template_url_.url()->url());
  ASSERT_EQ(1U, template_url_.input_encodings().size());
  EXPECT_EQ("UTF-8", template_url_.input_encodings()[0]);
  EXPECT_EQ(GURL("http://search.yahoo.com/favicon.ico"),
            template_url_.GetFavIconURL());
}

// Make sure we ignore POST suggestions (this is the same XML file as
// firefox_yahoo.xml, the suggestion method was just changed to POST).
TEST_F(TemplateURLParserTest, TestPostSuggestion) {
  if (IsDisabled())
    return;
  // This XML file uses a namespace.
  ParamFilterImpl filter("", "Mozilla");
  ParseFile("post_suggestion.xml", &filter);
  ASSERT_TRUE(parse_result_);
  EXPECT_EQ(L"Yahoo", template_url_.short_name());
  EXPECT_TRUE(template_url_.url() != NULL);
  EXPECT_TRUE(template_url_.url()->SupportsReplacement());
  EXPECT_TRUE(template_url_.suggestions_url() == NULL);
  EXPECT_EQ(L"http://search.yahoo.com/search?p={searchTerms}&ei=UTF-8",
            template_url_.url()->url());
  ASSERT_EQ(1U, template_url_.input_encodings().size());
  EXPECT_EQ("UTF-8", template_url_.input_encodings()[0]);
  EXPECT_EQ(GURL("http://search.yahoo.com/favicon.ico"),
            template_url_.GetFavIconURL());
}
<|endoftext|>


<commit_before><commit_msg>planning: fix compile warning.<commit_after><|endoftext|>


<commit_before>#pragma once
#include <mutex>
#include <iosfwd>
#include <sstream>
#include <cctype>
#include <But/Log/Destination/detail/StreamAndTrimVisitor.hpp>
#include <But/Log/Destination/Sink.hpp>

namespace But
{
namespace Log
{
namespace Destination
{
namespace Common
{

class TextStream: public Sink
{
protected:
  explicit TextStream(std::ostream& os): os_{os} { }

  std::string const& endline() const { return endline_; }
  auto const& trim() const { return trim_; }

private:
  void logImpl(Backend::FieldInfo const& fi) override final
  {
    const std::lock_guard<std::mutex> lock(mutex_);
    toStreamFormat(os_, fi);
  }

  void reloadImpl() override final
  {
    const std::lock_guard<std::mutex> lock(mutex_);
    reloadImplUnderLock();
  }

  void flushImpl() override final
  {
    const std::lock_guard<std::mutex> lock(mutex_);
    os_ << std::flush;
  }

  virtual void reloadImplUnderLock() = 0;

  virtual void toStreamFormat(std::ostream& os, Backend::FieldInfo const& fi)
  {
    detail::StreamAndTrimVisitor satv{&trim_, &os};
    fi.visit(satv);
    os << endline();
  }

  static std::string endlineType()
  {
    std::stringstream ss;
    ss << std::endl;
    return ss.str();
  }

  std::mutex mutex_;
  std::ostream& os_;
  const std::string endline_{ endlineType() };
  const Backend::NonPrintableTrimmer trim_;
};

}
}
}
}
<commit_msg>TODO for osyncstream for display<commit_after>#pragma once
#include <mutex>
#include <iosfwd>
#include <sstream>
#include <cctype>
#include <But/Log/Destination/detail/StreamAndTrimVisitor.hpp>
#include <But/Log/Destination/Sink.hpp>

namespace But
{
namespace Log
{
namespace Destination
{
namespace Common
{

class TextStream: public Sink
{
protected:
  explicit TextStream(std::ostream& os): os_{os} { }

  std::string const& endline() const { return endline_; }
  auto const& trim() const { return trim_; }

private:
  void logImpl(Backend::FieldInfo const& fi) override final
  {
    const std::lock_guard<std::mutex> lock(mutex_);
    toStreamFormat(os_, fi);
  }

  void reloadImpl() override final
  {
    const std::lock_guard<std::mutex> lock(mutex_);
    reloadImplUnderLock();
  }

  void flushImpl() override final
  {
    const std::lock_guard<std::mutex> lock(mutex_);
    os_ << std::flush;
  }

  virtual void reloadImplUnderLock() = 0;

  virtual void toStreamFormat(std::ostream& os, Backend::FieldInfo const& fi)
  {
    detail::StreamAndTrimVisitor satv{&trim_, &os};
    fi.visit(satv);
    os << endline();
  }

  static std::string endlineType()
  {
    std::stringstream ss;
    ss << std::endl;
    return ss.str();
  }

  std::mutex mutex_;
  // TODO: consider std::osyncstream
  // https://en.cppreference.com/w/cpp/io/basic_osyncstream
  std::ostream& os_;
  const std::string endline_{ endlineType() };
  const Backend::NonPrintableTrimmer trim_;
};

}
}
}
}
<|endoftext|>


<commit_before>#include "puppet_animation_aspect.hpp"
#include "game/world/level_model.hpp"
#include "game/world/keys/components/key_state.hpp"
#include "game/world/keys/key_presenter.hpp"
#include "game/world/events/armed_mode_changed.hpp"
#include "game/world/events/jumped.hpp"
#include "game/world/events/landed.hpp"
#include "game/world/events/killed.hpp"
#include "game/world/events/thing_created.hpp"

using gorc::game::world::aspects::puppet_animation_aspect;

puppet_animation_aspect::puppet_animation_aspect(entity_component_system<thing_id> &cs,
                                                 level_presenter &presenter)
    : inner_join_aspect(cs)
    , presenter(presenter) {

    created_delegate =
        cs.bus.add_handler<events::thing_created>([&](events::thing_created const &e) {
        maybe_if(e.tpl.pup, [&](auto pup) {
            // New thing has a puppet. Create a puppet animations component.
            cs.emplace_component<components::puppet_animations>(e.thing, pup);

            for(auto &pup : cs.find_component<components::puppet_animations>(e.thing)) {
                // HACK: Initialize actor walk animation
                pup.second->actor_walk_animation =
                        presenter.key_presenter->play_mode(thing_id(e.thing),
                                                           flags::puppet_submode_type::Stand);
                maybe_if(pup.second->actor_walk_animation, [&](auto walk_anim) {
                    for(auto &key_state : cs.find_component<keys::key_state>(walk_anim)) {
                        key_state.second->flags = flag_set<flags::key_flag>();
                    }
                });
            }
        });
    });

    armed_mode_delegate =
        cs.bus.add_handler<events::armed_mode_changed>([&](events::armed_mode_changed const &e) {
        for(auto &pup : cs.find_component<components::puppet_animations>(e.thing)) {
            bool is_underwater = false;
            for(auto &thing : cs.find_component<components::thing>(e.thing)) {
                auto const &cur_sector = at_id(presenter.model->sectors, thing.second->sector);
                is_underwater = cur_sector.flags & flags::sector_flag::Underwater;
            }

            flags::puppet_mode_type maj_mode = flags::puppet_mode_type::unarmed;
            switch(e.mode) {
            case flags::armed_mode::unarmed:
                maj_mode = is_underwater ? flags::puppet_mode_type::swimming_unarmed
                                         : flags::puppet_mode_type::unarmed;
                break;

            case flags::armed_mode::armed:
                maj_mode = is_underwater ? flags::puppet_mode_type::swimming_armed
                                         : flags::puppet_mode_type::armed;
                break;

            case flags::armed_mode::saber:
                maj_mode = is_underwater ? flags::puppet_mode_type::swimming_saber
                                         : flags::puppet_mode_type::saber;
                break;
            }

            pup.second->puppet_mode_type = maj_mode;
        }
    });

    jumped_delegate =
        cs.bus.add_handler<events::jumped>([&](events::jumped const &e) {
        for(auto &pup : cs.find_component<components::puppet_animations>(e.thing)) {
            for(auto &thing : cs.find_component<components::thing>(e.thing)) {
                auto jump_submode = flags::puppet_submode_type::Rising;
                if(thing.second->physics_flags & flags::physics_flag::is_crouching) {
                    jump_submode = flags::puppet_submode_type::Leap;
                }

                set_walk_animation(*thing.second, *pup.second, jump_submode, 1.0f);
            }
        }
    });

    landed_delegate =
        cs.bus.add_handler<events::landed>([&](events::landed const &e) {
        auto rng = cs.find_component<components::puppet_animations>(e.thing);
        for(auto it = rng.begin(); it != rng.end(); ++it) {
            presenter.key_presenter->play_mode(thing_id(e.thing), flags::puppet_submode_type::Land);
        }
    });

    killed_delegate =
        cs.bus.add_handler<events::killed>([&](events::killed const &e) {
        for(auto &pup : cs.find_component<components::puppet_animations>(e.thing)) {
            // HACK: Stop idle animation
            maybe_if(pup.second->actor_walk_animation, [&](thing_id anim) {
                presenter.key_presenter->stop_key(e.thing, anim, 0.0f);
                pup.second->actor_walk_animation = nothing;
            });

            presenter.key_presenter->play_mode(e.thing, flags::puppet_submode_type::Death);
        }
    });
    return;
}

void puppet_animation_aspect::set_walk_animation(components::thing &thing,
                                                 components::puppet_animations &pup,
                                                 flags::puppet_submode_type type,
                                                 float speed) {
    if(thing.type == flags::thing_type::Corpse || !pup.actor_walk_animation.has_value()) {
        // Thing is dead and/or cannot play a walk animation.
        return;
    }

    keys::key_state *keyState = nullptr;
    maybe_if(pup.actor_walk_animation, [&](thing_id anim) {
            for(auto &key_state : ecs.find_component<keys::key_state>(anim)) {
                keyState = key_state.second;
            }
        });

    if(!keyState) {
        return;
    }

    auto const &maybe_submode = pup.puppet->get_mode(pup.puppet_mode_type).get_submode(type);
    maybe_if(maybe_submode, [&](content::assets::puppet_submode const *submode) {
        if(keyState->animation != submode->anim) {
            keyState->animation_time = 0.0;
        }

        keyState->animation = submode->anim;
        keyState->high_priority = submode->hi_priority;
        keyState->low_priority = submode->lo_priority;
        keyState->flags = flag_set<flags::key_flag>();
        keyState->speed = speed;
    });
}

void puppet_animation_aspect::set_walk_animation_speed(components::puppet_animations &pup,
                                                       float speed) {
    maybe_if(pup.actor_walk_animation, [&](thing_id anim) {
        for(auto &key_state : ecs.find_component<keys::key_state>(anim)) {
            key_state.second->speed = speed;
        }
    });
}

bool puppet_animation_aspect::is_walk_animation_mode(components::puppet_animations &pup,
                                                     flags::puppet_submode_type type) {
    maybe_if(pup.actor_walk_animation, [&](thing_id anim) {
        for(auto &key_state : ecs.find_component<keys::key_state>(anim)) {
            auto const &maybe_submode = pup.puppet->get_mode(pup.puppet_mode_type).get_submode(type);
            maybe_if(maybe_submode, [&](content::assets::puppet_submode const *submode) {
                return key_state.second->animation == submode->anim;
            });
        }
    });

    return false;
}

void puppet_animation_aspect::update_standing_animation(components::thing &thing,
                                                        components::puppet_animations &pup) {
    auto oriented_vel = invert(thing.orient).transform(thing.vel);
    auto run_length = length(thing.vel);

    auto vel_fb = get<1>(oriented_vel);
    auto vel_lr = get<0>(oriented_vel);
    auto turn_rate = get<1>(thing.ang_vel);

    float run_anim_speed = run_length * 20.0f;
    float turn_anim_speed = static_cast<float>(fabs(turn_rate) / 360.0);

    if(thing.physics_flags & flags::physics_flag::is_crouching) {
        if(fabs(turn_rate) > 0.0001) {
            set_walk_animation(thing, pup, flags::puppet_submode_type::CrouchForward, turn_anim_speed * 20.0f);
        }
        else if(vel_fb >= 0.0f || fabs(vel_lr) > fabs(vel_fb)) {
            set_walk_animation(thing, pup, flags::puppet_submode_type::CrouchForward, run_anim_speed);
        }
        else {
            set_walk_animation(thing, pup, flags::puppet_submode_type::CrouchBack, run_anim_speed);
        }
    }
    else {
        if(run_length < 0.001f) {
            // Idle or turning.
            if(turn_rate > 60.0f) {
                // Turning right
                set_walk_animation(thing, pup, flags::puppet_submode_type::TurnRight, turn_anim_speed);
            }
            else if(turn_rate < -60.0f) {
                // Turning left
                set_walk_animation(thing, pup, flags::puppet_submode_type::TurnLeft, turn_anim_speed);
            }
            else if(fabs(turn_rate) < 0.001) {
                set_walk_animation(thing, pup, flags::puppet_submode_type::Stand, 1.0f);
            }
            else if(!is_walk_animation_mode(pup, flags::puppet_submode_type::Stand)) {
                set_walk_animation_speed(pup, turn_anim_speed);
            }
        }
        else if(fabs(vel_lr) > fabs(vel_fb)) {
            // Strafing left or right
            if(vel_lr >= 0.0f) {
                set_walk_animation(thing, pup, flags::puppet_submode_type::StrafeRight, run_anim_speed);
            }
            else {
                set_walk_animation(thing, pup, flags::puppet_submode_type::StrafeLeft, run_anim_speed);
            }
        }
        else if(vel_fb > 0.5f) {
            // Running forward
            set_walk_animation(thing, pup, flags::puppet_submode_type::Run, run_anim_speed);
        }
        else if(vel_fb > 0.0f) {
            set_walk_animation(thing, pup, flags::puppet_submode_type::Walk, run_anim_speed);
        }
        else {
            // Walking backwards
            set_walk_animation(thing, pup, flags::puppet_submode_type::WalkBack, run_anim_speed);
        }
    }
}

void puppet_animation_aspect::update(time_delta,
                                     thing_id,
                                     components::puppet_animations &pup,
                                     components::thing &thing) {
    // Updates the idle animation loop

    // There are many possible states. This aspect tries to determine how the
    // entity is moving based on its thing properties.

    if(static_cast<int>(thing.attach_flags)) {
        // Thing is standing on a hard surface
        update_standing_animation(thing, pup);
    }
    else {
        // Thing is in freefall.
        // If the player has just jumped, the jump animation is already playing.
        // Check to see if the player has reached apogee:
        if(dot(thing.vel, make_vector(0.0f, 0.0f, -1.0f)) > 0.0f) {
            // Thing's trajectory has reached apogee.
            set_walk_animation(thing, pup, flags::puppet_submode_type::Drop, 1.0f);
        }
    }

    return;
}
<commit_msg>Fixed bug causing level startup thing number instability<commit_after>#include "puppet_animation_aspect.hpp"
#include "game/world/level_model.hpp"
#include "game/world/keys/components/key_state.hpp"
#include "game/world/keys/key_presenter.hpp"
#include "game/world/events/armed_mode_changed.hpp"
#include "game/world/events/jumped.hpp"
#include "game/world/events/landed.hpp"
#include "game/world/events/killed.hpp"
#include "game/world/events/thing_created.hpp"

using gorc::game::world::aspects::puppet_animation_aspect;

puppet_animation_aspect::puppet_animation_aspect(entity_component_system<thing_id> &cs,
                                                 level_presenter &presenter)
    : inner_join_aspect(cs)
    , presenter(presenter) {

    created_delegate =
        cs.bus.add_handler<events::thing_created>([&](events::thing_created const &e) {
        maybe_if(e.tpl.pup, [&](auto pup) {
            // New thing has a puppet. Create a puppet animations component.
            cs.emplace_component<components::puppet_animations>(e.thing, pup);
        });
    });

    armed_mode_delegate =
        cs.bus.add_handler<events::armed_mode_changed>([&](events::armed_mode_changed const &e) {
        for(auto &pup : cs.find_component<components::puppet_animations>(e.thing)) {
            bool is_underwater = false;
            for(auto &thing : cs.find_component<components::thing>(e.thing)) {
                auto const &cur_sector = at_id(presenter.model->sectors, thing.second->sector);
                is_underwater = cur_sector.flags & flags::sector_flag::Underwater;
            }

            flags::puppet_mode_type maj_mode = flags::puppet_mode_type::unarmed;
            switch(e.mode) {
            case flags::armed_mode::unarmed:
                maj_mode = is_underwater ? flags::puppet_mode_type::swimming_unarmed
                                         : flags::puppet_mode_type::unarmed;
                break;

            case flags::armed_mode::armed:
                maj_mode = is_underwater ? flags::puppet_mode_type::swimming_armed
                                         : flags::puppet_mode_type::armed;
                break;

            case flags::armed_mode::saber:
                maj_mode = is_underwater ? flags::puppet_mode_type::swimming_saber
                                         : flags::puppet_mode_type::saber;
                break;
            }

            pup.second->puppet_mode_type = maj_mode;
        }
    });

    jumped_delegate =
        cs.bus.add_handler<events::jumped>([&](events::jumped const &e) {
        for(auto &pup : cs.find_component<components::puppet_animations>(e.thing)) {
            for(auto &thing : cs.find_component<components::thing>(e.thing)) {
                auto jump_submode = flags::puppet_submode_type::Rising;
                if(thing.second->physics_flags & flags::physics_flag::is_crouching) {
                    jump_submode = flags::puppet_submode_type::Leap;
                }

                set_walk_animation(*thing.second, *pup.second, jump_submode, 1.0f);
            }
        }
    });

    landed_delegate =
        cs.bus.add_handler<events::landed>([&](events::landed const &e) {
        auto rng = cs.find_component<components::puppet_animations>(e.thing);
        for(auto it = rng.begin(); it != rng.end(); ++it) {
            presenter.key_presenter->play_mode(thing_id(e.thing), flags::puppet_submode_type::Land);
        }
    });

    killed_delegate =
        cs.bus.add_handler<events::killed>([&](events::killed const &e) {
        for(auto &pup : cs.find_component<components::puppet_animations>(e.thing)) {
            // HACK: Stop idle animation
            maybe_if(pup.second->actor_walk_animation, [&](thing_id anim) {
                presenter.key_presenter->stop_key(e.thing, anim, 0.0f);
                pup.second->actor_walk_animation = nothing;
            });

            presenter.key_presenter->play_mode(e.thing, flags::puppet_submode_type::Death);
        }
    });
    return;
}

void puppet_animation_aspect::set_walk_animation(components::thing &thing,
                                                 components::puppet_animations &pup,
                                                 flags::puppet_submode_type type,
                                                 float speed) {
    if(thing.type == flags::thing_type::Corpse || !pup.actor_walk_animation.has_value()) {
        // Thing is dead and/or cannot play a walk animation.
        return;
    }

    keys::key_state *keyState = nullptr;
    maybe_if(pup.actor_walk_animation, [&](thing_id anim) {
            for(auto &key_state : ecs.find_component<keys::key_state>(anim)) {
                keyState = key_state.second;
            }
        });

    if(!keyState) {
        return;
    }

    auto const &maybe_submode = pup.puppet->get_mode(pup.puppet_mode_type).get_submode(type);
    maybe_if(maybe_submode, [&](content::assets::puppet_submode const *submode) {
        if(keyState->animation != submode->anim) {
            keyState->animation_time = 0.0;
        }

        keyState->animation = submode->anim;
        keyState->high_priority = submode->hi_priority;
        keyState->low_priority = submode->lo_priority;
        keyState->flags = flag_set<flags::key_flag>();
        keyState->speed = speed;
    });
}

void puppet_animation_aspect::set_walk_animation_speed(components::puppet_animations &pup,
                                                       float speed) {
    maybe_if(pup.actor_walk_animation, [&](thing_id anim) {
        for(auto &key_state : ecs.find_component<keys::key_state>(anim)) {
            key_state.second->speed = speed;
        }
    });
}

bool puppet_animation_aspect::is_walk_animation_mode(components::puppet_animations &pup,
                                                     flags::puppet_submode_type type) {
    maybe_if(pup.actor_walk_animation, [&](thing_id anim) {
        for(auto &key_state : ecs.find_component<keys::key_state>(anim)) {
            auto const &maybe_submode = pup.puppet->get_mode(pup.puppet_mode_type).get_submode(type);
            maybe_if(maybe_submode, [&](content::assets::puppet_submode const *submode) {
                return key_state.second->animation == submode->anim;
            });
        }
    });

    return false;
}

void puppet_animation_aspect::update_standing_animation(components::thing &thing,
                                                        components::puppet_animations &pup) {
    auto oriented_vel = invert(thing.orient).transform(thing.vel);
    auto run_length = length(thing.vel);

    auto vel_fb = get<1>(oriented_vel);
    auto vel_lr = get<0>(oriented_vel);
    auto turn_rate = get<1>(thing.ang_vel);

    float run_anim_speed = run_length * 20.0f;
    float turn_anim_speed = static_cast<float>(fabs(turn_rate) / 360.0);

    if(thing.physics_flags & flags::physics_flag::is_crouching) {
        if(fabs(turn_rate) > 0.0001) {
            set_walk_animation(thing, pup, flags::puppet_submode_type::CrouchForward, turn_anim_speed * 20.0f);
        }
        else if(vel_fb >= 0.0f || fabs(vel_lr) > fabs(vel_fb)) {
            set_walk_animation(thing, pup, flags::puppet_submode_type::CrouchForward, run_anim_speed);
        }
        else {
            set_walk_animation(thing, pup, flags::puppet_submode_type::CrouchBack, run_anim_speed);
        }
    }
    else {
        if(run_length < 0.001f) {
            // Idle or turning.
            if(turn_rate > 60.0f) {
                // Turning right
                set_walk_animation(thing, pup, flags::puppet_submode_type::TurnRight, turn_anim_speed);
            }
            else if(turn_rate < -60.0f) {
                // Turning left
                set_walk_animation(thing, pup, flags::puppet_submode_type::TurnLeft, turn_anim_speed);
            }
            else if(fabs(turn_rate) < 0.001) {
                set_walk_animation(thing, pup, flags::puppet_submode_type::Stand, 1.0f);
            }
            else if(!is_walk_animation_mode(pup, flags::puppet_submode_type::Stand)) {
                set_walk_animation_speed(pup, turn_anim_speed);
            }
        }
        else if(fabs(vel_lr) > fabs(vel_fb)) {
            // Strafing left or right
            if(vel_lr >= 0.0f) {
                set_walk_animation(thing, pup, flags::puppet_submode_type::StrafeRight, run_anim_speed);
            }
            else {
                set_walk_animation(thing, pup, flags::puppet_submode_type::StrafeLeft, run_anim_speed);
            }
        }
        else if(vel_fb > 0.5f) {
            // Running forward
            set_walk_animation(thing, pup, flags::puppet_submode_type::Run, run_anim_speed);
        }
        else if(vel_fb > 0.0f) {
            set_walk_animation(thing, pup, flags::puppet_submode_type::Walk, run_anim_speed);
        }
        else {
            // Walking backwards
            set_walk_animation(thing, pup, flags::puppet_submode_type::WalkBack, run_anim_speed);
        }
    }
}

void puppet_animation_aspect::update(time_delta,
                                     thing_id tid,
                                     components::puppet_animations &pup,
                                     components::thing &thing) {
    // Updates the idle animation loop

    // There are many possible states. This aspect tries to determine how the
    // entity is moving based on its thing properties.

    // Create the walk animation, if one does not already exist
    if(!pup.actor_walk_animation.has_value()) {
        pup.actor_walk_animation =
            presenter.key_presenter->play_mode(tid, flags::puppet_submode_type::Stand);
        maybe_if(pup.actor_walk_animation, [&](auto walk_anim) {
            for(auto &key_state : ecs.find_component<keys::key_state>(walk_anim)) {
                key_state.second->flags = flag_set<flags::key_flag>();
            }
        });
    }

    if(static_cast<int>(thing.attach_flags)) {
        // Thing is standing on a hard surface
        update_standing_animation(thing, pup);
    }
    else {
        // Thing is in freefall.
        // If the player has just jumped, the jump animation is already playing.
        // Check to see if the player has reached apogee:
        if(dot(thing.vel, make_vector(0.0f, 0.0f, -1.0f)) > 0.0f) {
            // Thing's trajectory has reached apogee.
            set_walk_animation(thing, pup, flags::puppet_submode_type::Drop, 1.0f);
        }
    }

    return;
}
<|endoftext|>