<commit_before>#include <iostream>                                         /* allows to perform standard input and output operations */
#include <fstream>
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
#include <unistd.h>                                         /* UNIX standard function definitions */
#include <fcntl.h>                                          /* File control definitions */
#include <errno.h>                                          /* Error number definitions */
#include <termios.h>                                        /* POSIX terminal control definitions */
#include <ctype.h>                                        /* isxxx() */

const char* serialport="/dev/ttyAMA0";                      /* defines used serialport */
int serialport_bps=B38400;                                  /* defines baudrate od serialport */
int32_t EncoderL;                                           /* stores encoder value left read from md49 */
int32_t EncoderR;                                           /* stores encoder value right read from md49 */
unsigned char speed_l=128, speed_r=128;                               /* speed to set for MD49 */

int filedesc;                                               // File descriptor of serial port we will talk to
int fd;                                                     /* serial port file descriptor */
unsigned char serialBuffer[16];                             /* Serial buffer to store uart data */
struct termios orig;                                        // Port options

using namespace std;

int openSerialPort(const char * device, int bps);
void writeBytes(int descriptor, int count);
void readBytes(int descriptor, int count);
void read_MD49_Data (void);
void set_MD49_speed (unsigned char speed_l, unsigned char speed_r);

char* itoa(int value, char* result, int base) {
        // check that the base if valid
        if (base < 2 || base > 36) { *result = '\0'; return result; }

        char* ptr = result, *ptr1 = result, tmp_char;
        int tmp_value;

        do {
            tmp_value = value;
            value /= base;
            *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
        } while ( value );

        // Apply negative sign
        if (tmp_value < 0) *ptr++ = '-';
        *ptr-- = '\0';
        while(ptr1 < ptr) {
            tmp_char = *ptr;
            *ptr--= *ptr1;
            *ptr1++ = tmp_char;
        }
        return result;
    }

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

    // Open serial port
    // ****************
    filedesc = openSerialPort("/dev/ttyAMA0", serialport_bps);
    if (filedesc == -1) exit(1);
    usleep(10000);                                      // Sleep for UART to power up and set options

    while( 1 )
    {

        // Read encoder and other data from MD49
        // and put into sqlite db
        // *************************************
        read_MD49_Data();
        usleep(250000);
        // Read commands from sqlite db and
        // set speed and other commands to MD49
        // ************************************

    }// end.mainloop

    return 1;
} // end.main

int openSerialPort(const char * device, int bps){
   struct termios neu;
   char buf[128];

   //fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
   fd = open(device, O_RDWR | O_NOCTTY);

   if (fd == -1)
   {
      sprintf(buf, "openSerialPort %s error", device);
      perror(buf);
   }
   else
   {
      tcgetattr(fd, &orig); 						/* save current serial settings */
      tcgetattr(fd, &neu);
      cfmakeraw(&neu);
      //fprintf(stderr, "speed=%d\n", bps);
      cfsetispeed(&neu, bps);
      cfsetospeed(&neu, bps);
      tcflush(fd, TCIFLUSH);
      tcsetattr(fd, TCSANOW, &neu); 				/* set new serial settings */
      fcntl (fd, F_SETFL, O_RDWR);
   }
   return fd;
}

void writeBytes(int descriptor, int count) {
    if ((write(descriptor, serialBuffer, count)) == -1) {	// Send data out
        perror("Error writing");
        close(descriptor);				// Close port if there is an error
        exit(1);
    }

}

void readBytes(int descriptor, int count) {
    if (read(descriptor, serialBuffer, count) == -1) {	// Read back data into buf[]
        perror("Error reading ");
        close(descriptor);				// Close port if there is an error
        exit(1);
    }
}

void read_MD49_Data (void){
    serialBuffer[0] = 82;							// 82=R Steuerbyte um alle Daten vom MD49 zu lesen
    writeBytes(fd, 1);
    //Daten lesen und in Array schreiben
    readBytes(fd, 18);

    ofstream myfile;
    myfile.open ("example.txt");
    //myfile << "Writing this to a file.\n";

    char buffer[33];

    printf("\033[2J");        /*  clear the screen  */
    printf("\033[H");         /*  position cursor at top-left corner */
    printf ("MD49-Data read from AVR-Master: \n");
    printf("====================================================== \n");
    printf("Encoder1 Byte1: %i ",serialBuffer[0]);
    myfile << itoa(serialBuffer[0],buffer,10);
    myfile << "\n";
    printf("Byte2: %i ",serialBuffer[1]);
    myfile << itoa(serialBuffer[1],buffer,10);
    myfile << "\n";
    printf("Byte3: % i ",serialBuffer[2]);
    myfile <<  itoa(serialBuffer[2],buffer,10);
    myfile << "\n";
    printf("Byte4: %i \n",serialBuffer[3]);
    myfile <<  itoa(serialBuffer[3],buffer,10);
    myfile << "\n";
    printf("Encoder2 Byte1: %i ",serialBuffer[4]);
    myfile <<  itoa(serialBuffer[4],buffer,10);
    myfile << "\n";
    printf("Byte2: %i ",serialBuffer[5]);
    myfile <<  itoa(serialBuffer[5],buffer,10);
    myfile << "\n";
    printf("Byte3: %i ",serialBuffer[6]);
    myfile <<  itoa(serialBuffer[6],buffer,10);
    myfile << "\n";
    printf("Byte4: %i \n",serialBuffer[7]);
    myfile <<  itoa(serialBuffer[7],buffer,10);
    myfile << "\n";
    printf("EncoderL: %i ",EncoderL);
    myfile <<  itoa(EncoderL,buffer,10);
    myfile << "\n";
    printf("EncoderR: %i \n",EncoderR);
    myfile <<  itoa(EncoderR,buffer,10);
    myfile << "\n";
    printf("====================================================== \n");
    printf("Speed1: %i ",serialBuffer[8]);
    myfile << itoa(serialBuffer[8],buffer,10);
    myfile << "\n";
    printf("Speed2: %i \n",serialBuffer[9]);
    myfile << itoa(serialBuffer[9],buffer,10);
    myfile << "\n";
    printf("Volts: %i \n",serialBuffer[10]);
    myfile << itoa(serialBuffer[10],buffer,10);
    myfile << "\n";
    printf("Current1: %i ",serialBuffer[11]);
    myfile << itoa(serialBuffer[11],buffer,10);
    myfile << "\n";
    printf("Current2: %i \n",serialBuffer[12]);
    myfile << itoa(serialBuffer[12],buffer,10);
    myfile << "\n";
    printf("Error: %i \n",serialBuffer[13]);
    myfile << itoa(serialBuffer[13],buffer,10);
    myfile << "\n";
    printf("Acceleration: %i \n",serialBuffer[14]);
    myfile << itoa(serialBuffer[14],buffer,10);
    myfile << "\n";
    printf("Mode: %i \n",serialBuffer[15]);
    myfile << itoa(serialBuffer[15],buffer,10);
    myfile << "\n";
    printf("Regulator: %i \n",serialBuffer[16]);
    myfile << itoa(serialBuffer[16],buffer,10);
    myfile << "\n";
    printf("Timeout: %i \n",serialBuffer[17]);
    myfile << itoa(serialBuffer[17],buffer,10);
    myfile << "\n";

    EncoderL = serialBuffer[0] << 24;                        // Put together first encoder value
    EncoderL |= (serialBuffer[1] << 16);
    EncoderL |= (serialBuffer[2] << 8);
    EncoderL |= (serialBuffer[3]);
    EncoderR = serialBuffer[4] << 24;                        // Put together second encoder value
    EncoderR |= (serialBuffer[5] << 16);
    EncoderR |= (serialBuffer[6] << 8);
    EncoderR |= (serialBuffer[7]);

    myfile.close();
}

void set_MD49_speed (unsigned char speed_l, unsigned char speed_r){
    serialBuffer[0] = 88;					// 88 =X Steuerbyte um Commands an MD49 zu senden
    serialBuffer[1] = 115;					// 115=s Steuerbyte setSpeed
    serialBuffer[2] = speed_l;				// speed1
    serialBuffer[3] = speed_r;				// speed2
    writeBytes(fd, 4);
}
<commit_msg>Update code<commit_after>#include <iostream>                                         /* allows to perform standard input and output operations */
#include <fstream>
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
#include <unistd.h>                                         /* UNIX standard function definitions */
#include <fcntl.h>                                          /* File control definitions */
#include <errno.h>                                          /* Error number definitions */
#include <termios.h>                                        /* POSIX terminal control definitions */
#include <ctype.h>                                        /* isxxx() */

const char* serialport="/dev/ttyAMA0";                      /* defines used serialport */
int serialport_bps=B38400;                                  /* defines baudrate od serialport */
int32_t EncoderL;                                           /* stores encoder value left read from md49 */
int32_t EncoderR;                                           /* stores encoder value right read from md49 */
unsigned char speed_l=128, speed_r=128;                               /* speed to set for MD49 */

int filedesc;                                               // File descriptor of serial port we will talk to
int fd;                                                     /* serial port file descriptor */
unsigned char serialBuffer[16];                             /* Serial buffer to store uart data */
struct termios orig;                                        // Port options

using namespace std;

int openSerialPort(const char * device, int bps);
void writeBytes(int descriptor, int count);
void readBytes(int descriptor, int count);
void read_MD49_Data (void);
void set_MD49_speed (unsigned char speed_l, unsigned char speed_r);

char* itoa(int value, char* result, int base) {
        // check that the base if valid
        if (base < 2 || base > 36) { *result = '\0'; return result; }

        char* ptr = result, *ptr1 = result, tmp_char;
        int tmp_value;

        do {
            tmp_value = value;
            value /= base;
            *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
        } while ( value );

        // Apply negative sign
        if (tmp_value < 0) *ptr++ = '-';
        *ptr-- = '\0';
        while(ptr1 < ptr) {
            tmp_char = *ptr;
            *ptr--= *ptr1;
            *ptr1++ = tmp_char;
        }
        return result;
    }

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

    // Open serial port
    // ****************
    filedesc = openSerialPort("/dev/ttyAMA0", serialport_bps);
    if (filedesc == -1) exit(1);
    usleep(10000);                                      // Sleep for UART to power up and set options

    while( 1 )
    {

        // Read encoder and other data from MD49
        // and put into sqlite db
        // *************************************
        read_MD49_Data();
        usleep(250000);
        // Read commands from sqlite db and
        // set speed and other commands to MD49
        // ************************************

    }// end.mainloop

    return 1;
} // end.main

int openSerialPort(const char * device, int bps){
   struct termios neu;
   char buf[128];

   //fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
   fd = open(device, O_RDWR | O_NOCTTY);

   if (fd == -1)
   {
      sprintf(buf, "openSerialPort %s error", device);
      perror(buf);
   }
   else
   {
      tcgetattr(fd, &orig); 						/* save current serial settings */
      tcgetattr(fd, &neu);
      cfmakeraw(&neu);
      //fprintf(stderr, "speed=%d\n", bps);
      cfsetispeed(&neu, bps);
      cfsetospeed(&neu, bps);
      tcflush(fd, TCIFLUSH);
      tcsetattr(fd, TCSANOW, &neu); 				/* set new serial settings */
      fcntl (fd, F_SETFL, O_RDWR);
   }
   return fd;
}

void writeBytes(int descriptor, int count) {
    if ((write(descriptor, serialBuffer, count)) == -1) {	// Send data out
        perror("Error writing");
        close(descriptor);				// Close port if there is an error
        exit(1);
    }

}

void readBytes(int descriptor, int count) {
    if (read(descriptor, serialBuffer, count) == -1) {	// Read back data into buf[]
        perror("Error reading ");
        close(descriptor);				// Close port if there is an error
        exit(1);
    }
}

void read_MD49_Data (void){
    serialBuffer[0] = 82;							// 82=R Steuerbyte um alle Daten vom MD49 zu lesen
    writeBytes(fd, 1);
    //Daten lesen und in Array schreiben
    readBytes(fd, 18);

    ofstream myfile;
    myfile.open ("md49_data.txt");
    //myfile << "Writing this to a file.\n";

    char buffer[33];

    printf("\033[2J");        /*  clear the screen  */
    printf("\033[H");         /*  position cursor at top-left corner */
    printf ("MD49-Data read from AVR-Master: \n");
    printf("====================================================== \n");
    printf("Encoder1 Byte1: %i ",serialBuffer[0]);
    myfile << itoa(serialBuffer[0],buffer,10);
    myfile << "\n";
    printf("Byte2: %i ",serialBuffer[1]);
    myfile << itoa(serialBuffer[1],buffer,10);
    myfile << "\n";
    printf("Byte3: % i ",serialBuffer[2]);
    myfile <<  itoa(serialBuffer[2],buffer,10);
    myfile << "\n";
    printf("Byte4: %i \n",serialBuffer[3]);
    myfile <<  itoa(serialBuffer[3],buffer,10);
    myfile << "\n";
    printf("Encoder2 Byte1: %i ",serialBuffer[4]);
    myfile <<  itoa(serialBuffer[4],buffer,10);
    myfile << "\n";
    printf("Byte2: %i ",serialBuffer[5]);
    myfile <<  itoa(serialBuffer[5],buffer,10);
    myfile << "\n";
    printf("Byte3: %i ",serialBuffer[6]);
    myfile <<  itoa(serialBuffer[6],buffer,10);
    myfile << "\n";
    printf("Byte4: %i \n",serialBuffer[7]);
    myfile <<  itoa(serialBuffer[7],buffer,10);
    myfile << "\n";
    printf("EncoderL: %i ",EncoderL);
    myfile <<  itoa(EncoderL,buffer,10);
    myfile << "\n";
    printf("EncoderR: %i \n",EncoderR);
    myfile <<  itoa(EncoderR,buffer,10);
    myfile << "\n";
    printf("====================================================== \n");
    printf("Speed1: %i ",serialBuffer[8]);
    myfile << itoa(serialBuffer[8],buffer,10);
    myfile << "\n";
    printf("Speed2: %i \n",serialBuffer[9]);
    myfile << itoa(serialBuffer[9],buffer,10);
    myfile << "\n";
    printf("Volts: %i \n",serialBuffer[10]);
    myfile << itoa(serialBuffer[10],buffer,10);
    myfile << "\n";
    printf("Current1: %i ",serialBuffer[11]);
    myfile << itoa(serialBuffer[11],buffer,10);
    myfile << "\n";
    printf("Current2: %i \n",serialBuffer[12]);
    myfile << itoa(serialBuffer[12],buffer,10);
    myfile << "\n";
    printf("Error: %i \n",serialBuffer[13]);
    myfile << itoa(serialBuffer[13],buffer,10);
    myfile << "\n";
    printf("Acceleration: %i \n",serialBuffer[14]);
    myfile << itoa(serialBuffer[14],buffer,10);
    myfile << "\n";
    printf("Mode: %i \n",serialBuffer[15]);
    myfile << itoa(serialBuffer[15],buffer,10);
    myfile << "\n";
    printf("Regulator: %i \n",serialBuffer[16]);
    myfile << itoa(serialBuffer[16],buffer,10);
    myfile << "\n";
    printf("Timeout: %i \n",serialBuffer[17]);
    myfile << itoa(serialBuffer[17],buffer,10);
    myfile << "\n";

    EncoderL = serialBuffer[0] << 24;                        // Put together first encoder value
    EncoderL |= (serialBuffer[1] << 16);
    EncoderL |= (serialBuffer[2] << 8);
    EncoderL |= (serialBuffer[3]);
    EncoderR = serialBuffer[4] << 24;                        // Put together second encoder value
    EncoderR |= (serialBuffer[5] << 16);
    EncoderR |= (serialBuffer[6] << 8);
    EncoderR |= (serialBuffer[7]);

    myfile.close();
}

void set_MD49_speed (unsigned char speed_l, unsigned char speed_r){
    serialBuffer[0] = 88;					// 88 =X Steuerbyte um Commands an MD49 zu senden
    serialBuffer[1] = 115;					// 115=s Steuerbyte setSpeed
    serialBuffer[2] = speed_l;				// speed1
    serialBuffer[3] = speed_r;				// speed2
    writeBytes(fd, 4);
}
<|endoftext|>


<commit_before>#include <common.hpp>

int debugCount=0;
pair<float,float> HotspotPos[] = {
	// TOP_LEFT,
	{0.0,0.0},
	// TOP,
	{0.5,0.0},
	// TOP_RIGHT,
	{1.0,0.0},
	// LEFT,
	{0.0,0.5},
	// CENTER,
	{0.5,0.5},
	// RIGHT,
	{1.0,0.5},
	// BOTTOM_LEFT,
	{0.0,1.0},
	// BOTTOM,
	{0.5,1.0},
	// BOTTOM_RIGHT
	{1.0,1.0}
};

SDL_Color MakeColor(int r,int g,int b,int a) {
	SDL_Color color;
	color.r=r;
	color.g=g;
	color.b=b;
	color.a=a;
	return color;
}

bool equals(const float &a,const float &b) {
	return (std::fabs((a-b))<=PRECISION);
}

float closeDist(const float &from,const float &to,const float &change) {
	if (abs(from-to)<change)return to;
	if (from>to)return from - change;
	return from + change;
}

string FloatToStr(float f) {
	char s[15];
	sprintf(s,"%.2f",f);
	return s;
}
<commit_msg>Applies Comments Technique to file common.cpp<commit_after>/*
 *  File: common.cpp
 *
 *  Description:  Implements common functions
 */

#include <common.hpp>

// Global variable used as debug counter
int debugCount = 0;

// Hotspot screen positions to be used as shortcuts
// The number on the left is x axis and the right one is y axis
pair<float,float> HotspotPos[] = {
	// TOP_LEFT
	{0.0,0.0},
	// TOP
	{0.5,0.0},
	// TOP_RIGHT
	{1.0,0.0},
	// LEFT
	{0.0,0.5},
	// CENTER
	{0.5,0.5},
	// RIGHT
	{1.0,0.5},
	// BOTTOM_LEFT
	{0.0,1.0},
	// BOTTOM
	{0.5,1.0},
	// BOTTOM_RIGHT
	{1.0,1.0}
};

// Returns a color generated by the params
SDL_Color MakeColor(int r,		// red value, 	range: 0 -> 255
										int g,		// green value, range: 0 -> 255
										int b,		// blue value,	range: 0 -> 255
										int a) {	// alpha value, range: unknown
	SDL_Color color;

	color.r = r;
	color.g = g;
	color.b = b;
	color.a = a;

	return color;
}

// Function that compares two float constants
// Returns true if the difference between them is <= than 0.0001 (PRECISION)
bool equals(const float &a, const float &b) {
	return (std::fabs((a-b)) <= PRECISION);
}

// TODO: refactorate for better understanding
// Function that cannot be comprehended by mere human beings
float closeDist(const float &from, const float &to, const float &change) {
	if (abs(from - to) < change) {
		return to;
	}

	if (from > to) {
		return from - change;
	}

	return from + change;
}

// Converts a float number to a string and returns it
string FloatToStr(float f) {
	char s[15];

	sprintf(s,"%.2f",f);

	return s;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit_training.C
/// @brief Train dram
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_draminit_training.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;

extern "C"
{
    ///
    /// @brief Train dram
    /// @param[in] i_target, the McBIST of the ports of the dram you're training
    /// @param[in] i_special_training, optional CAL_STEP_ENABLE override. Used in sim, debug
    /// @return FAPI2_RC_SUCCESS iff ok
    ///
    fapi2::ReturnCode p9_mss_draminit_training( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
            const uint16_t i_special_training )
    {
        fapi2::buffer<uint16_t> l_cal_steps_enabled = i_special_training;

        FAPI_INF("Start draminit training");

        uint8_t l_reset_disable = 0;
        FAPI_TRY( mss::draminit_reset_disable(l_reset_disable) );

        // Configure the CCS engine.
        {
            fapi2::buffer<uint64_t> l_ccs_config;

            FAPI_TRY( mss::ccs::read_mode(i_target, l_ccs_config) );

            // It's unclear if we want to run with this true or false. Right now (10/15) this
            // has to be false. Shelton was unclear if this should be on or off in general BRS
            mss::ccs::stop_on_err(i_target, l_ccs_config, false);
            mss::ccs::ue_disable(i_target, l_ccs_config, false);
            mss::ccs::copy_cke_to_spare_cke(i_target, l_ccs_config, true);

            // Hm. Centaur sets this up for the longest duration possible. Can we do better?
            mss::ccs::cal_count(i_target, l_ccs_config, ~0, ~0);

#ifndef JIM_SAYS_TURN_OFF_ECC
            mss::ccs::disable_ecc(i_target, l_ccs_config);
#endif
            FAPI_TRY( mss::ccs::write_mode(i_target, l_ccs_config) );
        }

        // Clean out any previous calibration results, set bad-bits and configure the ranks.
        FAPI_DBG("MCA's on this McBIST: %d", i_target.getChildren<TARGET_TYPE_MCA>().size());

        for( auto p : i_target.getChildren<TARGET_TYPE_MCA>())
        {
            mss::ccs::program<TARGET_TYPE_MCBIST, TARGET_TYPE_MCA> l_program;

            // Setup a series of register probes which we'll see during the polling loop
            // Leaving these probes in here as we need them from time to time, but they
            // take up a lot of sim time, so we like to remove them simply
#ifdef TRAINING_POLLING_PROBES
            l_program.iv_probes =
            {
                // One block for each DP16
                {p, "wr_cntr_status0 (dp16 0)", MCA_DDRPHY_DP16_WR_CNTR_STATUS0_P0_0},
                {p, "wr_cntr_status1 (dp16 0)", MCA_DDRPHY_DP16_WR_CNTR_STATUS1_P0_0},
                {p, "wr_cntr_status2 (dp16 0)", MCA_DDRPHY_DP16_WR_CNTR_STATUS2_P0_0},
                {p, "wr_lvl_status (dp16 0)",   MCA_DDRPHY_DP16_WR_LVL_STATUS0_P0_0},

                {p, "wr_cntr_status0 (dp16 1)", MCA_DDRPHY_DP16_WR_CNTR_STATUS0_P0_1},
                {p, "wr_cntr_status1 (dp16 1)", MCA_DDRPHY_DP16_WR_CNTR_STATUS1_P0_1},
                {p, "wr_cntr_status2 (dp16 1)", MCA_DDRPHY_DP16_WR_CNTR_STATUS2_P0_1},
                {p, "wr_lvl_status (dp16 1)",   MCA_DDRPHY_DP16_WR_LVL_STATUS0_P0_1},

                {p, "wr_cntr_status0 (dp16 2)", MCA_DDRPHY_DP16_WR_CNTR_STATUS0_P0_2},
                {p, "wr_cntr_status1 (dp16 2)", MCA_DDRPHY_DP16_WR_CNTR_STATUS1_P0_2},
                {p, "wr_cntr_status2 (dp16 2)", MCA_DDRPHY_DP16_WR_CNTR_STATUS2_P0_2},
                {p, "wr_lvl_status (dp16 2)",   MCA_DDRPHY_DP16_WR_LVL_STATUS0_P0_2},

                {p, "wr_cntr_status0 (dp16 3)", MCA_DDRPHY_DP16_WR_CNTR_STATUS0_P0_3},
                {p, "wr_cntr_status1 (dp16 3)", MCA_DDRPHY_DP16_WR_CNTR_STATUS1_P0_3},
                {p, "wr_cntr_status2 (dp16 3)", MCA_DDRPHY_DP16_WR_CNTR_STATUS2_P0_3},
                {p, "wr_lvl_status (dp16 3)",   MCA_DDRPHY_DP16_WR_LVL_STATUS0_P0_3},

                {p, "wr_cntr_status0 (dp16 4)", MCA_DDRPHY_DP16_WR_CNTR_STATUS0_P0_4},
                {p, "wr_cntr_status1 (dp16 4)", MCA_DDRPHY_DP16_WR_CNTR_STATUS1_P0_4},
                {p, "wr_cntr_status2 (dp16 4)", MCA_DDRPHY_DP16_WR_CNTR_STATUS2_P0_4},
                {p, "wr_lvl_status (dp16 4)",   MCA_DDRPHY_DP16_WR_LVL_STATUS0_P0_4},
            };
#endif
            // Delays in the CCS instruction ARR1 for training are supposed to be 0xFFFF,
            // and we're supposed to poll for the done or timeout bit. But we don't want
            // to wait 0xFFFF cycles before we start polling - that's too long. So we put
            // in a best-guess of how long to wait. This, in a perfect world, would be the
            // time it takes one rank to train one training algorithm times the number of
            // ranks we're going to train. We fail-safe as worst-case we simply poll the
            // register too much - so we can tune this as we learn more.
            l_program.iv_poll.iv_initial_sim_delay = mss::DELAY_100US;
            l_program.iv_poll.iv_initial_sim_delay = 200;
            l_program.iv_poll.iv_poll_count = 0xFFFF;

            // Returned from set_rank_pairs, it tells us how many rank pairs
            // we configured on this port.
            std::vector<uint64_t> l_pairs;

#ifdef CAL_STATUS_DOESNT_REPORT_COMPLETE
            // This isn't correct - shouldn't be setting
            static const uint64_t CLEAR_CAL_COMPLETE = 0x000000000000F000;
            FAPI_TRY( mss::putScom(p, MCA_DDRPHY_PC_INIT_CAL_STATUS_P0, CLEAR_CAL_COMPLETE) );
#endif
            FAPI_TRY( mss::putScom(p, MCA_DDRPHY_PC_INIT_CAL_ERROR_P0, 0) );
            FAPI_TRY( mss::putScom(p, MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0, 0) );

            // Disable port fails as it doesn't appear the MC handles initial cal timeouts
            // correctly (cal_length.) BRS, see conversation with Brad Michael
            FAPI_TRY( mss::change_port_fail_disable(p, mss::ON ) );

            // The following registers must be configured to the correct operating environment:

            // Unclear, can probably be 0's for sim BRS
            // • Section 5.2.5.10 SEQ ODT Write Configuration {0-3} on page 422

            FAPI_TRY( mss::reset_seq_config0(p) );
            FAPI_TRY( mss::reset_seq_rd_wr_data(p) );

            FAPI_TRY( mss::reset_odt_config(p) );

            // These are reset in phy_scominit
            // • Section 5.2.6.1 WC Configuration 0 Register on page 434
            // • Section 5.2.6.2 WC Configuration 1 Register on page 436
            // • Section 5.2.6.3 WC Configuration 2 Register on page 438

            // Get our rank pairs.
            FAPI_TRY( mss::get_rank_pairs(p, l_pairs) );

            // Setup the config register
            //
            // Grab the attribute which contains the information on what cal steps we should run
            // if the i_specal_training bits have not been specified.
            if (i_special_training == 0)
            {
                FAPI_TRY( mss::cal_step_enable(p, l_cal_steps_enabled) );
            }

            FAPI_DBG("cal steps enabled: 0x%x special training: 0x%x", l_cal_steps_enabled, i_special_training);

            // Check to see if we're supposed to reset the delay values before starting training
            // don't reset if we're running special training - assumes there's a checkpoint which has valid state.
            if ((l_reset_disable == fapi2::ENUM_ATTR_MSS_DRAMINIT_RESET_DISABLE_ENABLE) && (i_special_training == 0))
            {
                FAPI_TRY( mss::dp16<TARGET_TYPE_MCA>().reset_delay_values(p, l_pairs) );
            }

            FAPI_DBG("generating calibration CCS instructions: %d rank-pairs", l_pairs.size());

            // For each rank pair we need to calibrate, pop a ccs instruction in an array and execute it.
            // NOTE: IF YOU CALIBRATE MORE THAN ONE RANK PAIR PER CCS PROGRAM, MAKE SURE TO CHANGE
            // THE PROCESSING OF THE ERRORS. (it's hard to figure out which DIMM failed, too) BRS.
            for (auto rp : l_pairs)
            {
                auto l_inst = mss::ccs::initial_cal_command<TARGET_TYPE_MCBIST>(rp);

                FAPI_DBG("exeecuting training CCS instruction: 0x%llx, 0x%llx", l_inst.arr0, l_inst.arr1);
                l_program.iv_instructions.push_back(l_inst);

                // We need to figure out how long to wait before we start polling. Each cal step has an expected
                // duration, so for each cal step which was enabled, we update the CCS program.
                FAPI_TRY( mss::cal_timer_setup(p, l_program.iv_poll, l_cal_steps_enabled) );
                FAPI_TRY( mss::setup_cal_config(p, rp, l_cal_steps_enabled) );

                // In the event of an init cal hang, CCS_STATQ(2) will assert and CCS_STATQ(3:5) = “001” to indicate a
                // timeout. Otherwise, if calibration completes, FW should inspect DDRPHY_FIR_REG bits (50) and (58)
                // for signs of a calibration error. If either bit is on, then the DDRPHY_PC_INIT_CAL_ERROR register
                // should be polled to determine which calibration step failed.

                // If we got a cal timeout, or another CCS error just leave now. If we got success, check the error
                // bits for a cal failure. We'll return the proper ReturnCode so all we need to do is FAPI_TRY.
                FAPI_TRY( mss::ccs::execute(i_target, l_program, p) );
                FAPI_TRY( mss::process_initial_cal_errors(p) );
            }
        }

    fapi_try_exit:
        FAPI_INF("End draminit training");
        return fapi2::current_err;
    }
}
<commit_msg>Change PHY PC, RC and DP16 register blocks to functional API<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit_training.C
/// @brief Train dram
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_draminit_training.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;

extern "C"
{
    ///
    /// @brief Train dram
    /// @param[in] i_target, the McBIST of the ports of the dram you're training
    /// @param[in] i_special_training, optional CAL_STEP_ENABLE override. Used in sim, debug
    /// @return FAPI2_RC_SUCCESS iff ok
    ///
    fapi2::ReturnCode p9_mss_draminit_training( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
            const uint16_t i_special_training )
    {
        fapi2::buffer<uint16_t> l_cal_steps_enabled = i_special_training;

        FAPI_INF("Start draminit training");

        uint8_t l_reset_disable = 0;
        FAPI_TRY( mss::draminit_reset_disable(l_reset_disable) );

        // Configure the CCS engine.
        {
            fapi2::buffer<uint64_t> l_ccs_config;

            FAPI_TRY( mss::ccs::read_mode(i_target, l_ccs_config) );

            // It's unclear if we want to run with this true or false. Right now (10/15) this
            // has to be false. Shelton was unclear if this should be on or off in general BRS
            mss::ccs::stop_on_err(i_target, l_ccs_config, false);
            mss::ccs::ue_disable(i_target, l_ccs_config, false);
            mss::ccs::copy_cke_to_spare_cke(i_target, l_ccs_config, true);

            // Hm. Centaur sets this up for the longest duration possible. Can we do better?
            mss::ccs::cal_count(i_target, l_ccs_config, ~0, ~0);

#ifndef JIM_SAYS_TURN_OFF_ECC
            mss::ccs::disable_ecc(i_target, l_ccs_config);
#endif
            FAPI_TRY( mss::ccs::write_mode(i_target, l_ccs_config) );
        }

        // Clean out any previous calibration results, set bad-bits and configure the ranks.
        FAPI_DBG("MCA's on this McBIST: %d", i_target.getChildren<TARGET_TYPE_MCA>().size());

        for( auto p : i_target.getChildren<TARGET_TYPE_MCA>())
        {
            mss::ccs::program<TARGET_TYPE_MCBIST, TARGET_TYPE_MCA> l_program;

            // Setup a series of register probes which we'll see during the polling loop
            // Leaving these probes in here as we need them from time to time, but they
            // take up a lot of sim time, so we like to remove them simply
#ifdef TRAINING_POLLING_PROBES
            l_program.iv_probes =
            {
                // One block for each DP16
                {p, "wr_cntr_status0 (dp16 0)", MCA_DDRPHY_DP16_WR_CNTR_STATUS0_P0_0},
                {p, "wr_cntr_status1 (dp16 0)", MCA_DDRPHY_DP16_WR_CNTR_STATUS1_P0_0},
                {p, "wr_cntr_status2 (dp16 0)", MCA_DDRPHY_DP16_WR_CNTR_STATUS2_P0_0},
                {p, "wr_lvl_status (dp16 0)",   MCA_DDRPHY_DP16_WR_LVL_STATUS0_P0_0},

                {p, "wr_cntr_status0 (dp16 1)", MCA_DDRPHY_DP16_WR_CNTR_STATUS0_P0_1},
                {p, "wr_cntr_status1 (dp16 1)", MCA_DDRPHY_DP16_WR_CNTR_STATUS1_P0_1},
                {p, "wr_cntr_status2 (dp16 1)", MCA_DDRPHY_DP16_WR_CNTR_STATUS2_P0_1},
                {p, "wr_lvl_status (dp16 1)",   MCA_DDRPHY_DP16_WR_LVL_STATUS0_P0_1},

                {p, "wr_cntr_status0 (dp16 2)", MCA_DDRPHY_DP16_WR_CNTR_STATUS0_P0_2},
                {p, "wr_cntr_status1 (dp16 2)", MCA_DDRPHY_DP16_WR_CNTR_STATUS1_P0_2},
                {p, "wr_cntr_status2 (dp16 2)", MCA_DDRPHY_DP16_WR_CNTR_STATUS2_P0_2},
                {p, "wr_lvl_status (dp16 2)",   MCA_DDRPHY_DP16_WR_LVL_STATUS0_P0_2},

                {p, "wr_cntr_status0 (dp16 3)", MCA_DDRPHY_DP16_WR_CNTR_STATUS0_P0_3},
                {p, "wr_cntr_status1 (dp16 3)", MCA_DDRPHY_DP16_WR_CNTR_STATUS1_P0_3},
                {p, "wr_cntr_status2 (dp16 3)", MCA_DDRPHY_DP16_WR_CNTR_STATUS2_P0_3},
                {p, "wr_lvl_status (dp16 3)",   MCA_DDRPHY_DP16_WR_LVL_STATUS0_P0_3},

                {p, "wr_cntr_status0 (dp16 4)", MCA_DDRPHY_DP16_WR_CNTR_STATUS0_P0_4},
                {p, "wr_cntr_status1 (dp16 4)", MCA_DDRPHY_DP16_WR_CNTR_STATUS1_P0_4},
                {p, "wr_cntr_status2 (dp16 4)", MCA_DDRPHY_DP16_WR_CNTR_STATUS2_P0_4},
                {p, "wr_lvl_status (dp16 4)",   MCA_DDRPHY_DP16_WR_LVL_STATUS0_P0_4},
            };
#endif
            // Delays in the CCS instruction ARR1 for training are supposed to be 0xFFFF,
            // and we're supposed to poll for the done or timeout bit. But we don't want
            // to wait 0xFFFF cycles before we start polling - that's too long. So we put
            // in a best-guess of how long to wait. This, in a perfect world, would be the
            // time it takes one rank to train one training algorithm times the number of
            // ranks we're going to train. We fail-safe as worst-case we simply poll the
            // register too much - so we can tune this as we learn more.
            l_program.iv_poll.iv_initial_sim_delay = mss::DELAY_100US;
            l_program.iv_poll.iv_initial_sim_delay = 200;
            l_program.iv_poll.iv_poll_count = 0xFFFF;

            // Returned from set_rank_pairs, it tells us how many rank pairs
            // we configured on this port.
            std::vector<uint64_t> l_pairs;

#ifdef CAL_STATUS_DOESNT_REPORT_COMPLETE
            // This isn't correct - shouldn't be setting
            static const uint64_t CLEAR_CAL_COMPLETE = 0x000000000000F000;
            FAPI_TRY( mss::putScom(p, MCA_DDRPHY_PC_INIT_CAL_STATUS_P0, CLEAR_CAL_COMPLETE) );
#endif
            FAPI_TRY( mss::putScom(p, MCA_DDRPHY_PC_INIT_CAL_ERROR_P0, 0) );
            FAPI_TRY( mss::putScom(p, MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0, 0) );

            // Disable port fails as it doesn't appear the MC handles initial cal timeouts
            // correctly (cal_length.) BRS, see conversation with Brad Michael
            FAPI_TRY( mss::change_port_fail_disable(p, mss::ON ) );

            // The following registers must be configured to the correct operating environment:

            // Unclear, can probably be 0's for sim BRS
            // • Section 5.2.5.10 SEQ ODT Write Configuration {0-3} on page 422

            FAPI_TRY( mss::reset_seq_config0(p) );
            FAPI_TRY( mss::reset_seq_rd_wr_data(p) );

            FAPI_TRY( mss::reset_odt_config(p) );

            // These are reset in phy_scominit
            // • Section 5.2.6.1 WC Configuration 0 Register on page 434
            // • Section 5.2.6.2 WC Configuration 1 Register on page 436
            // • Section 5.2.6.3 WC Configuration 2 Register on page 438

            // Get our rank pairs.
            FAPI_TRY( mss::get_rank_pairs(p, l_pairs) );

            // Setup the config register
            //
            // Grab the attribute which contains the information on what cal steps we should run
            // if the i_specal_training bits have not been specified.
            if (i_special_training == 0)
            {
                FAPI_TRY( mss::cal_step_enable(p, l_cal_steps_enabled) );
            }

            FAPI_DBG("cal steps enabled: 0x%x special training: 0x%x", l_cal_steps_enabled, i_special_training);

            // Check to see if we're supposed to reset the delay values before starting training
            // don't reset if we're running special training - assumes there's a checkpoint which has valid state.
            if ((l_reset_disable == fapi2::ENUM_ATTR_MSS_DRAMINIT_RESET_DISABLE_ENABLE) && (i_special_training == 0))
            {
                FAPI_TRY( mss::dp16::reset_delay_values(p, l_pairs) );
            }

            FAPI_DBG("generating calibration CCS instructions: %d rank-pairs", l_pairs.size());

            // For each rank pair we need to calibrate, pop a ccs instruction in an array and execute it.
            // NOTE: IF YOU CALIBRATE MORE THAN ONE RANK PAIR PER CCS PROGRAM, MAKE SURE TO CHANGE
            // THE PROCESSING OF THE ERRORS. (it's hard to figure out which DIMM failed, too) BRS.
            for (auto rp : l_pairs)
            {
                auto l_inst = mss::ccs::initial_cal_command<TARGET_TYPE_MCBIST>(rp);

                FAPI_DBG("exeecuting training CCS instruction: 0x%llx, 0x%llx", l_inst.arr0, l_inst.arr1);
                l_program.iv_instructions.push_back(l_inst);

                // We need to figure out how long to wait before we start polling. Each cal step has an expected
                // duration, so for each cal step which was enabled, we update the CCS program.
                FAPI_TRY( mss::cal_timer_setup(p, l_program.iv_poll, l_cal_steps_enabled) );
                FAPI_TRY( mss::setup_cal_config(p, rp, l_cal_steps_enabled) );

                // In the event of an init cal hang, CCS_STATQ(2) will assert and CCS_STATQ(3:5) = “001” to indicate a
                // timeout. Otherwise, if calibration completes, FW should inspect DDRPHY_FIR_REG bits (50) and (58)
                // for signs of a calibration error. If either bit is on, then the DDRPHY_PC_INIT_CAL_ERROR register
                // should be polled to determine which calibration step failed.

                // If we got a cal timeout, or another CCS error just leave now. If we got success, check the error
                // bits for a cal failure. We'll return the proper ReturnCode so all we need to do is FAPI_TRY.
                FAPI_TRY( mss::ccs::execute(i_target, l_program, p) );
                FAPI_TRY( mss::process_initial_cal_errors(p) );
            }
        }

    fapi_try_exit:
        FAPI_INF("End draminit training");
        return fapi2::current_err;
    }
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// File: mframework.hpp
//
// Desc: Data Mining Framework.
//
// Copyright (c) 2014-2018. veyesys.com All rights reserved.
//------------------------------------------------------------------------------
#ifndef __M_FRAME_WORK_HPP__
#define __M_FRAME_WORK_HPP__
#include "utility.hpp"
#include "debug.hpp"
#include "videotype.hpp"
#include "miningtype.hpp"
#include "mmodule.hpp"
#include "factory.hpp"
#include <QThread>
#include <qdebug.h>
#include "cppkit/ck_string.h"
#include "cppkit/ck_memory.h"
#include "cppkit/ck_command_queue.h"
#include "cppkit/ck_dynamic_library.h"
#include "cppkit/ck_byte_ptr.h"

using namespace std;
using namespace cppkit;

/* All the mining data will be post a queue to here,
    Then start a thread to peek the queue to post to each device in factory
*/

typedef command_queue<MiningRet> MModuleRetQueue;

typedef std::map<int, MiningModule *> MModuleMap;
class MFramework:public QThread
{
    Q_OBJECT
public:
	inline MFramework(Factory &pFactory);
	inline ~MFramework();
public:
	inline void run();
public:
	inline static BOOL RetHandler(s32 id, MiningRet& ret, void * pParam);
	inline BOOL RetHandler1(s32 id, MiningRet& ret);

private:
	MModuleMap m_MModules;
	MModuleRetQueue m_RetQueue;
	BOOL m_bExit;
};

BOOL MFramework::RetHandler(s32 id, MiningRet& ret, void * pParam)
{
	int dummy = errno;
	MFramework *pMFramework = (MFramework)pParam;

	if (pMFramework)
	{
		return pMFramework->RetHandler1(id, ret);
	}

	return TRUE;
}

BOOL MFramework::RetHandler1(s32 id, MiningRet& ret)
{
	m_RetQueue.post(ret);

	return TRUE;
}

void MFramework::run()
{
	MiningRet ret;
	while (m_bExit != TRUE)
	{
		if (m_RetQueue.size() > 0)
		{
			ret = m_RetQueue.pop();
			//send the ret va data to factory for showing
			continue;
		}else
		{
			ve_sleep(1000);
		}
	}
	return;
}

#endif /* __M_FRAME_WORK_HPP__ */
<commit_msg>add device change api<commit_after>//------------------------------------------------------------------------------
// File: mframework.hpp
//
// Desc: Data Mining Framework.
//
// Copyright (c) 2014-2018. veyesys.com All rights reserved.
//------------------------------------------------------------------------------
#ifndef __M_FRAME_WORK_HPP__
#define __M_FRAME_WORK_HPP__
#include "utility.hpp"
#include "debug.hpp"
#include "videotype.hpp"
#include "miningtype.hpp"
#include "mmodule.hpp"
#include "factory.hpp"
#include <QThread>
#include <qdebug.h>
#include "cppkit/ck_string.h"
#include "cppkit/ck_memory.h"
#include "cppkit/ck_command_queue.h"
#include "cppkit/ck_dynamic_library.h"
#include "cppkit/ck_byte_ptr.h"

using namespace std;
using namespace cppkit;

/* All the mining data will be post a queue to here,
    Then start a thread to peek the queue to post to each device in factory
*/

typedef command_queue<MiningRet> MModuleRetQueue;

typedef std::map<int, MiningModule *> MModuleMap;
class MFramework:public QThread
{
    Q_OBJECT
public:
	inline MFramework(Factory &pFactory);
	inline ~MFramework();
public:
	inline void run();
public:
	inline static BOOL RetHandler(s32 id, MiningRet& ret, void * pParam);
	inline BOOL RetHandler1(s32 id, MiningRet& ret);
public:
	static BOOL DeviceChangeCallbackFunc(void* pData, FactoryDeviceChangeData change);
	BOOL DeviceChangeCallbackFunc1(FactoryDeviceChangeData change);

private:
	MModuleMap m_MModules;
	MModuleRetQueue m_RetQueue;
	BOOL m_bExit;
};

BOOL MFramework::RetHandler(s32 id, MiningRet& ret, void * pParam)
{
	int dummy = errno;
	MFramework *pMFramework = (MFramework)pParam;

	if (pMFramework)
	{
		return pMFramework->RetHandler1(id, ret);
	}

	return TRUE;
}

BOOL MFramework::RetHandler1(s32 id, MiningRet& ret)
{
	m_RetQueue.post(ret);

	return TRUE;
}

void MFramework::run()
{
	MiningRet ret;
	while (m_bExit != TRUE)
	{
		if (m_RetQueue.size() > 0)
		{
			ret = m_RetQueue.pop();
			//send the ret va data to factory for showing
			continue;
		}else
		{
			ve_sleep(1000);
		}
	}
	return;
}

bool MFramework::DeviceChangeCallbackFunc(void* pData,
								FactoryDeviceChangeData change)
{
	if (pData)
	{
		MFramework * pthread = (MFramework *)pData;
		pthread->DeviceChangeCallbackFunc1(change);
	}
	return true;
}
bool MFramework::DeviceChangeCallbackFunc1(FactoryDeviceChangeData change)
{
	VDC_DEBUG( "Event Device Change Callback %d type %d Begin\n", change.id, change.type);

	if (change.type == FACTORY_DEVICE_OFFLINE)
	{

	}
	if (change.type == FACTORY_DEVICE_ONLINE)
	{

	}
	VDC_DEBUG( "Event Device Change Callback %d type %d End \n", change.id, change.type);

	return TRUE;
}

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


<commit_before>/************************************************************************************
**
* @copyright (c) 2013-2100, ChengDu Duyer Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @GFile	g_file.cpp
* @version
* @brief
* @author	duye
* @date		2013-06-20
* @note
*
*  1. 2013-06-20 duye Created this GFile
*
*/
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <g_file.h>

using namespace gsys;

// default create GFile permissions
static const GUint32 G_FILE_MASK = 0x775;

GResult FileUtil::createFile(const GInt8* filePath)
{
	return createFile(filePath, 0);
}

GResult FileUtil::createFile(const GInt8* filePath, const GUint64& initSize)
{
	GInt32 fd = ::creat(filePath, G_FILE_MASK);
	if (fd == -1)
	{
		return G_NO;
	}

	if (ftruncate(fd, initSize) == -1)
	{
		::close(fd);
		return G_NO;
	}

	::close(fd);

	return G_YES;
}

bool FileUtil::isExist(const GInt8* filePath)
{
	if (filePath == nullptr)
    {
    	return false;
    }

	if (access(filePath, 0) < 0)
    {
    	return false;
    }

    return true;
}

GResult FileUtil::removeFile(const GInt8* filePath)
{
	if (filePath == nullptr)
	{
		return G_NO;
	}

	GInt8 cmd[128] = {0};
	sprintf(cmd, "rm %s -f", filePath);
	return System::shell(cmd);
}

File::File() : m_fd(-1), m_flags(0), m_pathLen(0)
{
	m_error[0] = 0;
	m_path[0] = 0;
}

File::File(const GInt8* filePath) : m_fd(-1), m_flags(0), m_pathLen(0)
{
	GUint32 len = strlen(filePath);
	if (len < G_PATH_MAX)
	{
		memcpy(m_path, filePath, len);
		m_path[len] = 0;
		m_pathLen = len;
	}

	m_error[0] = 0;
}

File::~File()
{
	close();
}

GResult File::open(const FileOpenFlags fileOpenFlags)
{
	return open(fileOpenFlags, G_FILE_MASK);
}

GResult File::open(const FileOpenFlags fileOpenFlags, const GInt32 mode)
{
	GInt32 openFlags = 0;
	if (fileOpenFlags | G_OPEN_READ)
	{
		openFlags = O_RDONLY;
	}
	else if (fileOpenFlags | G_OPEN_WRITE)
	{
		openFlags = O_WRONLY | O_CREAT;
	}
	else if (fileOpenFlags | G_OPEN_RDWR)
	{
		openFlags = O_RDWR | O_CREAT;
	}
	else if (fileOpenFlags | G_OPEN_APPEND)
	{
		if (openFlags == 0)
		{
			return G_NO;
		}

		openFlags |= O_APPEND;
	}

	if (openFlags == 0)
	{
		setError("input open mode error");
		return G_NO;
	}

	return orgOpen(openFlags, mode);
}

GResult File::close()
{
	if (m_fd < 0)
	{
		setError("file don't open");
		return G_NO;
	}

	GResult ret = (::close(m_fd) != -1 ? G_YES : G_NO);

	m_fd = -1;
	m_path[0] = 0;
	m_flags = 0;

	return ret;
}

GInt64 File::getSize()
{
	if (m_fd <= 0)
	{
		setError("file don't open");
		return G_NO;
	}

    struct stat	fileStat;
	fstat(m_fd, &fileStat);

	return (GInt64)(fileStat.st_size);
}

GInt64 File::seek(const GInt64 offset, const FileSeekFlags& flags)
{
	if (m_fd <= 0)
	{
		setError("file don't open");
		return G_NO;
	}

	GInt32 sysFlags = -1;

	switch(flags)
	{
	case G_SEEK_BEG:
		sysFlags = SEEK_SET;
		break;
	case G_SEEK_CUR:
		sysFlags = SEEK_CUR;
		break;
	case G_SEEK_END:
		sysFlags = SEEK_END;
		break;
	default:
		return G_NO;
		break;
	}

	return ::lseek(m_fd, offset, sysFlags);
}

GInt64 File::tell()
{
	return seek(0, G_SEEK_CUR);
}

GInt64 File::read(GInt8* buffer, const GUint64 size)
{
	if (buffer == NULL || size <= 0)
	{
		setError("input parameter is error");
		return G_NO;
	}

	if (m_fd <= 0)
	{
		setError("file don't open");
		return G_NO;
	}

	return ::read(m_fd, buffer, size);
}

GInt64 File::write(const GInt8* data, const GUint64 length)
{
	if (data == NULL || length <= 0)
	{
		setError("input parameter is error");
		return G_NO;
	}

	if (m_fd <= 0)
	{
		setError("file don't open");
		return G_NO;
	}

	return ::write(m_fd, data, length);
}

GInt8* File::getError()
{
	return m_error;
}

GResult File::orgOpen(const GInt32 flags, const GUint32 mode)
{
	if (m_fd > 0)
	{
		setError("file had opened");
		return G_NO;
	}

	if (m_pathLen == 0)
	{
		setError("hasn't set file path");
		return G_NO;
	}

	m_fd = ::open(m_path, flags, mode);
	if (m_fd > 0)
	{
		m_flags = flags;
	}
	else
	{
		setError("open file failed, check whether exist this file path");
	}

	return (m_fd != -1 ? true : false);
}

void File::setError(const GInt8* args, ...)
{
	System::pformat(m_error, G_ERROR_BUF_SIZE, args);
}
<commit_msg>Update g_file.cpp<commit_after>/************************************************************************************
**
* @copyright (c) 2013-2100, ChengDu Duyer Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @GFile    g_file.cpp
* @version
* @brief
* @author   duye
* @date	    2013-06-20
* @note
*
*  1. 2013-06-20 duye Created this GFile
*
*/
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <g_file.h>

namespace gsys {

// default create GFile permissions
static const GUint32 G_FILE_MASK = 0x775;

GResult FileUtil::createFile(const GInt8* filePath)
{
    return createFile(filePath, 0);
}

GResult FileUtil::createFile(const GInt8* filePath, const GUint64& initSize)
{
    GInt32 fd = ::creat(filePath, G_FILE_MASK);
    if (fd == -1)
    {
    	return G_NO;
    }

    if (ftruncate(fd, initSize) == -1)
    {
    	::close(fd);
    	return G_NO;
    }

    ::close(fd);

    return G_YES;
}

bool FileUtil::isExist(const GInt8* filePath)
{
    if (filePath == nullptr)
    {
    	return false;
    }

    if (access(filePath, 0) < 0)
    {
    	return false;
    }

    return true;
}

GResult FileUtil::removeFile(const GInt8* filePath)
{
    if (filePath == nullptr)
    {
    	return G_NO;
    }

    GInt8 cmd[128] = {0};
    sprintf(cmd, "rm %s -f", filePath);
    return System::shell(cmd);
}

File::File() : m_fd(-1), m_flags(0), m_pathLen(0)
{
    m_error[0] = 0;
    m_path[0] = 0;
}

File::File(const GInt8* filePath) : m_fd(-1), m_flags(0), m_pathLen(0)
{
    GUint32 len = strlen(filePath);
    if (len < G_PATH_MAX)
    {
    	memcpy(m_path, filePath, len);
    	m_path[len] = 0;
    	m_pathLen = len;
    }

    m_error[0] = 0;
}

File::~File()
{
    close();
}

GResult File::open(const FileOpenFlags fileOpenFlags)
{
    return open(fileOpenFlags, G_FILE_MASK);
}

GResult File::open(const FileOpenFlags fileOpenFlags, const GInt32 mode)
{
    GInt32 openFlags = 0;
    if (fileOpenFlags | G_OPEN_READ)
    {
    	openFlags = O_RDONLY;
    }
    else if (fileOpenFlags | G_OPEN_WRITE)
    {
        openFlags = O_WRONLY | O_CREAT;
    }
    else if (fileOpenFlags | G_OPEN_RDWR)
    {
    	openFlags = O_RDWR | O_CREAT;
    }
    else if (fileOpenFlags | G_OPEN_APPEND)
    {
    	if (openFlags == 0)
    	{
            return G_NO;
    	}
        openFlags |= O_APPEND;
    }

    if (openFlags == 0)
    {
    	setError("input open mode error");
    	return G_NO;
    }

    return orgOpen(openFlags, mode);
}

GResult File::close()
{
    if (m_fd < 0)
    {
        setError("file don't open");
        return G_NO;
    }

    GResult ret = (::close(m_fd) != -1 ? G_YES : G_NO);

    m_fd = -1;
    m_path[0] = 0;
    m_flags = 0;

    return ret;
}

GInt64 File::getSize()
{
    if (m_fd <= 0)
    {
    	setError("file don't open");
    	return G_NO;
    }

    struct stat	fileStat;
    fstat(m_fd, &fileStat);

    return (GInt64)(fileStat.st_size);
}

GInt64 File::seek(const GInt64 offset, const FileSeekFlags& flags)
{
    if (m_fd <= 0)
    {
    	setError("file don't open");
    	return G_NO;
    }

    GInt32 sysFlags = -1;

    switch(flags)
    {
	case G_SEEK_BEG:
            sysFlags = SEEK_SET;
            break;
	case G_SEEK_CUR:
            sysFlags = SEEK_CUR;
            break;
	case G_SEEK_END:
            sysFlags = SEEK_END;
            break;
	default:
	    return G_NO;
	    break;
    }

    return ::lseek(m_fd, offset, sysFlags);
}

GInt64 File::tell()
{
    return seek(0, G_SEEK_CUR);
}

GInt64 File::read(GInt8* buffer, const GUint64 size)
{
    if (buffer == NULL || size <= 0)
    {
    	setError("input parameter is error");
    	return G_NO;
    }

    if (m_fd <= 0)
    {
    	setError("file don't open");
    	return G_NO;
    }

    return ::read(m_fd, buffer, size);
}

GInt64 File::write(const GInt8* data, const GUint64 length)
{
    if (data == NULL || length <= 0)
    {
    	setError("input parameter is error");
    	return G_NO;
    }

    if (m_fd <= 0)
    {
        setError("file don't open");
        return G_NO;
    }

    return ::write(m_fd, data, length);
}

GInt8* File::getError()
{
    return m_error;
}

GResult File::orgOpen(const GInt32 flags, const GUint32 mode)
{
    if (m_fd > 0)
    {
    	setError("file had opened");
    	return G_NO;
    }

    if (m_pathLen == 0)
    {
    	setError("hasn't set file path");
    	return G_NO;
    }

    m_fd = ::open(m_path, flags, mode);
    if (m_fd > 0)
    {
    	m_flags = flags;
    }
    else
    {
    	setError("open file failed, check whether exist this file path");
    }

    return (m_fd != -1 ? true : false);
}

void File::setError(const GInt8* args, ...)
{
    System::pformat(m_error, G_ERROR_BUF_SIZE, args);
}
<|endoftext|>


<commit_before>/*
 * SPDX-FileCopyrightText: 2016-2016 CSSlayer <wengxt@gmail.com>
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 *
 */

#include "chttrans.h"
#include "config.h"
#include <fcitx-config/iniparser.h>
#include <fcitx-utils/i18n.h>
#include <fcitx-utils/standardpath.h>
#include <fcitx-utils/utf8.h>
#include <fcitx/addonfactory.h>
#include <fcitx/addonmanager.h>
#include <fcitx/inputmethodentry.h>
#include <fcntl.h>
#ifdef ENABLE_OPENCC
#include "chttrans-opencc.h"
#endif
#include "chttrans-native.h"
#include <fcitx/inputcontext.h>
#include <fcitx/userinterfacemanager.h>

using namespace fcitx;

static ChttransIMType inputMethodType(const InputMethodEntry &entry) {
    if (entry.languageCode() == "zh_CN") {
        return ChttransIMType::Simp;
    }
    if (entry.languageCode() == "zh_HK" || entry.languageCode() == "zh_TW") {
        return ChttransIMType::Trad;
    }
    return ChttransIMType::Other;
}

Chttrans::Chttrans(fcitx::Instance *instance) : instance_(instance) {
    instance_->userInterfaceManager().registerAction("chttrans",
                                                     &toggleAction_);
    reloadConfig();
#ifdef ENABLE_OPENCC
    backends_.emplace(ChttransEngine::OpenCC,
                      std::make_unique<OpenCCBackend>());
#endif
    backends_.emplace(ChttransEngine::Native,
                      std::make_unique<NativeBackend>());

    eventHandler_ = instance_->watchEvent(
        EventType::InputContextKeyEvent, EventWatcherPhase::Default,
        [this](Event &event) {
            auto &keyEvent = static_cast<KeyEvent &>(event);
            if (keyEvent.isRelease()) {
                return;
            }
            auto *ic = keyEvent.inputContext();
            auto *engine = instance_->inputMethodEngine(ic);
            const auto *entry = instance_->inputMethodEntry(ic);
            if (!engine || !entry ||
                !toggleAction_.isParent(&ic->statusArea())) {
                return;
            }
            auto type = inputMethodType(*entry);
            if (type == ChttransIMType::Other) {
                return;
            }
            if (keyEvent.key().checkKeyList(config_.hotkey.value())) {
                toggle(ic);
                bool tradEnabled = convertType(ic) == ChttransIMType::Trad;
                if (notifications()) {
                    notifications()->call<INotifications::showTip>(
                        "fcitx-chttrans-toggle",
                        _("Simplified and Traditional Chinese Translation"),
                        tradEnabled ? "fcitx-chttrans-active"
                                    : "fcitx-chttrans-inactive",
                        tradEnabled ? _("Switch to Simplified Chinese")
                                    : _("Switch to Traditional Chinese"),
                        tradEnabled ? _("Traditional Chinese is enabled.")
                                    : _("Simplified Chinese is enabled."),
                        -1);
                }
                keyEvent.filterAndAccept();
                ic->updateUserInterface(UserInterfaceComponent::InputPanel);
            }
        });
    outputFilterConn_ = instance_->connect<Instance::OutputFilter>(
        [this](InputContext *inputContext, Text &text) {
            if (!toggleAction_.isParent(&inputContext->statusArea()) ||
                !needConvert(inputContext)) {
                return;
            }
            auto type = convertType(inputContext);
            auto oldString = text.toString();
            auto oldLength = utf8::lengthValidated(oldString);
            if (oldLength == utf8::INVALID_LENGTH) {
                return;
            }
            auto newString = convert(type, oldString);
            auto newLength = utf8::lengthValidated(newString);
            if (newLength == utf8::INVALID_LENGTH) {
                return;
            }
            Text newText;
            size_t off = 0;
            size_t remainLength = newLength;
            for (size_t i = 0; i < text.size(); i++) {
                auto segmentLength = utf8::length(text.stringAt(i));
                if (remainLength < segmentLength) {
                    segmentLength = remainLength;
                }
                remainLength -= segmentLength;
                size_t segmentByteLength = utf8::ncharByteLength(
                    newString.begin() + off, segmentLength);
                newText.append(newString.substr(off, segmentByteLength),
                               text.formatAt(i));
                off = off + segmentByteLength;
            }
            if (text.cursor() >= 0) {
                auto length = utf8::length(oldString, 0, text.cursor());
                if (length > newLength) {
                    length = newLength;
                }
                newText.setCursor(
                    utf8::ncharByteLength(newText.toString().begin(), length));
            } else {
                newText.setCursor(text.cursor());
            }
            text = std::move(newText);
        });
    commitFilterConn_ = instance_->connect<Instance::CommitFilter>(
        [this](InputContext *inputContext, std::string &str) {
            if (!toggleAction_.isParent(&inputContext->statusArea()) ||
                !needConvert(inputContext)) {
                return;
            }
            auto type = convertType(inputContext);
            str = convert(type, str);
        });
}

void Chttrans::toggle(InputContext *ic) {
    auto *engine = instance_->inputMethodEngine(ic);
    const auto *entry = instance_->inputMethodEntry(ic);
    if (!engine || !entry || !toggleAction_.isParent(&ic->statusArea())) {
        return;
    }
    auto type = inputMethodType(*entry);
    if (type == ChttransIMType::Other) {
        return;
    }
    if (enabledIM_.count(entry->uniqueName())) {
        enabledIM_.erase(entry->uniqueName());
    } else {
        enabledIM_.insert(entry->uniqueName());
    }
    toggleAction_.update(ic);
}

void Chttrans::reloadConfig() {
    readAsIni(config_, "conf/chttrans.conf");
    populateConfig();
}

void Chttrans::populateConfig() {
    enabledIM_.clear();
    enabledIM_.insert(config_.enabledIM.value().begin(),
                      config_.enabledIM.value().end());
}

void Chttrans::save() {
    std::vector<std::string> values_;
    for (const auto &id : enabledIM_) {
        values_.push_back(id);
    }
    config_.enabledIM.setValue(std::move(values_));

    safeSaveAsIni(config_, "conf/chttrans.conf");
}

std::string Chttrans::convert(ChttransIMType type, const std::string &str) {
    auto iter = backends_.find(config_.engine.value());
    if (iter == backends_.end()) {
        iter = backends_.find(ChttransEngine::Native);
    }
    if (iter == backends_.end() || !iter->second->load()) {
        return str;
    }

    if (type == ChttransIMType::Trad) {
        return iter->second->convertSimpToTrad(str);
    }
    return iter->second->convertTradToSimp(str);
}

bool Chttrans::needConvert(fcitx::InputContext *inputContext) {
    auto *engine = instance_->inputMethodEngine(inputContext);
    const auto *entry = instance_->inputMethodEntry(inputContext);
    if (!engine || !entry) {
        return false;
    }
    auto type = inputMethodType(*entry);
    if (type == ChttransIMType::Other) {
        return false;
    }

    return enabledIM_.count(entry->uniqueName());
}

ChttransIMType Chttrans::convertType(fcitx::InputContext *inputContext) {
    auto *engine = instance_->inputMethodEngine(inputContext);
    const auto *entry = instance_->inputMethodEntry(inputContext);
    if (!engine || !entry) {
        return ChttransIMType::Other;
    }
    auto type = inputMethodType(*entry);
    if (type == ChttransIMType::Other) {
        return ChttransIMType::Other;
    }

    if (!enabledIM_.count(entry->uniqueName())) {
        return type;
    }
    return type == ChttransIMType::Simp ? ChttransIMType::Trad
                                        : ChttransIMType::Simp;
}

class ChttransModuleFactory : public AddonFactory {
    AddonInstance *create(AddonManager *manager) override {
        return new Chttrans(manager->instance());
    }
};

FCITX_ADDON_FACTORY(ChttransModuleFactory)
<commit_msg>Fix wrong string in chttrans notification<commit_after>/*
 * SPDX-FileCopyrightText: 2016-2016 CSSlayer <wengxt@gmail.com>
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 *
 */

#include "chttrans.h"
#include "config.h"
#include <fcitx-config/iniparser.h>
#include <fcitx-utils/i18n.h>
#include <fcitx-utils/standardpath.h>
#include <fcitx-utils/utf8.h>
#include <fcitx/addonfactory.h>
#include <fcitx/addonmanager.h>
#include <fcitx/inputmethodentry.h>
#include <fcntl.h>
#ifdef ENABLE_OPENCC
#include "chttrans-opencc.h"
#endif
#include "chttrans-native.h"
#include <fcitx/inputcontext.h>
#include <fcitx/userinterfacemanager.h>

using namespace fcitx;

static ChttransIMType inputMethodType(const InputMethodEntry &entry) {
    if (entry.languageCode() == "zh_CN") {
        return ChttransIMType::Simp;
    }
    if (entry.languageCode() == "zh_HK" || entry.languageCode() == "zh_TW") {
        return ChttransIMType::Trad;
    }
    return ChttransIMType::Other;
}

Chttrans::Chttrans(fcitx::Instance *instance) : instance_(instance) {
    instance_->userInterfaceManager().registerAction("chttrans",
                                                     &toggleAction_);
    reloadConfig();
#ifdef ENABLE_OPENCC
    backends_.emplace(ChttransEngine::OpenCC,
                      std::make_unique<OpenCCBackend>());
#endif
    backends_.emplace(ChttransEngine::Native,
                      std::make_unique<NativeBackend>());

    eventHandler_ = instance_->watchEvent(
        EventType::InputContextKeyEvent, EventWatcherPhase::Default,
        [this](Event &event) {
            auto &keyEvent = static_cast<KeyEvent &>(event);
            if (keyEvent.isRelease()) {
                return;
            }
            auto *ic = keyEvent.inputContext();
            auto *engine = instance_->inputMethodEngine(ic);
            const auto *entry = instance_->inputMethodEntry(ic);
            if (!engine || !entry ||
                !toggleAction_.isParent(&ic->statusArea())) {
                return;
            }
            auto type = inputMethodType(*entry);
            if (type == ChttransIMType::Other) {
                return;
            }
            if (keyEvent.key().checkKeyList(config_.hotkey.value())) {
                toggle(ic);
                bool tradEnabled = convertType(ic) == ChttransIMType::Trad;
                if (notifications()) {
                    notifications()->call<INotifications::showTip>(
                        "fcitx-chttrans-toggle",
                        _("Simplified and Traditional Chinese Translation"),
                        tradEnabled ? "fcitx-chttrans-active"
                                    : "fcitx-chttrans-inactive",
                        tradEnabled ? _("Switch to Traditional Chinese")
                                    : _("Switch to Simplified Chinese"),
                        tradEnabled ? _("Traditional Chinese is enabled.")
                                    : _("Simplified Chinese is enabled."),
                        -1);
                }
                keyEvent.filterAndAccept();
                ic->updateUserInterface(UserInterfaceComponent::InputPanel);
            }
        });
    outputFilterConn_ = instance_->connect<Instance::OutputFilter>(
        [this](InputContext *inputContext, Text &text) {
            if (!toggleAction_.isParent(&inputContext->statusArea()) ||
                !needConvert(inputContext)) {
                return;
            }
            auto type = convertType(inputContext);
            auto oldString = text.toString();
            auto oldLength = utf8::lengthValidated(oldString);
            if (oldLength == utf8::INVALID_LENGTH) {
                return;
            }
            auto newString = convert(type, oldString);
            auto newLength = utf8::lengthValidated(newString);
            if (newLength == utf8::INVALID_LENGTH) {
                return;
            }
            Text newText;
            size_t off = 0;
            size_t remainLength = newLength;
            for (size_t i = 0; i < text.size(); i++) {
                auto segmentLength = utf8::length(text.stringAt(i));
                if (remainLength < segmentLength) {
                    segmentLength = remainLength;
                }
                remainLength -= segmentLength;
                size_t segmentByteLength = utf8::ncharByteLength(
                    newString.begin() + off, segmentLength);
                newText.append(newString.substr(off, segmentByteLength),
                               text.formatAt(i));
                off = off + segmentByteLength;
            }
            if (text.cursor() >= 0) {
                auto length = utf8::length(oldString, 0, text.cursor());
                if (length > newLength) {
                    length = newLength;
                }
                newText.setCursor(
                    utf8::ncharByteLength(newText.toString().begin(), length));
            } else {
                newText.setCursor(text.cursor());
            }
            text = std::move(newText);
        });
    commitFilterConn_ = instance_->connect<Instance::CommitFilter>(
        [this](InputContext *inputContext, std::string &str) {
            if (!toggleAction_.isParent(&inputContext->statusArea()) ||
                !needConvert(inputContext)) {
                return;
            }
            auto type = convertType(inputContext);
            str = convert(type, str);
        });
}

void Chttrans::toggle(InputContext *ic) {
    auto *engine = instance_->inputMethodEngine(ic);
    const auto *entry = instance_->inputMethodEntry(ic);
    if (!engine || !entry || !toggleAction_.isParent(&ic->statusArea())) {
        return;
    }
    auto type = inputMethodType(*entry);
    if (type == ChttransIMType::Other) {
        return;
    }
    if (enabledIM_.count(entry->uniqueName())) {
        enabledIM_.erase(entry->uniqueName());
    } else {
        enabledIM_.insert(entry->uniqueName());
    }
    toggleAction_.update(ic);
}

void Chttrans::reloadConfig() {
    readAsIni(config_, "conf/chttrans.conf");
    populateConfig();
}

void Chttrans::populateConfig() {
    enabledIM_.clear();
    enabledIM_.insert(config_.enabledIM.value().begin(),
                      config_.enabledIM.value().end());
}

void Chttrans::save() {
    std::vector<std::string> values_;
    for (const auto &id : enabledIM_) {
        values_.push_back(id);
    }
    config_.enabledIM.setValue(std::move(values_));

    safeSaveAsIni(config_, "conf/chttrans.conf");
}

std::string Chttrans::convert(ChttransIMType type, const std::string &str) {
    auto iter = backends_.find(config_.engine.value());
    if (iter == backends_.end()) {
        iter = backends_.find(ChttransEngine::Native);
    }
    if (iter == backends_.end() || !iter->second->load()) {
        return str;
    }

    if (type == ChttransIMType::Trad) {
        return iter->second->convertSimpToTrad(str);
    }
    return iter->second->convertTradToSimp(str);
}

bool Chttrans::needConvert(fcitx::InputContext *inputContext) {
    auto *engine = instance_->inputMethodEngine(inputContext);
    const auto *entry = instance_->inputMethodEntry(inputContext);
    if (!engine || !entry) {
        return false;
    }
    auto type = inputMethodType(*entry);
    if (type == ChttransIMType::Other) {
        return false;
    }

    return enabledIM_.count(entry->uniqueName());
}

ChttransIMType Chttrans::convertType(fcitx::InputContext *inputContext) {
    auto *engine = instance_->inputMethodEngine(inputContext);
    const auto *entry = instance_->inputMethodEntry(inputContext);
    if (!engine || !entry) {
        return ChttransIMType::Other;
    }
    auto type = inputMethodType(*entry);
    if (type == ChttransIMType::Other) {
        return ChttransIMType::Other;
    }

    if (!enabledIM_.count(entry->uniqueName())) {
        return type;
    }
    return type == ChttransIMType::Simp ? ChttransIMType::Trad
                                        : ChttransIMType::Simp;
}

class ChttransModuleFactory : public AddonFactory {
    AddonInstance *create(AddonManager *manager) override {
        return new Chttrans(manager->instance());
    }
};

FCITX_ADDON_FACTORY(ChttransModuleFactory)
<|endoftext|>


<commit_before>/* Copyright (C) 2003 MySQL AB

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

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

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/************************************************************************************************
Name:          NdbRecAttr.C
Include:
Link:
Author:        UABRONM Mikael Ronstrm UAB/B/SD
Date:          971206
Version:       0.1
Description:   Interface between TIS and NDB
Documentation:
Adjust:  971206  UABRONM First version
************************************************************************************************/
#include <ndb_global.h>
#include <NdbOut.hpp>
#include <NdbRecAttr.hpp>
#include <NdbBlob.hpp>
#include "NdbDictionaryImpl.hpp"
#include <NdbTCP.h>

NdbRecAttr::NdbRecAttr()
{
  init();
}

NdbRecAttr::~NdbRecAttr()
{
  release();
}

int
NdbRecAttr::setup(const class NdbDictionary::Column* col, char* aValue)
{
  return setup(&(col->m_impl), aValue);
}
int
NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
{
  Uint32 tAttrSize = anAttrInfo->m_attrSize;
  Uint32 tArraySize = anAttrInfo->m_arraySize;
  Uint32 tAttrByteSize = tAttrSize * tArraySize;

  m_column = anAttrInfo;

  theAttrId = anAttrInfo->m_attrId;
  theAttrSize = tAttrSize;
  theArraySize = tArraySize;
  theValue = aValue;
  theNULLind = 0;
  m_nullable = anAttrInfo->m_nullable;

  // check alignment to signal data
  // a future version could check alignment per data type as well

  if (aValue != NULL && (UintPtr(aValue)&3) == 0 && (tAttrByteSize&3) == 0) {
    theStorageX = NULL;
    theRef = aValue;
    return 0;
  }
  if (tAttrByteSize <= 32) {
    theStorageX = NULL;
    theStorage[0] = 0;
    theStorage[1] = 0;
    theStorage[2] = 0;
    theStorage[3] = 0;
    theRef = theStorage;
    return 0;
  }
  Uint32 tSize = (tAttrByteSize + 7) >> 3;
  Uint64* tRef = new Uint64[tSize];
  if (tRef != NULL) {
    for (Uint32 i = 0; i < tSize; i++) {
      tRef[i] = 0;
    }
    theStorageX = tRef;
    theRef = tRef;
    return 0;
  }
  return -1;
}

void
NdbRecAttr::copyout()
{
  char* tRef = (char*)theRef;
  char* tValue = theValue;
  if (tRef != tValue && tRef != NULL && tValue != NULL) {
    Uint32 n = theAttrSize * theArraySize;
    while (n-- > 0) {
      *tValue++ = *tRef++;
    }
  }
}

NdbRecAttr *
NdbRecAttr::clone() const {
  NdbRecAttr * ret = new NdbRecAttr();

  ret->theAttrId = theAttrId;
  ret->theNULLind = theNULLind;
  ret->theAttrSize = theAttrSize;
  ret->theArraySize = theArraySize;
  ret->m_column = m_column;

  Uint32 n = theAttrSize * theArraySize;
  if(n <= 32){
    ret->theRef = (char*)&ret->theStorage[0];
    ret->theStorageX = 0;
    ret->theValue = 0;
  } else {
    ret->theStorageX = new Uint64[((n + 7) >> 3)];
    ret->theRef = (char*)ret->theStorageX;
    ret->theValue = 0;
  }
  memcpy(ret->theRef, theRef, n);
  return ret;
}

bool
NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz){
  const Uint32 n = (theAttrSize * theArraySize + 3) >> 2;
  if(n == sz){
    theNULLind = 0;
    if(!copyoutRequired())
      memcpy(theRef, data, 4 * sz);
    else
      memcpy(theValue, data, theAttrSize * theArraySize);
    return true;
  } else if(sz == 0){
    setNULL();
    return true;
  }
  return false;
}

NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
{
  if (r.isNULL())
  {
    out << "[NULL]";
    return out;
  }

  if (r.arraySize() > 1)
    out << "[";

  for (Uint32 j = 0; j < r.arraySize(); j++)
  {
    if (j > 0)
      out << " ";

    switch(r.getType())
      {
      case NdbDictionary::Column::Bigunsigned:
	out << r.u_64_value();
	break;
      case NdbDictionary::Column::Bit:
	out << hex << "H'" << r.u_32_value() << dec;
	break;
      case NdbDictionary::Column::Unsigned:
	out << r.u_32_value();
	break;
      case NdbDictionary::Column::Smallunsigned:
	out << r.u_short_value();
	break;
      case NdbDictionary::Column::Tinyunsigned:
	out << (unsigned) r.u_char_value();
	break;
      case NdbDictionary::Column::Bigint:
	out << r.int64_value();
	break;
      case NdbDictionary::Column::Int:
	out << r.int32_value();
	break;
      case NdbDictionary::Column::Smallint:
	out << r.short_value();
	break;
      case NdbDictionary::Column::Tinyint:
	out << (int) r.char_value();
	break;
      case NdbDictionary::Column::Char:
	out.print("%.*s", r.arraySize(), r.aRef());
	j = r.arraySize();
	break;
      case NdbDictionary::Column::Varchar:
	{
	  short len = ntohs(r.u_short_value());
	  out.print("%.*s", len, r.aRef()+2);
	}
	j = r.arraySize();
      break;
      case NdbDictionary::Column::Float:
	out << r.float_value();
	break;
      case NdbDictionary::Column::Double:
	out << r.double_value();
	break;
      case NdbDictionary::Column::Blob:
        {
          const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
          out << h->length << ":";
          const unsigned char* p = (const unsigned char*)(h + 1);
          unsigned n = r.arraySize() - sizeof(*h);
          for (unsigned k = 0; k < n && k < h->length; k++)
            out.print("%02X", (int)p[k]);
          j = r.arraySize();
        }
        break;
      case NdbDictionary::Column::Text:
        {
          const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
          out << h->length << ":";
          const unsigned char* p = (const unsigned char*)(h + 1);
          unsigned n = r.arraySize() - sizeof(*h);
          for (unsigned k = 0; k < n && k < h->length; k++)
            out.print("%c", (int)p[k]);
          j = r.arraySize();
        }
        break;
      default: /* no print functions for the rest, just print type */
	out << (int) r.getType();
	j = r.arraySize();
	if (j > 1)
	  out << " " << j << " times";
	break;
      }
  }

  if (r.arraySize() > 1)
  {
    out << "]";
  }

  return out;
}
<commit_msg>improved print routine for NdbRecAttr<commit_after>/* Copyright (C) 2003 MySQL AB

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

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

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <ndb_global.h>
#include <NdbOut.hpp>
#include <NdbRecAttr.hpp>
#include <NdbBlob.hpp>
#include "NdbDictionaryImpl.hpp"
#include <NdbTCP.h>

NdbRecAttr::NdbRecAttr()
{
  init();
}

NdbRecAttr::~NdbRecAttr()
{
  release();
}

int
NdbRecAttr::setup(const class NdbDictionary::Column* col, char* aValue)
{
  return setup(&(col->m_impl), aValue);
}
int
NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
{
  Uint32 tAttrSize = anAttrInfo->m_attrSize;
  Uint32 tArraySize = anAttrInfo->m_arraySize;
  Uint32 tAttrByteSize = tAttrSize * tArraySize;

  m_column = anAttrInfo;

  theAttrId = anAttrInfo->m_attrId;
  theAttrSize = tAttrSize;
  theArraySize = tArraySize;
  theValue = aValue;
  theNULLind = 0;
  m_nullable = anAttrInfo->m_nullable;

  // check alignment to signal data
  // a future version could check alignment per data type as well

  if (aValue != NULL && (UintPtr(aValue)&3) == 0 && (tAttrByteSize&3) == 0) {
    theStorageX = NULL;
    theRef = aValue;
    return 0;
  }
  if (tAttrByteSize <= 32) {
    theStorageX = NULL;
    theStorage[0] = 0;
    theStorage[1] = 0;
    theStorage[2] = 0;
    theStorage[3] = 0;
    theRef = theStorage;
    return 0;
  }
  Uint32 tSize = (tAttrByteSize + 7) >> 3;
  Uint64* tRef = new Uint64[tSize];
  if (tRef != NULL) {
    for (Uint32 i = 0; i < tSize; i++) {
      tRef[i] = 0;
    }
    theStorageX = tRef;
    theRef = tRef;
    return 0;
  }
  return -1;
}

void
NdbRecAttr::copyout()
{
  char* tRef = (char*)theRef;
  char* tValue = theValue;
  if (tRef != tValue && tRef != NULL && tValue != NULL) {
    Uint32 n = theAttrSize * theArraySize;
    while (n-- > 0) {
      *tValue++ = *tRef++;
    }
  }
}

NdbRecAttr *
NdbRecAttr::clone() const {
  NdbRecAttr * ret = new NdbRecAttr();

  ret->theAttrId = theAttrId;
  ret->theNULLind = theNULLind;
  ret->theAttrSize = theAttrSize;
  ret->theArraySize = theArraySize;
  ret->m_column = m_column;

  Uint32 n = theAttrSize * theArraySize;
  if(n <= 32){
    ret->theRef = (char*)&ret->theStorage[0];
    ret->theStorageX = 0;
    ret->theValue = 0;
  } else {
    ret->theStorageX = new Uint64[((n + 7) >> 3)];
    ret->theRef = (char*)ret->theStorageX;
    ret->theValue = 0;
  }
  memcpy(ret->theRef, theRef, n);
  return ret;
}

bool
NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz){
  const Uint32 n = (theAttrSize * theArraySize + 3) >> 2;
  if(n == sz){
    theNULLind = 0;
    if(!copyoutRequired())
      memcpy(theRef, data, 4 * sz);
    else
      memcpy(theValue, data, theAttrSize * theArraySize);
    return true;
  } else if(sz == 0){
    setNULL();
    return true;
  }
  return false;
}

static void
ndbrecattr_print_string(NdbOut& out, const char *type,
			const char *ref, unsigned sz)
{
  int i;
  // trailing zeroes are not printed
  for (i=sz-1; i >= 0; i--)
    if (ref[i] == 0) sz--;
    else break;
  if (sz == 0) return; // empty

  char *str= (char*)malloc(sz+1);
  memcpy(str, ref, sz);
  str[sz]= 0; // null terminate
  int len= strlen(str);
  int printable= 1;
  for (i=0; i < len; i++)
  {
    if (str[i] < 32) {
      printable= 0;
      break;
    }
  }
  if (printable)
    out.print("%.*s", len, str);
  else
  {
    for (i=0; i < len; i++)
      out.print("%02X", (int)str[i]);
  }

  free(str);
  if (len != (int)sz)
  {
    out.print("[");
    for (i= len+1; ref[i] != 0; i++)
    out.print("%u]",len-i);
    assert(sz > i);
    ndbrecattr_print_string(out,type,ref+i,sz-i);
  }
}

NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
{
  if (r.isNULL())
  {
    out << "[NULL]";
    return out;
  }

  if (r.arraySize() > 1)
    out << "[";

  for (Uint32 j = 0; j < r.arraySize(); j++)
  {
    if (j > 0)
      out << " ";

    switch(r.getType())
      {
      case NdbDictionary::Column::Bigunsigned:
	out << r.u_64_value();
	break;
      case NdbDictionary::Column::Bit:
	out << hex << "H'" << r.u_32_value() << dec;
	break;
      case NdbDictionary::Column::Unsigned:
	out << r.u_32_value();
	break;
      case NdbDictionary::Column::Smallunsigned:
	out << r.u_short_value();
	break;
      case NdbDictionary::Column::Tinyunsigned:
	out << (unsigned) r.u_char_value();
	break;
      case NdbDictionary::Column::Bigint:
	out << r.int64_value();
	break;
      case NdbDictionary::Column::Int:
	out << r.int32_value();
	break;
      case NdbDictionary::Column::Smallint:
	out << r.short_value();
	break;
      case NdbDictionary::Column::Tinyint:
	out << (int) r.char_value();
	break;
      case NdbDictionary::Column::Binary:
	ndbrecattr_print_string(out,"Binary",r.aRef(),r.arraySize());
	j = r.arraySize();
	break;
      case NdbDictionary::Column::Char:
	ndbrecattr_print_string(out,"Char",r.aRef(),r.arraySize());
	j = r.arraySize();
	break;
      case NdbDictionary::Column::Varchar:
	ndbrecattr_print_string(out,"Varchar", r.aRef()+ 2,
				ntohs(r.u_short_value()));
	j = r.arraySize();
	break;
      case NdbDictionary::Column::Float:
	out << r.float_value();
	break;
      case NdbDictionary::Column::Double:
	out << r.double_value();
	break;
      case NdbDictionary::Column::Blob:
        {
          const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
          out << h->length << ":";
          const unsigned char* p = (const unsigned char*)(h + 1);
          unsigned n = r.arraySize() - sizeof(*h);
          for (unsigned k = 0; k < n && k < h->length; k++)
            out.print("%02X", (int)p[k]);
          j = r.arraySize();
        }
        break;
      case NdbDictionary::Column::Text:
        {
          const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
          out << h->length << ":";
          const unsigned char* p = (const unsigned char*)(h + 1);
          unsigned n = r.arraySize() - sizeof(*h);
          for (unsigned k = 0; k < n && k < h->length; k++)
            out.print("%c", (int)p[k]);
          j = r.arraySize();
        }
        break;
      default: /* no print functions for the rest, just print type */
	out << (int) r.getType();
	j = r.arraySize();
	if (j > 1)
	  out << " " << j << " times";
	break;
      }
  }

  if (r.arraySize() > 1)
  {
    out << "]";
  }

  return out;
}
<|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/basictypes.h"
#include "googleurl/src/gurl.h"
#include "net/base/data_url.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

  struct ParseTestData {
    const char* url;
    bool is_valid;
    const char* mime_type;
    const char* charset;
    const char* data;
  };

class DataURLTest : public testing::Test {
};

}

TEST(DataURLTest, Parse) {
  const ParseTestData tests[] = {
    { "data:",
       false,
       "",
       "",
       "" },

    { "data:,",
      true,
      "text/plain",
      "US-ASCII",
      "" },

    { "data:;base64,",
      true,
      "text/plain",
      "US-ASCII",
      "" },

    { "data:;charset=,test",
      true,
      "text/plain",
      "US-ASCII",
      "test" },

    { "data:TeXt/HtMl,x",
      true,
      "text/html",
      "US-ASCII",
      "x" },

    { "data:,foo",
      true,
      "text/plain",
      "US-ASCII",
      "foo" },

    { "data:;base64,aGVsbG8gd29ybGQ=",
      true,
      "text/plain",
      "US-ASCII",
      "hello world" },

    { "data:foo/bar;baz=1;charset=kk,boo",
      true,
      "foo/bar",
      "kk",
      "boo" },

    { "data:text/html,%3Chtml%3E%3Cbody%3E%3Cb%3Ehello%20world"
          "%3C%2Fb%3E%3C%2Fbody%3E%3C%2Fhtml%3E",
      true,
      "text/html",
      "US-ASCII",
      "hello world" },

    { "data:text/html,hello world",
      true,
      "text/html",
      "US-ASCII",
      "hello world" },

    // the comma cannot be url-escaped!
    { "data:%2Cblah",
      false,
      "",
      "",
      "" },

    // invalid base64 content
    { "data:;base64,aGVs_-_-",
      false,
      "",
      "",
      "" },

    // Spaces should be removed from non-text data URLs (we already tested
    // spaces above).
    { "data:image/fractal,a b c d e f g",
      true,
      "image/fractal",
      "US-ASCII",
      "abcdefg" },

    // Spaces should also be removed from anything base-64 encoded
    { "data:;base64,aGVs bG8gd2  9ybGQ=",
      true,
      "text/plain",
      "US-ASCII",
      "hello world" },

    // Other whitespace should also be removed from anything base-64 encoded.
    { "data:;base64,aGVs bG8gd2  \n9ybGQ=",
      true,
      "text/plain",
      "US-ASCII",
      "hello world" },

    // In base64 encoding, escaped whitespace should be stripped.
    // (This test was taken from acid3)
    // http://b/1054495
    { "data:text/javascript;base64,%20ZD%20Qg%0D%0APS%20An%20Zm91cic%0D%0A%207"
          "%20",
      true,
      "text/javascript",
      "US-ASCII",
      "d4 = 'four';" },

    // Only unescaped whitespace should be stripped in non-base64.
    // http://b/1157796
    { "data:img/png,A  B  %20  %0A  C",
      true,
      "img/png",
      "US-ASCII",
      "AB \nC" },

    // TODO(darin): add more interesting tests
  };

  for (size_t i = 0; i < arraysize(tests); ++i) {
    std::string mime_type;
    std::string charset;
    std::string data;
    bool ok =
        net::DataURL::Parse(GURL(tests[i].url), &mime_type, &charset, &data);
    EXPECT_EQ(ok, tests[i].is_valid);
    if (tests[i].is_valid) {
      EXPECT_EQ(tests[i].mime_type, mime_type);
      EXPECT_EQ(tests[i].charset, charset);
      EXPECT_EQ(tests[i].data, data);
    }
  }
}
<commit_msg>Fix indentation.<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/basictypes.h"
#include "googleurl/src/gurl.h"
#include "net/base/data_url.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

struct ParseTestData {
  const char* url;
  bool is_valid;
  const char* mime_type;
  const char* charset;
  const char* data;
};

class DataURLTest : public testing::Test {
};

}

TEST(DataURLTest, Parse) {
  const ParseTestData tests[] = {
    { "data:",
       false,
       "",
       "",
       "" },

    { "data:,",
      true,
      "text/plain",
      "US-ASCII",
      "" },

    { "data:;base64,",
      true,
      "text/plain",
      "US-ASCII",
      "" },

    { "data:;charset=,test",
      true,
      "text/plain",
      "US-ASCII",
      "test" },

    { "data:TeXt/HtMl,x",
      true,
      "text/html",
      "US-ASCII",
      "x" },

    { "data:,foo",
      true,
      "text/plain",
      "US-ASCII",
      "foo" },

    { "data:;base64,aGVsbG8gd29ybGQ=",
      true,
      "text/plain",
      "US-ASCII",
      "hello world" },

    { "data:foo/bar;baz=1;charset=kk,boo",
      true,
      "foo/bar",
      "kk",
      "boo" },

    { "data:text/html,%3Chtml%3E%3Cbody%3E%3Cb%3Ehello%20world"
          "%3C%2Fb%3E%3C%2Fbody%3E%3C%2Fhtml%3E",
      true,
      "text/html",
      "US-ASCII",
      "hello world" },

    { "data:text/html,hello world",
      true,
      "text/html",
      "US-ASCII",
      "hello world" },

    // the comma cannot be url-escaped!
    { "data:%2Cblah",
      false,
      "",
      "",
      "" },

    // invalid base64 content
    { "data:;base64,aGVs_-_-",
      false,
      "",
      "",
      "" },

    // Spaces should be removed from non-text data URLs (we already tested
    // spaces above).
    { "data:image/fractal,a b c d e f g",
      true,
      "image/fractal",
      "US-ASCII",
      "abcdefg" },

    // Spaces should also be removed from anything base-64 encoded
    { "data:;base64,aGVs bG8gd2  9ybGQ=",
      true,
      "text/plain",
      "US-ASCII",
      "hello world" },

    // Other whitespace should also be removed from anything base-64 encoded.
    { "data:;base64,aGVs bG8gd2  \n9ybGQ=",
      true,
      "text/plain",
      "US-ASCII",
      "hello world" },

    // In base64 encoding, escaped whitespace should be stripped.
    // (This test was taken from acid3)
    // http://b/1054495
    { "data:text/javascript;base64,%20ZD%20Qg%0D%0APS%20An%20Zm91cic%0D%0A%207"
          "%20",
      true,
      "text/javascript",
      "US-ASCII",
      "d4 = 'four';" },

    // Only unescaped whitespace should be stripped in non-base64.
    // http://b/1157796
    { "data:img/png,A  B  %20  %0A  C",
      true,
      "img/png",
      "US-ASCII",
      "AB \nC" },

    // TODO(darin): add more interesting tests
  };

  for (size_t i = 0; i < arraysize(tests); ++i) {
    std::string mime_type;
    std::string charset;
    std::string data;
    bool ok =
        net::DataURL::Parse(GURL(tests[i].url), &mime_type, &charset, &data);
    EXPECT_EQ(ok, tests[i].is_valid);
    if (tests[i].is_valid) {
      EXPECT_EQ(tests[i].mime_type, mime_type);
      EXPECT_EQ(tests[i].charset, charset);
      EXPECT_EQ(tests[i].data, data);
    }
  }
}
<|endoftext|>


<commit_before>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2019 Intel Corporation

#include "pattern_matching.hpp"

#include "ade/util/zip_range.hpp"

namespace cv { namespace gimpl {
namespace {
using Graph = GModel::Graph;

template<typename Iterator>
ade::NodeHandle getNh(Iterator it) { return *it; }

template<>
ade::NodeHandle getNh(SubgraphMatch::M::const_iterator it) { return it->second; }

template<typename Container>
void erase(Graph& g, const Container& c)
{
    for (auto first = c.begin(); first != c.end(); ++first) {
        ade::NodeHandle node = getNh(first);
        if (node == nullptr) continue;  // some nodes might already be erased
        g.erase(node);
    }
}
}  // anonymous namespace

void performSubstitution(GModel::Graph& graph,
                         const Protocol& patternP,
                         const Protocol& substituteP,
                         const SubgraphMatch& patternToGraphMatch)
{
    // 1. substitute input nodes
    const auto& patternIns = patternP.in_nhs;
    const auto& substituteIns = substituteP.in_nhs;

    for (auto it : ade::util::zip(ade::util::toRange(patternIns),
                                  ade::util::toRange(substituteIns))) {
        // Note: we don't replace input DATA nodes here, only redirect their output edges
        const auto& patternDataNode = std::get<0>(it);
        const auto& substituteDataNode = std::get<1>(it);
        const auto& graphDataNode = patternToGraphMatch.inputDataNodes.at(patternDataNode);
        GModel::redirectReaders(graph, substituteDataNode, graphDataNode);
    }

    // 2. substitute output nodes
    const auto& patternOuts = patternP.out_nhs;
    const auto& substituteOuts = substituteP.out_nhs;

    for (auto it : ade::util::zip(ade::util::toRange(patternOuts),
                                  ade::util::toRange(substituteOuts))) {
        // Note: we don't replace output DATA nodes here, only redirect their input edges
        const auto& patternDataNode = std::get<0>(it);
        const auto& substituteDataNode = std::get<1>(it);
        const auto& graphDataNode = patternToGraphMatch.outputDataNodes.at(patternDataNode);
        // delete existing edges (otherwise we cannot redirect)
        for (auto e : graphDataNode->inEdges()) {
            graph.erase(e);
        }
        GModel::redirectWriter(graph, substituteDataNode, graphDataNode);
    }

    // 3. erase redundant nodes:
    // erase input data nodes of __substitute__
    erase(graph, substituteIns);

    // erase old start OP nodes of __main graph__
    erase(graph, patternToGraphMatch.startOpNodes);

    // erase old internal nodes of __main graph__
    erase(graph, patternToGraphMatch.internalLayers);

    // erase old finish OP nodes of __main graph__
    erase(graph, patternToGraphMatch.finishOpNodes);

    // erase output data nodes of __substitute__
    erase(graph, substituteOuts);
}

}  // namespace gimpl
}  // namespace cv
<commit_msg>G-API: fix perform substitution UB/crash<commit_after>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2019 Intel Corporation

#include "pattern_matching.hpp"

#include "ade/util/zip_range.hpp"

namespace cv { namespace gimpl {
namespace {
using Graph = GModel::Graph;

template<typename Iterator>
ade::NodeHandle getNh(Iterator it) { return *it; }

template<>
ade::NodeHandle getNh(SubgraphMatch::M::const_iterator it) { return it->second; }

template<typename Container>
void erase(Graph& g, const Container& c)
{
    for (auto first = c.begin(); first != c.end(); ++first) {
        ade::NodeHandle node = getNh(first);
        if (node == nullptr) continue;  // some nodes might already be erased
        g.erase(node);
    }
}
}  // anonymous namespace

void performSubstitution(GModel::Graph& graph,
                         const Protocol& patternP,
                         const Protocol& substituteP,
                         const SubgraphMatch& patternToGraphMatch)
{
    // 1. substitute input nodes
    const auto& patternIns = patternP.in_nhs;
    const auto& substituteIns = substituteP.in_nhs;

    for (auto it : ade::util::zip(ade::util::toRange(patternIns),
                                  ade::util::toRange(substituteIns))) {
        // Note: we don't replace input DATA nodes here, only redirect their output edges
        const auto& patternDataNode = std::get<0>(it);
        const auto& substituteDataNode = std::get<1>(it);
        const auto& graphDataNode = patternToGraphMatch.inputDataNodes.at(patternDataNode);
        GModel::redirectReaders(graph, substituteDataNode, graphDataNode);
    }

    // 2. substitute output nodes
    const auto& patternOuts = patternP.out_nhs;
    const auto& substituteOuts = substituteP.out_nhs;

    for (auto it : ade::util::zip(ade::util::toRange(patternOuts),
                                  ade::util::toRange(substituteOuts))) {
        // Note: we don't replace output DATA nodes here, only redirect their input edges
        const auto& patternDataNode = std::get<0>(it);
        const auto& substituteDataNode = std::get<1>(it);
        const auto& graphDataNode = patternToGraphMatch.outputDataNodes.at(patternDataNode);

        // delete existing edges (otherwise we cannot redirect)
        auto existingEdges = graphDataNode->inEdges();
        // NB: we cannot iterate over node->inEdges() here directly because it gets modified when
        //     edges are erased. Erasing an edge supposes that src/dst nodes will remove
        //     (correspondingly) out/in edge (which is _our edge_). Now, this deleting means
        //     node->inEdges() will also get updated in the process: so, we'd iterate over a
        //     container which changes in this case. Using supplementary std::vector instead:
        std::vector<ade::EdgeHandle> handles(existingEdges.begin(), existingEdges.end());
        for (const auto& e : handles) {
            graph.erase(e);
        }

        GModel::redirectWriter(graph, substituteDataNode, graphDataNode);
    }

    // 3. erase redundant nodes:
    // erase input data nodes of __substitute__
    erase(graph, substituteIns);

    // erase old start OP nodes of __main graph__
    erase(graph, patternToGraphMatch.startOpNodes);

    // erase old internal nodes of __main graph__
    erase(graph, patternToGraphMatch.internalLayers);

    // erase old finish OP nodes of __main graph__
    erase(graph, patternToGraphMatch.finishOpNodes);

    // erase output data nodes of __substitute__
    erase(graph, substituteOuts);
}

}  // namespace gimpl
}  // namespace cv
<|endoftext|>