<commit_before>#include <iostream>
#include <sstream>
#include <string>

#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <netdb.h>
#include <cstdlib>
#include <cstring>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"
#include "terminate_message.h"

#include "constants.h"
#include "helper_function.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *>, ps_compare> proc_loc_dict;
static list<server_function_info *> roundRobinList;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/

void registration_request_handler(RegisterRequestMessage * message, int sock){
	const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  procedure_signature key(name, argTypes);

  int status = 0;

  //if 'key' dosnt exist in map, add it to the map and round robin
	if (proc_loc_dict.find(key) == proc_loc_dict.end()) {
    //The purpose of this function is so we can have copy of the argTypes that not the original
    int *memArgTypes = copyArgTypes(argTypes);

    key = procedure_signature(name, memArgTypes);
    proc_loc_dict[key] = list<server_info *>();

    //This is bad we shouldn't need a newKey and we should be able to use the key above
    //due to &* reasones I made a variable newKey for the 'info' object
    procedure_signature * newKey = new procedure_signature(name, memArgTypes);
    server_info * entry = new server_info(server_identifier, port, sock);

    //Adding to roundRobinList
    server_function_info * info = new server_function_info(entry, newKey);
    roundRobinList.push_back(info);

  } else {
    bool sameLoc = false;
    list<server_info *> hostList = proc_loc_dict[key];

    for (list<server_info *>::iterator it = hostList.begin(); it != hostList.end(); it++) {
      if((*it)->socket == sock){
        //If they have the same socket, then must be same server_address/port
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something, maybe we should keep
        sameLoc = true;
      }
    }

  	if(!sameLoc){ //same procedure different socket
       server_info * new_msg_loc = new server_info(server_identifier, port, sock);
       hostList.push_back(new_msg_loc);
    }
  }

  RegisterSuccessMessage regSuccessMsg = RegisterSuccessMessage(status);
  Segment regSuccessSeg = Segment(regSuccessMsg.getLength(), MSG_TYPE_REGISTER_SUCCESS, &regSuccessMsg);
  regSuccessSeg.send(sock);

}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
void location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
	for (list<server_function_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){

    //If the name are the same and argTypes
    if((*it)->ps->name == message->getName() && compareArr((*it)->ps->argTypes, message->getArgTypes() )){
      exist = true;

      LocSuccessMessage locSuccessMsg = LocSuccessMessage((*it)->si->server_identifier, (*it)->si->port);
      Segment locSuccessSeg = Segment(regSuccessMsg.getLength(), MSG_TYPE_LOC_SUCCESS, &locSuccessMsg);
      locSuccessSeg.send(sock);

      //When we have identified the correct procedure_signature use splice and move that service to the end
      roundRobinList.splice(roundRobinList.end(), roundRobinList, it);
      break;
 		}
	}

  if(!exist){
    int reasoncode = -5; // Need actual reasoncode
    LocFailureMessage locFailMsg = LocFailureMessage(reasoncode);
    Segment regFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
    regFailSeg.send(sock);
  }
}

int request_handler(Segment * segment, int sock){
  int retval = 0;
  if(segment->getType() == MSG_TYPE_REGISTER_REQUEST){ //'LOC_REQUEST'
    Message * cast1 = segment->getMessage();
    RegisterRequestMessage * rrm = dynamic_cast<RegisterRequestMessage*>(cast1);

    registration_request_handler(rrm, sock);

  }else if (segment->getType() == MSG_TYPE_LOC_REQUEST){ //'REGISTER'
    Message * cast2 = segment->getMessage();
    LocRequestMessage * lqm = dynamic_cast<LocRequestMessage*>(cast2);

    location_request_handler(lqm, sock);
  }

	return retval;
}

// Returns the binder address
string getBinderAddress() {
   char hostname[MAXHOSTNAMELEN + 1] = {'\0'};
   gethostname(hostname, sizeof(hostname));
   return string(hostname);
}

// Returns the binder port
int getBinderPort(int welcomeSocket) {
   struct sockaddr_in binderAddress;
   socklen_t binderAddressLength = sizeof(binderAddress);

   int result = getsockname(welcomeSocket, (struct sockaddr*) &binderAddress,
      &binderAddressLength);
   if (result < 0) {
      exit(-1);
   } // if

   return ntohs(binderAddress.sin_port);
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main(){

  vector<int> myConnections;
  vector<int> myToRemove;

  int status;
  struct addrinfo hints;
  struct addrinfo* servinfo;
  struct addrinfo* p;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  status = getaddrinfo(NULL, "0", &hints, &servinfo);

  p = servinfo;
  int sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);

  status = bind(sock, servinfo->ai_addr, servinfo->ai_addrlen);
  status = listen(sock, SOMAXCONN);

  cout << "BINDER_ADDRESS " << getBinderAddress() << endl;
  cout << "BINDER_PORT " << getBinderPort(sock) << endl;

  fd_set readfds;
  int n;
  struct sockaddr_storage their_addr;

  while(true){
    //CONNECTIONS VECTOR
    FD_ZERO(&readfds);
    FD_SET(sock, &readfds);

    n = sock;

    for (vector<int>::iterator it = myConnections.begin();it != myConnections.end(); ++it) {
      int connection = *it;
      FD_SET(connection, &readfds);
       if (connection > n){
        n = connection;
      }
    }

    n = n+1;

    status = select(n, &readfds, NULL, NULL, NULL);

    if (status == -1) {
      cerr << "ERROR: select failed." << endl;
    } else {

      if (FD_ISSET(sock, &readfds)) {
        socklen_t addr_size = sizeof their_addr;
        int new_sock = accept(sock, (struct sockaddr*)&their_addr, &addr_size);

        if (new_sock < 0) {
          cerr << "ERROR: while accepting connection" << endl;
          close(new_sock);
          continue;
        }

        myConnections.push_back(new_sock);

      } else {

        for (vector<int>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
          int tempConnection = *it;
          if (FD_ISSET(tempConnection, &readfds)) {

            Segment * segment = 0;
            status = Segment::receive(sock, segment);

            //TODO: More sophisticaled error handling/replies
            // Maybe status should be reasonacode instead
            if (status < 0 && segment->getType() == MSG_TYPE_REGISTER_REQUEST) {
                RegisterFailureMessage regFailMsg = RegisterFailureMessage(status);
                Segment regFailSeg = Segment(regFailMsg.getLength(), MSG_TYPE_REGISTER_FAILURE, &regFailMsg);
                regFailSeg.send(sock);
                return status;
            } else if (status < 0 && segment->getType() == MSG_TYPE_LOC_REQUEST) {
                LocFailureMessage locFailMsg = LocFailureMessage(status);
                Segment regFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
                regFailSeg.send(sock);
                return status;
            }

            if (status == 0) {
              // client has closed the connection
              myToRemove.push_back(sock);
              return status;
            }

            request_handler(segment, sock);
          }
        }
      }

      for (vector<int>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
        myConnections.erase(remove(myConnections.begin(), myConnections.end(), *it), myConnections.end());
        close(*it);
      }
      myToRemove.clear();
    }
  }

  freeaddrinfo(servinfo);
}
<commit_msg>change<commit_after>#include <iostream>
#include <sstream>
#include <string>

#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <netdb.h>
#include <cstdlib>
#include <cstring>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"
#include "terminate_message.h"

#include "constants.h"
#include "helper_function.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *>, ps_compare> proc_loc_dict;
static list<server_function_info *> roundRobinList;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/

void registration_request_handler(RegisterRequestMessage * message, int sock){
	const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  procedure_signature key(name, argTypes);

  int status = 0;

  //if 'key' dosnt exist in map, add it to the map and round robin
	if (proc_loc_dict.find(key) == proc_loc_dict.end()) {
    //The purpose of this function is so we can have copy of the argTypes that not the original
    int *memArgTypes = copyArgTypes(argTypes);

    key = procedure_signature(name, memArgTypes);
    proc_loc_dict[key] = list<server_info *>();

    //This is bad we shouldn't need a newKey and we should be able to use the key above
    //due to &* reasones I made a variable newKey for the 'info' object
    procedure_signature * newKey = new procedure_signature(name, memArgTypes);
    server_info * entry = new server_info(server_identifier, port, sock);

    //Adding to roundRobinList
    server_function_info * info = new server_function_info(entry, newKey);
    roundRobinList.push_back(info);

  } else {
    bool sameLoc = false;
    list<server_info *> hostList = proc_loc_dict[key];

    for (list<server_info *>::iterator it = hostList.begin(); it != hostList.end(); it++) {
      if((*it)->socket == sock){
        //If they have the same socket, then must be same server_address/port
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something, maybe we should keep
        sameLoc = true;
      }
    }

  	if(!sameLoc){ //same procedure different socket
       server_info * new_msg_loc = new server_info(server_identifier, port, sock);
       hostList.push_back(new_msg_loc);
    }
  }

  RegisterSuccessMessage regSuccessMsg = RegisterSuccessMessage(status);
  Segment regSuccessSeg = Segment(regSuccessMsg.getLength(), MSG_TYPE_REGISTER_SUCCESS, &regSuccessMsg);
  regSuccessSeg.send(sock);

}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
void location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
	for (list<server_function_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){

    //If the name are the same and argTypes
    if((*it)->ps->name == message->getName() && compareArr((*it)->ps->argTypes, message->getArgTypes() )){
      exist = true;

      LocSuccessMessage locSuccessMsg = LocSuccessMessage((*it)->si->server_identifier, (*it)->si->port);
      Segment locSuccessSeg = Segment(locSuccessSeg.getLength(), MSG_TYPE_LOC_SUCCESS, &locSuccessMsg);
      locSuccessSeg.send(sock);

      //When we have identified the correct procedure_signature use splice and move that service to the end
      roundRobinList.splice(roundRobinList.end(), roundRobinList, it);
      break;
 		}
	}

  if(!exist){
    int reasoncode = -5; // Need actual reasoncode
    LocFailureMessage locFailMsg = LocFailureMessage(reasoncode);
    Segment locFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
    locFailSeg.send(sock);
  }
}

int request_handler(Segment * segment, int sock){
  int retval = 0;
  if(segment->getType() == MSG_TYPE_REGISTER_REQUEST){ //'LOC_REQUEST'
    Message * cast1 = segment->getMessage();
    RegisterRequestMessage * rrm = dynamic_cast<RegisterRequestMessage*>(cast1);

    registration_request_handler(rrm, sock);

  }else if (segment->getType() == MSG_TYPE_LOC_REQUEST){ //'REGISTER'
    Message * cast2 = segment->getMessage();
    LocRequestMessage * lqm = dynamic_cast<LocRequestMessage*>(cast2);

    location_request_handler(lqm, sock);
  }

	return retval;
}

// Returns the binder address
string getBinderAddress() {
   char hostname[MAXHOSTNAMELEN + 1] = {'\0'};
   gethostname(hostname, sizeof(hostname));
   return string(hostname);
}

// Returns the binder port
int getBinderPort(int welcomeSocket) {
   struct sockaddr_in binderAddress;
   socklen_t binderAddressLength = sizeof(binderAddress);

   int result = getsockname(welcomeSocket, (struct sockaddr*) &binderAddress,
      &binderAddressLength);
   if (result < 0) {
      exit(-1);
   } // if

   return ntohs(binderAddress.sin_port);
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main(){

  vector<int> myConnections;
  vector<int> myToRemove;

  int status;
  struct addrinfo hints;
  struct addrinfo* servinfo;
  struct addrinfo* p;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  status = getaddrinfo(NULL, "0", &hints, &servinfo);

  p = servinfo;
  int sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);

  status = bind(sock, servinfo->ai_addr, servinfo->ai_addrlen);
  status = listen(sock, SOMAXCONN);

  cout << "BINDER_ADDRESS " << getBinderAddress() << endl;
  cout << "BINDER_PORT " << getBinderPort(sock) << endl;

  fd_set readfds;
  int n;
  struct sockaddr_storage their_addr;

  while(true){
    //CONNECTIONS VECTOR
    FD_ZERO(&readfds);
    FD_SET(sock, &readfds);

    n = sock;

    for (vector<int>::iterator it = myConnections.begin();it != myConnections.end(); ++it) {
      int connection = *it;
      FD_SET(connection, &readfds);
       if (connection > n){
        n = connection;
      }
    }

    n = n+1;

    status = select(n, &readfds, NULL, NULL, NULL);

    if (status == -1) {
      cerr << "ERROR: select failed." << endl;
    } else {

      if (FD_ISSET(sock, &readfds)) {
        socklen_t addr_size = sizeof their_addr;
        int new_sock = accept(sock, (struct sockaddr*)&their_addr, &addr_size);

        if (new_sock < 0) {
          cerr << "ERROR: while accepting connection" << endl;
          close(new_sock);
          continue;
        }

        myConnections.push_back(new_sock);

      } else {

        for (vector<int>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
          int tempConnection = *it;
          if (FD_ISSET(tempConnection, &readfds)) {

            Segment * segment = 0;
            status = Segment::receive(sock, segment);

            //TODO: More sophisticaled error handling/replies
            // Maybe status should be reasonacode instead
            if (status < 0 && segment->getType() == MSG_TYPE_REGISTER_REQUEST) {
                RegisterFailureMessage regFailMsg = RegisterFailureMessage(status);
                Segment regFailSeg = Segment(regFailMsg.getLength(), MSG_TYPE_REGISTER_FAILURE, &regFailMsg);
                regFailSeg.send(sock);
                return status;
            } else if (status < 0 && segment->getType() == MSG_TYPE_LOC_REQUEST) {
                LocFailureMessage locFailMsg = LocFailureMessage(status);
                Segment regFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
                regFailSeg.send(sock);
                return status;
            }

            if (status == 0) {
              // client has closed the connection
              myToRemove.push_back(sock);
              return status;
            }

            request_handler(segment, sock);
          }
        }
      }

      for (vector<int>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
        myConnections.erase(remove(myConnections.begin(), myConnections.end(), *it), myConnections.end());
        close(*it);
      }
      myToRemove.clear();
    }
  }

  freeaddrinfo(servinfo);
}
<|endoftext|>


<commit_before><commit_msg>Bugfix: bitcoin-tx: scriptPubKey may be null, so accept outscript=<n>:<commit_after><|endoftext|>


<commit_before><commit_msg>Log READ_CB or WRITE_CB<commit_after><|endoftext|>


<commit_before><commit_msg>Some minor cleaning up [ci skip].<commit_after><|endoftext|>


<commit_before><commit_msg>Slight changes to the About box [ci skip].<commit_after><|endoftext|>


<commit_before><commit_msg>ruby: getPort function fix Fixed RubyMemory::getPort function to not pass in a -1 for the idx parameter<commit_after><|endoftext|>


<commit_before><commit_msg>Modified nearestValue to explicitly return null by calling Null().<commit_after><|endoftext|>


<commit_before><commit_msg>Add doc<commit_after><|endoftext|>


<commit_before>#include "Buttongrid.h"

Buttongrid::Buttongrid(){
	if(text = (char *)malloc(DISPLAY_SIZE+1)) memset(text,0,DISPLAY_SIZE+1); //Had to add one more, to avoid some bug
}

Buttongrid::Buttongrid(unsigned char size){
	if(text = (char *)malloc(DISPLAY_SIZE+1)) memset(text,0,DISPLAY_SIZE+1); //Had to add one more, to avoid some bug
	columns = size;
	rows = size;
	gridSize = size;

	//Allocate memory for labels
	if(gridSize!=NULL){
		if(labels = (unsigned char**)malloc(gridSize * sizeof(unsigned char*))){
			for(int i=0; i<gridSize; i++)
			{
				if(labels[i] = (unsigned char*)malloc(gridSize)){
					memset(labels[i],0,gridSize);
				}
			}
		}
	}

	this->init();
}

Buttongrid::Buttongrid(unsigned char r, unsigned char c){
	if(text = (char *)malloc(DISPLAY_SIZE+1)) memset(text,0,DISPLAY_SIZE+1); //Had to add one more, to avoid some bug
	columns = c;
	rows = r;
	//gridSize = size;

	//Allocate memory for labels
	if(rows!=NULL){
		if(labels = (unsigned char**)malloc(rows * sizeof(unsigned char*))){
			for(int i=0; i<rows; i++)
			{
				if(labels[i] = (unsigned char*)malloc(columns)){
					memset(labels[i],0,columns);
				}
			}
		}
	}

	//Allocate memory for names
	if(rows >= 0 && columns >= 0){
		char qty = rows * columns;
		if(names = (const char**) malloc(qty * 8 * sizeof(char))){
			memset(names,0,qty*8*sizeof(char));
		}
	}

	//this->init();

}

Buttongrid::Buttongrid(unsigned int width, unsigned int height, int backgroundColor, int textColor, int borderColor){
	if(text = (char *)malloc(DISPLAY_SIZE+1)) memset(text,0,DISPLAY_SIZE+1); //Had to add one more, to avoid some bug
	x = 0;
	y = 0;
	this->setSize(width,height);
	this->setColors(backgroundColor,textColor,borderColor);
	this->init();
}

Buttongrid::~Buttongrid(){
	if(text) free(text);
}

void Buttongrid::init(){
	Button::init();
	type = 0x31;
	borderWidth = 2;
	charPos = 0;

	// Initialize labels with position ID
	for(byte r=1; r<=rows; r++)
	{
		for(byte c=1; c<=columns; c++)
		{
			labels[r-1][c-1] = c+columns*(r-1);
			//Serial.print("Row ");
			//Serial.print(r);
			//Serial.print(" Col ");
			//Serial.print(c);
			//Serial.print(" Num ");
			//Serial.println(c+columns*(r-1));
		}
	}
}

void Buttongrid::drawGrid(){
  int xPos,yPos,width,height;
  int btnWidth,btnHeight;

  xPos = x;
  yPos = y;
  width = w;
  height = h;
  btnWidth = w / columns;
  btnHeight = h / rows;

  //--nums background rectangle
  Tft.fillRectangle(xPos,yPos,width,height,bgColor);

	//-- outer border
  for(byte i=borderWidth; i!=0;i--){
    Tft.drawRectangle(xPos++,yPos++,width--,height--,borderColor);
    width--;
    height--;
  }

  //-- horizontal lines
  for(byte j=1;j<rows;j++)
  {
	  // draw # horizontal lines depending on borderWidth
  	for(byte i=0; i<borderWidth;i++){
    	Tft.drawHorizontalLine(x,y+btnHeight*j+i-vGap,width+borderWidth,borderColor);
  	}

		//Only draw gaps in between edges
		if(vGap>0){
			//Tft.fillRectangle(xPos,y-vGap+btnHeight*j+1,width,btnHeight-1,BLACK);
			for(byte i=0; i<borderWidth;i++){
				Tft.drawHorizontalLine(x,y+btnHeight*j+i+borderWidth+vGap,width+borderWidth,borderColor);
			}
		}

  }

  //-- vertical lines
  for(byte j=1;j<columns;j++)
  {
	// draw # of vertical lines depending on borderWidth
  	for(byte i=0; i<borderWidth;i++){
    	Tft.drawVerticalLine(x+btnWidth*j+i-hGap,y+borderWidth,height+borderWidth,borderColor);
  	}

		//Only draw gaps in between edges
		if(hGap>0){
			//Tft.fillRectangle(xPos,y-vGap+btnHeight*j+1,width,btnHeight-1,BLACK);
			for(byte i=0; i<borderWidth;i++){
				Tft.drawVerticalLine(x+btnWidth*j+i+borderWidth+hGap,y+borderWidth,height+borderWidth,borderColor);
			}
		}

  }

  //-- draw contents
  byte colIndex=0;
  byte rowIndex=0;
  for(byte r=1; r<=rows; r++)
  {
	  for(byte c=1; c<=columns; c++)
	  {
		  //byte num = getNumber(r,c); //c+(r-1)*columns;
		  //Serial.print(" r: ");
		  //Serial.print(r);
		  //Serial.print(" c: ");
		  //Serial.print(c);
		  //Serial.print(" num: ");
		  //Serial.print(num);
		  //Serial.print(" label: ");
		  //Serial.print(labels[r-1][c-1]);
		  //Serial.print(",");

		  //setLabel(getNumber(r,c),labels[r-1][c-1]);
		  printName(getNumber(r,c));
	  }
	  //Serial.println();
  }

  //-- Gaps fill
  if(hGap > 0){
		for(byte j=1;j<columns;j++){
			Tft.fillRectangle(x+j*btnWidth+borderWidth-hGap,y,hGap*2,h,myCanvas->bgColor);
		}
  }
  if(vGap > 0){
		for(byte j=1;j<rows;j++){
			Tft.fillRectangle(x,y+j*btnHeight+borderWidth-vGap,w,vGap*2,myCanvas->bgColor);
		}
  }
}

void Buttongrid::setEventHandler(void (*functionPointer)(Buttongrid *, unsigned char)){
	eventHandler = functionPointer;
}

void Buttongrid::configure(byte size, byte f){
	columns = size;
	rows = size;
	gridSize = size;
	font_size = f;
	show();
}

unsigned char Buttongrid::getColumn(unsigned char num){
	unsigned char val = num%columns;
	return val==0 ? columns : val;
}

unsigned char Buttongrid::getRow(unsigned char num){
	num -= 1;
	unsigned char mod = num%columns;
	return num/columns + 1;
}

unsigned char Buttongrid::getNumber(unsigned char row, unsigned char column){
	unsigned char val = column + (row - 1) * columns;
	return val;
}

void Buttongrid::setNum(unsigned char id){
	int boundX1, boundX2, boundY1, boundY2;
	int btnWidth = w/columns;
	int btnHeight = h/rows;
	unsigned char colIndex = getColumn(id)-1;
	unsigned char rowIndex = getRow(id)-1;
	unsigned char digits = Tft.Get_Digits(id);

	//Calculates initial position of text inside the btnWidth
	//considering the number's width and font size.
	int xPos = btnWidth/2 - (digits*FONT_X*font_size)/2;//btnWidth/(2) - 6*digits -2;
	int yPos = btnHeight/(2) - 8;

	//Calculates position of the text considering
	//its column or row and the btnWidth.
  	xPos = x+(colIndex*btnWidth)+xPos+borderWidth;
  	yPos = y+yPos+(rowIndex*btnHeight);

  	//Draw contents function
  	Tft.drawNumber(id,xPos,yPos,font_size,BLACK);
}

void Buttongrid::setLabel(unsigned char id, unsigned char label){
	int boundX1, boundX2, boundY1, boundY2;
	int btnWidth = w/columns;
	int btnHeight = h/rows;
	unsigned char colIndex = getColumn(id)-1;
	unsigned char rowIndex = getRow(id)-1;
	unsigned char digits = Tft.Get_Digits(label);

	//labels[rowIndex][colIndex] = label; <---- No, can't do this! No enough memory to hold strings for each button
	//Calculates initial position of text inside the btnWidth
	//considering the number's width and font size.

	int xPos = (btnWidth - digits*6*font_size)/2;//btnWidth/(2) - 6*digits -2;
	int yPos = (btnHeight-FONT_Y*fontSize)/2;//btnHeight/(2) - 8;

	//Calculates position of the text considering
	//its column or row and the btnWidth.
	xPos = x+(colIndex*btnWidth)+xPos+borderWidth+hGap;//+(2*borderWidth);//+borderWidth;
	yPos = y+(rowIndex*btnHeight)+yPos+borderWidth+vGap;//+(2*borderWidth);

	//Draw contents function
	Tft.drawNumber(label,xPos,yPos,font_size,BLACK);
}

void Buttongrid::setName(unsigned char id, const char name[8]){
	names[id] = name;
	return;
}

void Buttongrid::setName(unsigned char id, char number){
	//names[id] = ;
	return;
}

void Buttongrid::printName(unsigned char id){
	const char* name = names[id];
	// Calculate characters in name
	int n;
	for(n=0;n<8;n++){
		if(name[n] == 0) break;
	}

	Serial.print(n);
	Serial.print(" characters for id: ");
	Serial.print(id);
	Serial.print(" ");
	Serial.println(names[id]);

	//setNum(id);
	setLabel(id,labels[getRow(id)-1][getColumn(id)-1]);
	return;

	// If name is empty draw the id, else draw the name
	if(n==0){
		setNum(id);
	}else{
		//i++;
		int boundX1, boundX2, boundY1, boundY2;
		int btnWidth = w/columns;
		int btnHeight = h/rows;
		unsigned char colIndex = getColumn(id)-1;
		unsigned char rowIndex = getRow(id)-1;

		int xPos = btnWidth/2 - (n*FONT_X*font_size)/2;
		int yPos = btnHeight/(2) - 8;

		xPos = x+(colIndex*btnWidth)+xPos+3*borderWidth;
		yPos = y+yPos+(rowIndex*btnHeight);

		Tft.drawString((char*)names[id],xPos, yPos, font_size, fgColor);
	}

	return;
}

void Buttongrid::clear(){
	drawGrid();
	lastPressed = 0;
}

//Overriden virtual methods

bool Buttongrid::checkTouch(Point* p){
	int boundX1, boundX2, boundY1, boundY2;
	int btnWidth = w/columns;
	int btnHeight = h/rows;
	bool pressed = false;
	if(lastMillis + debounceTime < millis()){
		if((p->x > x+borderWidth) && (p->x < x+w-borderWidth) && (p->y > y+borderWidth) && (p->y < y+h-borderWidth)){
			//num coordinates
			for(int r = 1;(r <= rows)&&(!pressed); r++)
			{
				// Determine the bounding y's for this row
				boundY1 = y+(btnHeight)*(r-1)+borderWidth;
				boundY2 = y+(btnHeight)*r-borderWidth;
				for(int c = 1;(c <= columns)&&(!pressed);c++)
				{
					// Determine the bounding x's for this column
					boundX1 = x + (btnWidth)*(c-1) + borderWidth;
					boundX2 = x + (btnWidth)*c - borderWidth;
					int num = columns*(r - 1) + c;
					if((p->x > boundX1) && (p->x < boundX2) && (p->y > boundY1) && (p->y < boundY2)){

						// Restore last button pressed appearance
						if(clearLastPressed && lastPressed != 0){
							int lastX = x + (btnWidth)*(getColumn(lastPressed)-1) + borderWidth;
							int lastY = y+(btnHeight)*(getRow(lastPressed)-1)+borderWidth;
							if(HIGHLIGHT == 1){
								Tft.fillRectangle(lastX,lastY,btnWidth-borderWidth-1,btnHeight-borderWidth-1,bgColor);
							}
							//setLabel(lastPressed,labels[getRow(lastPressed)-1][getColumn(lastPressed)-1]);
							printName(lastPressed);
						}

						// Highlight currently pressed button
						if(HIGHLIGHT == 1){
							Tft.fillRectangle(boundX1,boundY1,btnWidth-borderWidth-1,btnHeight-borderWidth-1,highlightColor);
						}
						//setNum(num);
						//setLabel(num,labels[r-1][c-1]);
						printName(num);

						// Call event handler with pressed button id
						eventHandler(this,num);
						pressed = true;
						lastPressed = num;
					}
				}// -- columns for loop
			}// --rows for loop
		}// -- if touch within widget area
		touched = !touched;
		lastMillis = millis();
	}// -- debounce
	return true; // <--- False means block further event checking.
}

void Buttongrid::show(){
	drawGrid();
	update();
}

void Buttongrid::update(){
	return;
}
<commit_msg>Changed order of drawing buttongrid.<commit_after>#include "Buttongrid.h"

Buttongrid::Buttongrid(){
	if(text = (char *)malloc(DISPLAY_SIZE+1)) memset(text,0,DISPLAY_SIZE+1); //Had to add one more, to avoid some bug
}

Buttongrid::Buttongrid(unsigned char size){
	if(text = (char *)malloc(DISPLAY_SIZE+1)) memset(text,0,DISPLAY_SIZE+1); //Had to add one more, to avoid some bug
	columns = size;
	rows = size;
	gridSize = size;

	//Allocate memory for labels
	if(gridSize!=NULL){
		if(labels = (unsigned char**)malloc(gridSize * sizeof(unsigned char*))){
			for(int i=0; i<gridSize; i++)
			{
				if(labels[i] = (unsigned char*)malloc(gridSize)){
					memset(labels[i],0,gridSize);
				}
			}
		}
	}

	this->init();
}

Buttongrid::Buttongrid(unsigned char r, unsigned char c){
	if(text = (char *)malloc(DISPLAY_SIZE+1)) memset(text,0,DISPLAY_SIZE+1); //Had to add one more, to avoid some bug
	columns = c;
	rows = r;
	//gridSize = size;

	//Allocate memory for labels
	if(rows!=NULL){
		if(labels = (unsigned char**)malloc(rows * sizeof(unsigned char*))){
			for(int i=0; i<rows; i++)
			{
				if(labels[i] = (unsigned char*)malloc(columns)){
					memset(labels[i],0,columns);
				}
			}
		}
	}

	//Allocate memory for names
	if(rows >= 0 && columns >= 0){
		char qty = rows * columns;
		if(names = (const char**) malloc(qty * 8 * sizeof(char))){
			memset(names,0,qty*8*sizeof(char));
		}
	}

	//this->init();

}

Buttongrid::Buttongrid(unsigned int width, unsigned int height, int backgroundColor, int textColor, int borderColor){
	if(text = (char *)malloc(DISPLAY_SIZE+1)) memset(text,0,DISPLAY_SIZE+1); //Had to add one more, to avoid some bug
	x = 0;
	y = 0;
	this->setSize(width,height);
	this->setColors(backgroundColor,textColor,borderColor);
	this->init();
}

Buttongrid::~Buttongrid(){
	if(text) free(text);
}

void Buttongrid::init(){
	Button::init();
	type = 0x31;
	borderWidth = 2;
	charPos = 0;

	// Initialize labels with position ID
	for(byte r=1; r<=rows; r++)
	{
		for(byte c=1; c<=columns; c++)
		{
			labels[r-1][c-1] = c+columns*(r-1);
			//Serial.print("Row ");
			//Serial.print(r);
			//Serial.print(" Col ");
			//Serial.print(c);
			//Serial.print(" Num ");
			//Serial.println(c+columns*(r-1));
		}
	}
}

void Buttongrid::drawGrid(){
  int xPos,yPos,width,height;
  int btnWidth,btnHeight;

  xPos = x;
  yPos = y;
  width = w;
  height = h;
  btnWidth = w / columns;
  btnHeight = h / rows;

  //--nums background rectangle
  Tft.fillRectangle(xPos,yPos,width,height,bgColor);

	//-- outer border
  for(byte i=borderWidth; i!=0;i--){
    Tft.drawRectangle(xPos++,yPos++,width--,height--,borderColor);
    width--;
    height--;
  }

  //-- horizontal lines
  for(byte j=1;j<rows;j++)
  {
	  // draw # horizontal lines depending on borderWidth
  	for(byte i=0; i<borderWidth;i++){
    	Tft.drawHorizontalLine(x,y+btnHeight*j+i-vGap,width+borderWidth,borderColor);
  	}

		//Only draw gaps in between edges
		if(vGap>0){
			//Tft.fillRectangle(xPos,y-vGap+btnHeight*j+1,width,btnHeight-1,BLACK);
			for(byte i=0; i<borderWidth;i++){
				Tft.drawHorizontalLine(x,y+btnHeight*j+i+borderWidth+vGap,width+borderWidth,borderColor);
			}
		}

  }

  //-- vertical lines
  for(byte j=1;j<columns;j++)
  {
	// draw # of vertical lines depending on borderWidth
  	for(byte i=0; i<borderWidth;i++){
    	Tft.drawVerticalLine(x+btnWidth*j+i-hGap,y+borderWidth,height+borderWidth,borderColor);
  	}

		//Only draw gaps in between edges
		if(hGap>0){
			//Tft.fillRectangle(xPos,y-vGap+btnHeight*j+1,width,btnHeight-1,BLACK);
			for(byte i=0; i<borderWidth;i++){
				Tft.drawVerticalLine(x+btnWidth*j+i+borderWidth+hGap,y+borderWidth,height+borderWidth,borderColor);
			}
		}

  }

  //-- Gaps fill
  if(hGap > 0){
		for(byte j=1;j<columns;j++){
			Tft.fillRectangle(x+j*btnWidth+borderWidth-hGap,y,hGap*2,h,myCanvas->bgColor);
		}
  }
  if(vGap > 0){
		for(byte j=1;j<rows;j++){
			Tft.fillRectangle(x,y+j*btnHeight+borderWidth-vGap,w,vGap*2,myCanvas->bgColor);
		}
  }

  //-- draw contents
  byte colIndex=0;
  byte rowIndex=0;
  for(byte r=1; r<=rows; r++)
  {
	  for(byte c=1; c<=columns; c++)
	  {
		  printName(getNumber(r,c));
	  }
  }

}

void Buttongrid::setEventHandler(void (*functionPointer)(Buttongrid *, unsigned char)){
	eventHandler = functionPointer;
}

void Buttongrid::configure(byte size, byte f){
	columns = size;
	rows = size;
	gridSize = size;
	font_size = f;
	show();
}

unsigned char Buttongrid::getColumn(unsigned char num){
	unsigned char val = num%columns;
	return val==0 ? columns : val;
}

unsigned char Buttongrid::getRow(unsigned char num){
	num -= 1;
	unsigned char mod = num%columns;
	return num/columns + 1;
}

unsigned char Buttongrid::getNumber(unsigned char row, unsigned char column){
	unsigned char val = column + (row - 1) * columns;
	return val;
}

void Buttongrid::setNum(unsigned char id){
	int boundX1, boundX2, boundY1, boundY2;
	int btnWidth = w/columns;
	int btnHeight = h/rows;
	unsigned char colIndex = getColumn(id)-1;
	unsigned char rowIndex = getRow(id)-1;
	unsigned char digits = Tft.Get_Digits(id);

	//Calculates initial position of text inside the btnWidth
	//considering the number's width and font size.
	int xPos = btnWidth/2 - (digits*FONT_X*font_size)/2;//btnWidth/(2) - 6*digits -2;
	int yPos = btnHeight/(2) - 8;

	//Calculates position of the text considering
	//its column or row and the btnWidth.
  	xPos = x+(colIndex*btnWidth)+xPos+borderWidth;
  	yPos = y+yPos+(rowIndex*btnHeight);

  	//Draw contents function
  	Tft.drawNumber(id,xPos,yPos,font_size,BLACK);
}

void Buttongrid::setLabel(unsigned char id, unsigned char label){
	int boundX1, boundX2, boundY1, boundY2;
	int btnWidth = w/columns;
	int btnHeight = h/rows;
	unsigned char colIndex = getColumn(id)-1;
	unsigned char rowIndex = getRow(id)-1;
	unsigned char digits = Tft.Get_Digits(label);

	//labels[rowIndex][colIndex] = label; <---- No, can't do this! No enough memory to hold strings for each button
	//Calculates initial position of text inside the btnWidth
	//considering the number's width and font size.

	int xPos = (btnWidth - digits*6*font_size)/2;//btnWidth/(2) - 6*digits -2;
	int yPos = (btnHeight-FONT_Y*fontSize)/2;//btnHeight/(2) - 8;

	//Calculates position of the text considering
	//its column or row and the btnWidth.
	xPos = x+(colIndex*btnWidth)+xPos+borderWidth+hGap;//+(2*borderWidth);//+borderWidth;
	yPos = y+(rowIndex*btnHeight)+yPos+borderWidth+vGap;//+(2*borderWidth);

	//Draw contents function
	Tft.drawNumber(label,xPos,yPos,font_size,BLACK);
}

void Buttongrid::setName(unsigned char id, const char name[8]){
	names[id] = name;
	return;
}

void Buttongrid::setName(unsigned char id, char number){
	//names[id] = ;
	return;
}

void Buttongrid::printName(unsigned char id){
	const char* name = names[id];
	// Calculate characters in name
	int n;
	for(n=0;n<8;n++){
		if(name[n] == 0) break;
	}

	Serial.print(n);
	Serial.print(" characters for id: ");
	Serial.print(id);
	Serial.print(" ");
	Serial.println(names[id]);

	//setNum(id);
	setLabel(id,labels[getRow(id)-1][getColumn(id)-1]);
	return;

	// If name is empty draw the id, else draw the name
	if(n==0){
		setNum(id);
	}else{
		//i++;
		int boundX1, boundX2, boundY1, boundY2;
		int btnWidth = w/columns;
		int btnHeight = h/rows;
		unsigned char colIndex = getColumn(id)-1;
		unsigned char rowIndex = getRow(id)-1;

		int xPos = btnWidth/2 - (n*FONT_X*font_size)/2;
		int yPos = btnHeight/(2) - 8;

		xPos = x+(colIndex*btnWidth)+xPos+3*borderWidth;
		yPos = y+yPos+(rowIndex*btnHeight);

		Tft.drawString((char*)names[id],xPos, yPos, font_size, fgColor);
	}

	return;
}

void Buttongrid::clear(){
	drawGrid();
	lastPressed = 0;
}

//Overriden virtual methods

bool Buttongrid::checkTouch(Point* p){
	int boundX1, boundX2, boundY1, boundY2;
	int btnWidth = w/columns;
	int btnHeight = h/rows;
	bool pressed = false;
	if(lastMillis + debounceTime < millis()){
		if((p->x > x+borderWidth) && (p->x < x+w-borderWidth) && (p->y > y+borderWidth) && (p->y < y+h-borderWidth)){
			//num coordinates
			for(int r = 1;(r <= rows)&&(!pressed); r++)
			{
				// Determine the bounding y's for this row
				boundY1 = y+(btnHeight)*(r-1)+borderWidth;
				boundY2 = y+(btnHeight)*r-borderWidth;
				for(int c = 1;(c <= columns)&&(!pressed);c++)
				{
					// Determine the bounding x's for this column
					boundX1 = x + (btnWidth)*(c-1) + borderWidth;
					boundX2 = x + (btnWidth)*c - borderWidth;
					int num = columns*(r - 1) + c;
					if((p->x > boundX1) && (p->x < boundX2) && (p->y > boundY1) && (p->y < boundY2)){

						// Restore last button pressed appearance
						if(clearLastPressed && lastPressed != 0){
							int lastX = x + (btnWidth)*(getColumn(lastPressed)-1) + borderWidth;
							int lastY = y+(btnHeight)*(getRow(lastPressed)-1)+borderWidth;
							if(HIGHLIGHT == 1){
								Tft.fillRectangle(lastX,lastY,btnWidth-borderWidth-1,btnHeight-borderWidth-1,bgColor);
							}
							//setLabel(lastPressed,labels[getRow(lastPressed)-1][getColumn(lastPressed)-1]);
							printName(lastPressed);
						}

						// Highlight currently pressed button
						if(HIGHLIGHT == 1){
							Tft.fillRectangle(boundX1,boundY1,btnWidth-borderWidth-1,btnHeight-borderWidth-1,highlightColor);
						}
						//setNum(num);
						//setLabel(num,labels[r-1][c-1]);
						printName(num);

						// Call event handler with pressed button id
						eventHandler(this,num);
						pressed = true;
						lastPressed = num;
					}
				}// -- columns for loop
			}// --rows for loop
		}// -- if touch within widget area
		touched = !touched;
		lastMillis = millis();
	}// -- debounce
	return true; // <--- False means block further event checking.
}

void Buttongrid::show(){
	drawGrid();
	update();
}

void Buttongrid::update(){
	return;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) [2014-2015] Novell, Inc.
 * Copyright (c) 2016 SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * 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, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include "storage/Action.h"
#include "storage/DevicegraphImpl.h"
#include "storage/Devices/DeviceImpl.h"
#include "storage/Devices/Partition.h"

namespace storage
{

    namespace Action
    {

	Text
	Create::text(const Actiongraph::Impl& actiongraph, Tense tense) const
	{
	    return get_device_rhs(actiongraph)->get_impl().do_create_text(tense);
	}

	void
	Create::commit(const Actiongraph::Impl& actiongraph) const
	{
	    get_device_rhs(actiongraph)->get_impl().do_create();
	}

	Text
	Delete::text(const Actiongraph::Impl& actiongraph, Tense tense) const
	{
	    return get_device_lhs(actiongraph)->get_impl().do_delete_text(tense);
	}

	void
	Delete::commit(const Actiongraph::Impl& actiongraph) const
	{
	    get_device_lhs(actiongraph)->get_impl().do_delete();
	}

	void
	Create::add_dependencies(Actiongraph::Impl::vertex_descriptor v, Actiongraph::Impl& actiongraph) const
	{
	    Base::add_dependencies(v, actiongraph);

	    sid_t sid = actiongraph[v]->sid;

	    Devicegraph::Impl::vertex_descriptor v_in_rhs = actiongraph.get_devicegraph(RHS)->get_impl().find_vertex(sid);

	    // iterate parents
	    Devicegraph::Impl::inv_adjacency_iterator vi, vi_end;
	    for (boost::tie(vi, vi_end) = inv_adjacent_vertices(v_in_rhs, actiongraph.get_devicegraph(RHS)->get_impl().graph); vi != vi_end; ++vi)
	    {
		sid_t parent_sid = actiongraph.get_devicegraph(RHS)->get_impl()[*vi]->get_sid();

		if (!actiongraph.get_devicegraph(LHS)->device_exists(parent_sid))
		{
		    // parents must be created beforehand if not existed

		    Actiongraph::Impl::vertex_descriptor tmp = actiongraph.actions_with_sid(parent_sid, ONLY_LAST).front();
		    actiongraph.add_edge(tmp, v);
		}
		else
		{
		    // children of parents must be deleted beforehand

		    Devicegraph::Impl::vertex_descriptor q = actiongraph.get_devicegraph(LHS)->get_impl().find_vertex(parent_sid);

		    Devicegraph::Impl::adjacency_iterator vi2, vi2_end;
		    for (boost::tie(vi2, vi2_end) = adjacent_vertices(q, actiongraph.get_devicegraph(LHS)->get_impl().graph); vi2 != vi2_end; ++vi2)
		    {
			sid_t child_sid = actiongraph.get_devicegraph(LHS)->get_impl()[*vi2]->get_sid();

			vector<Actiongraph::Impl::vertex_descriptor> tmp = actiongraph.actions_with_sid(child_sid, ONLY_LAST);
			if (!tmp.empty())
			{
			    // Make sure it's a delete action
			    const Action::Base* tmp_action = actiongraph[tmp.front()];
			    if (dynamic_cast<const Action::Delete*>(tmp_action))
				actiongraph.add_edge(tmp.front(), v);
			}
		    }
		}
	    }

	}

	void
	Delete::add_dependencies(Actiongraph::Impl::vertex_descriptor v, Actiongraph::Impl& actiongraph) const
	{
	    Base::add_dependencies(v, actiongraph);

	    // all children must be deleted beforehand

	    sid_t sid = actiongraph[v]->sid;

	    Devicegraph::Impl::vertex_descriptor v_in_lhs = actiongraph.get_devicegraph(LHS)->get_impl().find_vertex(sid);

	    // iterate children
	    Devicegraph::Impl::inv_adjacency_iterator vi, vi_end;
	    for (boost::tie(vi, vi_end) = inv_adjacent_vertices(v_in_lhs, actiongraph.get_devicegraph(LHS)->get_impl().graph); vi != vi_end; ++vi)
	    {
		sid_t child_sid = actiongraph.get_devicegraph(RHS)->get_impl()[*vi]->get_sid();

		for (Actiongraph::Impl::vertex_descriptor tmp : actiongraph.actions_with_sid(child_sid, ONLY_FIRST))
		    actiongraph.add_edge(v, tmp);
	    }
	}

    }

}
<commit_msg>- coding style<commit_after>/*
 * Copyright (c) [2014-2015] Novell, Inc.
 * Copyright (c) 2016 SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * 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, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include "storage/Action.h"
#include "storage/DevicegraphImpl.h"
#include "storage/Devices/DeviceImpl.h"
#include "storage/Devices/Partition.h"

namespace storage
{

    namespace Action
    {

	Text
	Create::text(const Actiongraph::Impl& actiongraph, Tense tense) const
	{
	    return get_device_rhs(actiongraph)->get_impl().do_create_text(tense);
	}

	void
	Create::commit(const Actiongraph::Impl& actiongraph) const
	{
	    get_device_rhs(actiongraph)->get_impl().do_create();
	}

	Text
	Delete::text(const Actiongraph::Impl& actiongraph, Tense tense) const
	{
	    return get_device_lhs(actiongraph)->get_impl().do_delete_text(tense);
	}

	void
	Delete::commit(const Actiongraph::Impl& actiongraph) const
	{
	    get_device_lhs(actiongraph)->get_impl().do_delete();
	}

	void
	Create::add_dependencies(Actiongraph::Impl::vertex_descriptor v, Actiongraph::Impl& actiongraph) const
	{
	    Base::add_dependencies(v, actiongraph);

	    sid_t sid = actiongraph[v]->sid;

	    Devicegraph::Impl::vertex_descriptor v_in_rhs = actiongraph.get_devicegraph(RHS)->get_impl().find_vertex(sid);

	    // iterate parents
	    Devicegraph::Impl::inv_adjacency_iterator vi, vi_end;
	    for (boost::tie(vi, vi_end) = inv_adjacent_vertices(v_in_rhs, actiongraph.get_devicegraph(RHS)->get_impl().graph); vi != vi_end; ++vi)
	    {
		sid_t parent_sid = actiongraph.get_devicegraph(RHS)->get_impl()[*vi]->get_sid();

		if (!actiongraph.get_devicegraph(LHS)->device_exists(parent_sid))
		{
		    // parents must be created beforehand if not existed

		    Actiongraph::Impl::vertex_descriptor tmp = actiongraph.actions_with_sid(parent_sid, ONLY_LAST).front();
		    actiongraph.add_edge(tmp, v);
		}
		else
		{
		    // children of parents must be deleted beforehand

		    Devicegraph::Impl::vertex_descriptor q = actiongraph.get_devicegraph(LHS)->get_impl().find_vertex(parent_sid);

		    Devicegraph::Impl::adjacency_iterator vi2, vi2_end;
		    for (boost::tie(vi2, vi2_end) = adjacent_vertices(q, actiongraph.get_devicegraph(LHS)->get_impl().graph); vi2 != vi2_end; ++vi2)
		    {
			sid_t child_sid = actiongraph.get_devicegraph(LHS)->get_impl()[*vi2]->get_sid();

			vector<Actiongraph::Impl::vertex_descriptor> tmp = actiongraph.actions_with_sid(child_sid, ONLY_LAST);
			if (!tmp.empty())
			{
			    // Make sure it's a delete action
			    const Action::Base* tmp_action = actiongraph[tmp.front()];
			    if (dynamic_cast<const Action::Delete*>(tmp_action))
				actiongraph.add_edge(tmp.front(), v);
			}
		    }
		}
	    }
	}

	void
	Delete::add_dependencies(Actiongraph::Impl::vertex_descriptor v, Actiongraph::Impl& actiongraph) const
	{
	    Base::add_dependencies(v, actiongraph);

	    // all children must be deleted beforehand

	    sid_t sid = actiongraph[v]->sid;

	    Devicegraph::Impl::vertex_descriptor v_in_lhs = actiongraph.get_devicegraph(LHS)->get_impl().find_vertex(sid);

	    // iterate children
	    Devicegraph::Impl::inv_adjacency_iterator vi, vi_end;
	    for (boost::tie(vi, vi_end) = inv_adjacent_vertices(v_in_lhs, actiongraph.get_devicegraph(LHS)->get_impl().graph); vi != vi_end; ++vi)
	    {
		sid_t child_sid = actiongraph.get_devicegraph(RHS)->get_impl()[*vi]->get_sid();

		for (Actiongraph::Impl::vertex_descriptor tmp : actiongraph.actions_with_sid(child_sid, ONLY_FIRST))
		    actiongraph.add_edge(v, tmp);
	    }
	}

    }

}
<|endoftext|>


<commit_before><commit_msg>Fix socket leak in PluginComm by closing all sockets in error state, checked using poll().<commit_after><|endoftext|>


<commit_before><commit_msg>fixed errors<commit_after><|endoftext|>


<commit_before><commit_msg>Refactored searchtree.cpp<commit_after><|endoftext|>


<commit_before><commit_msg>Raft: Don't set leaders out of the blue<commit_after><|endoftext|>


<commit_before><commit_msg>Fix makeDir on unix<commit_after><|endoftext|>


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

#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLE_HPP_
#include <com/sun/star/accessibility/XAccessible.hpp>
#endif

#ifndef _SAL_TYPES_H_
#include <sal/types.h>
#endif
#ifndef _CPPUHELPER_WEAKREF_HXX_
#include <cppuhelper/weakref.hxx>
#endif
#ifndef _VOS_REF_HXX_
#include <vos/ref.hxx>
#endif
#ifndef _VOS_MUTEX_HXX_ //autogen
#include <vos/mutex.hxx>
#endif
#ifndef _SVX_ACCESSIBILITY_IACCESSIBLE_VIEW_FORWARDER_HXX
#include <svx/IAccessibleViewForwarder.hxx>
#endif
#ifndef _SVX_ACCESSIBILITY_IACCESSIBLE_PARENT_HXX
#include <svx/IAccessibleParent.hxx>
#endif
#ifndef _VIEWSH_HXX
#include "viewsh.hxx"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _FRACT_HXX
#include <tools/fract.hxx>
#endif

#include <vector>

class Rectangle;
class SwFrm;
class SwRootFrm;
class SwPageFrm;
class SwAccessibleContext;
class SwAccessibleContextMap_Impl;
class SwAccessibleEventList_Impl;
class SwAccessibleEventMap_Impl;
class SwShapeList_Impl;
class SdrObject;
namespace accessibility { class AccessibleShape; }
class SwAccessibleShapeMap_Impl;
struct SwAccessibleEvent_Impl;
class SwRect;
class ViewShell;
class SwFrmOrObj;
class SwAccPreviewData;
// OD 14.01.2003 #103492#
#ifndef _PREVWPAGE_HXX
#include <prevwpage.hxx>
#endif

// real states for events
#define ACC_STATE_EDITABLE 0x01
#define ACC_STATE_OPAQUE 0x02

// pseudo states for events
#define ACC_STATE_CARET 0x80
#define ACC_STATE_RELATION_FROM 0x40
#define ACC_STATE_RELATION_TO 0x20

#define ACC_STATE_RELATION_MASK 0x60

#define ACC_STATE_MASK 0x1F

class SwAccessibleMap : public accessibility::IAccessibleViewForwarder,
                        public accessibility::IAccessibleParent
{
    ::vos::OMutex maMutex;
    ::vos::OMutex maEventMutex;
    SwAccessibleContextMap_Impl *mpFrmMap;
    SwAccessibleShapeMap_Impl *mpShapeMap;
    SwShapeList_Impl *mpShapes;
    SwAccessibleEventList_Impl *mpEvents;
    SwAccessibleEventMap_Impl *mpEventMap;
    ViewShell *mpVSh;
    /// for page preview: store preview data, VisArea, and mapping of
    /// preview-to-display coordinates
    SwAccPreviewData* mpPreview;

    ::com::sun::star::uno::WeakReference < ::com::sun::star::accessibility::XAccessible > mxCursorContext;

    sal_Int32 mnPara;
    sal_Int32 mnFootnote;
    sal_Int32 mnEndnote;

    sal_Bool mbShapeSelected;

    void FireEvent( const SwAccessibleEvent_Impl& rEvent );

    void AppendEvent( const SwAccessibleEvent_Impl& rEvent );

    void InvalidateCursorPosition(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::accessibility::XAccessible>& rAcc );
    void DoInvalidateShapeSelection();
    void DoInvalidateShapeFocus();
    void InvalidateShapeSelection();

    void _InvalidateRelationSet( const SwFrm* pFrm, sal_Bool bFrom );

    ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible>
            _GetDocumentView( sal_Bool bPagePreview );

public:

    SwAccessibleMap( ViewShell *pSh );
    ~SwAccessibleMap();

    ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible> GetDocumentView();

    // OD 15.01.2003 #103492# - complete re-factoring of method due to new
    // page/print preview functionality.
    ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible> GetDocumentPreview(
                            const std::vector<PrevwPage*>& _rPrevwPages,
                            const Fraction&  _rScale,
                            const SwPageFrm* _pSelectedPageFrm,
                            const Size&      _rPrevwWinSize );

    ::vos::ORef < SwAccessibleContext > GetContextImpl(
                                                 const SwFrm *pFrm,
                                                sal_Bool bCreate = sal_True );
    ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible> GetContext(
                                                 const SwFrm *pFrm,
                                                sal_Bool bCreate = sal_True );

    ::vos::ORef < ::accessibility::AccessibleShape > GetContextImpl(
                                        const SdrObject *pObj,
                                        SwAccessibleContext *pParentImpl,
                                        sal_Bool bCreate = sal_True );
    ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible> GetContext(
                                        const SdrObject *pObj,
                                        SwAccessibleContext *pParentImpl,
                                        sal_Bool bCreate = sal_True );

    ViewShell *GetShell() const { return mpVSh; }
    inline const SwRect& GetVisArea() const;

    /** get size of a dedicated preview page

        OD 15.01.2003 #103492#
        complete re-factoring of previous method due to new page/print preview
        functionality.

        @author OD

        @param _nPrevwPageNum
        input parameter - physical page number of page visible in the page preview

        @return an object of class <Size>
    */
    Size GetPreViewPageSize( sal_uInt16 _nPrevwPageNum ) const;

    void RemoveContext( const SwFrm *pFrm );
    void RemoveContext( const SdrObject *pObj );

    // Dispose frame and its children if bRecursive is set
    void Dispose( const SwFrm *pFrm, const SdrObject *pObj,
                  sal_Bool bRecursive=sal_False );

    void InvalidatePosOrSize( const SwFrm *pFrm, const SdrObject *pObj,
                              const SwRect& rOldFrm );

    void InvalidateContent( const SwFrm *pFrm );

    void InvalidateCursorPosition( const SwFrm *pFrm );
    void InvalidateFocus();

    void SetCursorContext(
        const ::vos::ORef < SwAccessibleContext >& rCursorContext );

    // Invalidate state of whole tree. If an action is open, this call
    // is processed when the last action ends.
    void InvalidateStates( sal_uInt8 nStates, const SwFrm *pFrm=0 );

    void InvalidateRelationSet( const SwFrm* pMaster, const SwFrm* pFollow );

    // update preview data (and fire events if necessary)
    // OD 15.01.2003 #103492# - complete re-factoring of method due to new
    // page/print preview functionality.
    void UpdatePreview( const std::vector<PrevwPage*>& _rPrevwPages,
                        const Fraction&  _rScale,
                        const SwPageFrm* _pSelectedPageFrm,
                        const Size&      _rPrevwWinSize );

    void InvalidatePreViewSelection( sal_uInt16 nSelPage );
    sal_Bool IsPageSelected( const SwPageFrm *pPageFrm ) const;

    void FireEvents();

    // IAccessibleViewForwarder

    virtual sal_Bool IsValid() const;
    virtual Rectangle GetVisibleArea() const;
    virtual Point LogicToPixel (const Point& rPoint) const;
    virtual Size LogicToPixel (const Size& rSize) const;
    virtual Point PixelToLogic (const Point& rPoint) const;
    virtual Size PixelToLogic (const Size& rSize) const;

    // IAccessibleParent
    virtual sal_Bool ReplaceChild (
        ::accessibility::AccessibleShape* pCurrentChild,
        const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
        const long _nIndex,
        const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo
    )   throw (::com::sun::star::uno::RuntimeException);

    // additional Core/Pixel conversions for internal use; also works
    // for preview
    Point PixelToCore (const Point& rPoint) const;
    Rectangle CoreToPixel (const Rectangle& rRect) const;

private:
    /** get mapping mode for LogicToPixel and PixelToLogic conversions

        OD 15.01.2003 #103492#
        Replacement method <PreviewAdjust(..)> by new method <GetMapMode>.
        Method returns mapping mode of current output device and adjusts it,
        if the shell is in page/print preview.
        Necessary, because <PreviewAdjust(..)> changes mapping mode at current
        output device for mapping logic document positions to page preview window
        positions and vice versa and doesn't take care to recover its changes.

        @author OD

        @param _rPoint
        input parameter - constant reference to point to determine the mapping
        mode adjustments for page/print preview.

        @param _orMapMode
        output parameter - reference to the mapping mode, which is determined
        by the method
    */
    void GetMapMode( const Point& _rPoint,
                     MapMode&     _orMapMode ) const;
};

// helper class that stores preview data
class SwAccPreviewData
{
    typedef std::vector<Rectangle> Rectangles;
    Rectangles maPreviewRects;
    Rectangles maLogicRects;

    SwRect maVisArea;
    Fraction maScale;

    const SwPageFrm *mpSelPage;

    /** adjust logic page retangle to its visible part

        OD 17.01.2003 #103492#

        @author OD

        @param _iorLogicPgSwRect
        input/output parameter - reference to the logic page rectangle, which
        has to be adjusted.

        @param _rPrevwPgSwRect
        input parameter - constant reference to the corresponding preview page
        rectangle; needed to determine the visible part of the logic page rectangle.

        @param _rPrevwWinSize
        input paramter - constant reference to the preview window size in TWIP;
        needed to determine the visible part of the logic page rectangle
    */
    void AdjustLogicPgRectToVisibleArea( SwRect&         _iorLogicPgSwRect,
                                         const SwRect&   _rPrevwPgSwRect,
                                         const Size&     _rPrevwWinSize );

public:
    SwAccPreviewData();
    ~SwAccPreviewData();

    // OD 14.01.2003 #103492# - complete re-factoring of method due to new
    // page/print preview functionality.
    void Update( const std::vector<PrevwPage*>& _rPrevwPages,
                 const Fraction&  _rScale,
                 const SwPageFrm* _pSelectedPageFrm,
                 const Size&      _rPrevwWinSize );

    // OD 14.01.2003 #103492# - complete re-factoring of method due to new
    // page/print preview functionality.
    void InvalidateSelection( const SwPageFrm* _pSelectedPageFrm );

    const SwRect& GetVisArea() const;

    MapMode GetMapModeForPreview( ) const;

    /** Adjust the MapMode so that the preview page appears at the
     * proper position. rPoint identifies the page for which the
     * MapMode should be adjusted. If bFromPreview is true, rPoint is
     * a preview coordinate; else it's a document coordinate. */
    // OD 17.01.2003 #103492# - delete unused 3rd parameter.
    void AdjustMapMode( MapMode& rMapMode,
                        const Point& rPoint ) const;

    inline const SwPageFrm *GetSelPage() const { return mpSelPage; }

    void DisposePage(const SwPageFrm *pPageFrm );
};

inline const SwRect& SwAccessibleMap::GetVisArea() const
{
    DBG_ASSERT( !mpVSh->IsPreView() || (mpPreview != NULL),
                "preview without preview data?" );
    return mpVSh->IsPreView() ? mpPreview->GetVisArea() : mpVSh->VisArea();
}
#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.24.600); FILE MERGED 2005/09/05 13:35:37 rt 1.24.600.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: accmap.hxx,v $
 *
 *  $Revision: 1.25 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 01:31:59 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _ACCMAP_HXX
#define _ACCMAP_HXX

#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLE_HPP_
#include <com/sun/star/accessibility/XAccessible.hpp>
#endif

#ifndef _SAL_TYPES_H_
#include <sal/types.h>
#endif
#ifndef _CPPUHELPER_WEAKREF_HXX_
#include <cppuhelper/weakref.hxx>
#endif
#ifndef _VOS_REF_HXX_
#include <vos/ref.hxx>
#endif
#ifndef _VOS_MUTEX_HXX_ //autogen
#include <vos/mutex.hxx>
#endif
#ifndef _SVX_ACCESSIBILITY_IACCESSIBLE_VIEW_FORWARDER_HXX
#include <svx/IAccessibleViewForwarder.hxx>
#endif
#ifndef _SVX_ACCESSIBILITY_IACCESSIBLE_PARENT_HXX
#include <svx/IAccessibleParent.hxx>
#endif
#ifndef _VIEWSH_HXX
#include "viewsh.hxx"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _FRACT_HXX
#include <tools/fract.hxx>
#endif

#include <vector>

class Rectangle;
class SwFrm;
class SwRootFrm;
class SwPageFrm;
class SwAccessibleContext;
class SwAccessibleContextMap_Impl;
class SwAccessibleEventList_Impl;
class SwAccessibleEventMap_Impl;
class SwShapeList_Impl;
class SdrObject;
namespace accessibility { class AccessibleShape; }
class SwAccessibleShapeMap_Impl;
struct SwAccessibleEvent_Impl;
class SwRect;
class ViewShell;
class SwFrmOrObj;
class SwAccPreviewData;
// OD 14.01.2003 #103492#
#ifndef _PREVWPAGE_HXX
#include <prevwpage.hxx>
#endif

// real states for events
#define ACC_STATE_EDITABLE 0x01
#define ACC_STATE_OPAQUE 0x02

// pseudo states for events
#define ACC_STATE_CARET 0x80
#define ACC_STATE_RELATION_FROM 0x40
#define ACC_STATE_RELATION_TO 0x20

#define ACC_STATE_RELATION_MASK 0x60

#define ACC_STATE_MASK 0x1F

class SwAccessibleMap : public accessibility::IAccessibleViewForwarder,
                        public accessibility::IAccessibleParent
{
    ::vos::OMutex maMutex;
    ::vos::OMutex maEventMutex;
    SwAccessibleContextMap_Impl *mpFrmMap;
    SwAccessibleShapeMap_Impl *mpShapeMap;
    SwShapeList_Impl *mpShapes;
    SwAccessibleEventList_Impl *mpEvents;
    SwAccessibleEventMap_Impl *mpEventMap;
    ViewShell *mpVSh;
    /// for page preview: store preview data, VisArea, and mapping of
    /// preview-to-display coordinates
    SwAccPreviewData* mpPreview;

    ::com::sun::star::uno::WeakReference < ::com::sun::star::accessibility::XAccessible > mxCursorContext;

    sal_Int32 mnPara;
    sal_Int32 mnFootnote;
    sal_Int32 mnEndnote;

    sal_Bool mbShapeSelected;

    void FireEvent( const SwAccessibleEvent_Impl& rEvent );

    void AppendEvent( const SwAccessibleEvent_Impl& rEvent );

    void InvalidateCursorPosition(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::accessibility::XAccessible>& rAcc );
    void DoInvalidateShapeSelection();
    void DoInvalidateShapeFocus();
    void InvalidateShapeSelection();

    void _InvalidateRelationSet( const SwFrm* pFrm, sal_Bool bFrom );

    ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible>
            _GetDocumentView( sal_Bool bPagePreview );

public:

    SwAccessibleMap( ViewShell *pSh );
    ~SwAccessibleMap();

    ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible> GetDocumentView();

    // OD 15.01.2003 #103492# - complete re-factoring of method due to new
    // page/print preview functionality.
    ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible> GetDocumentPreview(
                            const std::vector<PrevwPage*>& _rPrevwPages,
                            const Fraction&  _rScale,
                            const SwPageFrm* _pSelectedPageFrm,
                            const Size&      _rPrevwWinSize );

    ::vos::ORef < SwAccessibleContext > GetContextImpl(
                                                 const SwFrm *pFrm,
                                                sal_Bool bCreate = sal_True );
    ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible> GetContext(
                                                 const SwFrm *pFrm,
                                                sal_Bool bCreate = sal_True );

    ::vos::ORef < ::accessibility::AccessibleShape > GetContextImpl(
                                        const SdrObject *pObj,
                                        SwAccessibleContext *pParentImpl,
                                        sal_Bool bCreate = sal_True );
    ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible> GetContext(
                                        const SdrObject *pObj,
                                        SwAccessibleContext *pParentImpl,
                                        sal_Bool bCreate = sal_True );

    ViewShell *GetShell() const { return mpVSh; }
    inline const SwRect& GetVisArea() const;

    /** get size of a dedicated preview page

        OD 15.01.2003 #103492#
        complete re-factoring of previous method due to new page/print preview
        functionality.

        @author OD

        @param _nPrevwPageNum
        input parameter - physical page number of page visible in the page preview

        @return an object of class <Size>
    */
    Size GetPreViewPageSize( sal_uInt16 _nPrevwPageNum ) const;

    void RemoveContext( const SwFrm *pFrm );
    void RemoveContext( const SdrObject *pObj );

    // Dispose frame and its children if bRecursive is set
    void Dispose( const SwFrm *pFrm, const SdrObject *pObj,
                  sal_Bool bRecursive=sal_False );

    void InvalidatePosOrSize( const SwFrm *pFrm, const SdrObject *pObj,
                              const SwRect& rOldFrm );

    void InvalidateContent( const SwFrm *pFrm );

    void InvalidateCursorPosition( const SwFrm *pFrm );
    void InvalidateFocus();

    void SetCursorContext(
        const ::vos::ORef < SwAccessibleContext >& rCursorContext );

    // Invalidate state of whole tree. If an action is open, this call
    // is processed when the last action ends.
    void InvalidateStates( sal_uInt8 nStates, const SwFrm *pFrm=0 );

    void InvalidateRelationSet( const SwFrm* pMaster, const SwFrm* pFollow );

    // update preview data (and fire events if necessary)
    // OD 15.01.2003 #103492# - complete re-factoring of method due to new
    // page/print preview functionality.
    void UpdatePreview( const std::vector<PrevwPage*>& _rPrevwPages,
                        const Fraction&  _rScale,
                        const SwPageFrm* _pSelectedPageFrm,
                        const Size&      _rPrevwWinSize );

    void InvalidatePreViewSelection( sal_uInt16 nSelPage );
    sal_Bool IsPageSelected( const SwPageFrm *pPageFrm ) const;

    void FireEvents();

    // IAccessibleViewForwarder

    virtual sal_Bool IsValid() const;
    virtual Rectangle GetVisibleArea() const;
    virtual Point LogicToPixel (const Point& rPoint) const;
    virtual Size LogicToPixel (const Size& rSize) const;
    virtual Point PixelToLogic (const Point& rPoint) const;
    virtual Size PixelToLogic (const Size& rSize) const;

    // IAccessibleParent
    virtual sal_Bool ReplaceChild (
        ::accessibility::AccessibleShape* pCurrentChild,
        const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
        const long _nIndex,
        const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo
    )   throw (::com::sun::star::uno::RuntimeException);

    // additional Core/Pixel conversions for internal use; also works
    // for preview
    Point PixelToCore (const Point& rPoint) const;
    Rectangle CoreToPixel (const Rectangle& rRect) const;

private:
    /** get mapping mode for LogicToPixel and PixelToLogic conversions

        OD 15.01.2003 #103492#
        Replacement method <PreviewAdjust(..)> by new method <GetMapMode>.
        Method returns mapping mode of current output device and adjusts it,
        if the shell is in page/print preview.
        Necessary, because <PreviewAdjust(..)> changes mapping mode at current
        output device for mapping logic document positions to page preview window
        positions and vice versa and doesn't take care to recover its changes.

        @author OD

        @param _rPoint
        input parameter - constant reference to point to determine the mapping
        mode adjustments for page/print preview.

        @param _orMapMode
        output parameter - reference to the mapping mode, which is determined
        by the method
    */
    void GetMapMode( const Point& _rPoint,
                     MapMode&     _orMapMode ) const;
};

// helper class that stores preview data
class SwAccPreviewData
{
    typedef std::vector<Rectangle> Rectangles;
    Rectangles maPreviewRects;
    Rectangles maLogicRects;

    SwRect maVisArea;
    Fraction maScale;

    const SwPageFrm *mpSelPage;

    /** adjust logic page retangle to its visible part

        OD 17.01.2003 #103492#

        @author OD

        @param _iorLogicPgSwRect
        input/output parameter - reference to the logic page rectangle, which
        has to be adjusted.

        @param _rPrevwPgSwRect
        input parameter - constant reference to the corresponding preview page
        rectangle; needed to determine the visible part of the logic page rectangle.

        @param _rPrevwWinSize
        input paramter - constant reference to the preview window size in TWIP;
        needed to determine the visible part of the logic page rectangle
    */
    void AdjustLogicPgRectToVisibleArea( SwRect&         _iorLogicPgSwRect,
                                         const SwRect&   _rPrevwPgSwRect,
                                         const Size&     _rPrevwWinSize );

public:
    SwAccPreviewData();
    ~SwAccPreviewData();

    // OD 14.01.2003 #103492# - complete re-factoring of method due to new
    // page/print preview functionality.
    void Update( const std::vector<PrevwPage*>& _rPrevwPages,
                 const Fraction&  _rScale,
                 const SwPageFrm* _pSelectedPageFrm,
                 const Size&      _rPrevwWinSize );

    // OD 14.01.2003 #103492# - complete re-factoring of method due to new
    // page/print preview functionality.
    void InvalidateSelection( const SwPageFrm* _pSelectedPageFrm );

    const SwRect& GetVisArea() const;

    MapMode GetMapModeForPreview( ) const;

    /** Adjust the MapMode so that the preview page appears at the
     * proper position. rPoint identifies the page for which the
     * MapMode should be adjusted. If bFromPreview is true, rPoint is
     * a preview coordinate; else it's a document coordinate. */
    // OD 17.01.2003 #103492# - delete unused 3rd parameter.
    void AdjustMapMode( MapMode& rMapMode,
                        const Point& rPoint ) const;

    inline const SwPageFrm *GetSelPage() const { return mpSelPage; }

    void DisposePage(const SwPageFrm *pPageFrm );
};

inline const SwRect& SwAccessibleMap::GetVisArea() const
{
    DBG_ASSERT( !mpVSh->IsPreView() || (mpPreview != NULL),
                "preview without preview data?" );
    return mpVSh->IsPreView() ? mpPreview->GetVisArea() : mpVSh->VisArea();
}
#endif
<|endoftext|>


<commit_before><commit_msg>sstables_loader: mutation_fragment_v1_stream() instead of downgrade_to_v1()<commit_after><|endoftext|>


<commit_before>#include "broker.h"
#include "frame.h"
#include <sstream>
#include <thread>
#include <sys/socket.h>

Broker::Broker() {
    topicRoot = new TopicNode("", "");
}

Broker::~Broker() {
    delete topicRoot;
}

MQTT_ERROR Broker::Start() {
    struct sockaddr_in addr;
    int listener = socket(AF_INET, SOCK_STREAM, 0);
    addr.sin_family = AF_INET;
    addr.sin_port = 8883;
    addr.sin_addr.s_addr = INADDR_ANY;
    bind(listener, (struct sockaddr *)&addr, sizeof(addr));
    listen(listener, 5);
    while (true) {
        struct sockaddr_in client;
        unsigned int len = sizeof(client);
        int sock = accept(listener, (struct sockaddr *)&client, &len);
        BrokerSideClient* bc = new BrokerSideClient(new Transport(sock, &client), this);
        std::thread t(readLoop, bc);
        t.join();
        bc->readThread = &t;
    }

    return NO_ERROR;
}

MQTT_ERROR Broker::checkQoSAndPublish(BrokerSideClient* requestClient, uint8_t publisherQoS, uint8_t requestedQoS, bool retain, std::string topic, std::string message) {
    uint16_t id = 0;
    MQTT_ERROR err = NO_ERROR;
    uint8_t qos = publisherQoS;
    if (requestedQoS < publisherQoS) {
        // QoS downgrade
        qos = requestedQoS;
    }
    if (qos > 0) {
        err = requestClient->getUsablePacketID(&id);
        if (err != NO_ERROR) {
            return err;
        }
    }
    err = requestClient->sendMessage(new PublishMessage(false, qos, retain, id, topic, message));
    return err;
}

std::string Broker::ApplyDummyClientID() {
    std::stringstream ss;
    ss << "DummyClientID" << clients.size() + 1;
    return ss.str();
}

BrokerSideClient::BrokerSideClient(Transport* ct, Broker* b) : broker(b), Terminal("", NULL, 0, NULL) {
    this->ct = ct;
}

BrokerSideClient::~BrokerSideClient() {}

void BrokerSideClient::setPreviousSession(BrokerSideClient* ps) {
    subTopics = ps->subTopics;
    packetIDMap = ps->packetIDMap;
    cleanSession = ps->cleanSession;
    will = ps->will;
    user = ps->user;
    keepAlive = ps->keepAlive;
}

MQTT_ERROR BrokerSideClient::recvConnectMessage(ConnectMessage* m) {return NO_ERROR;}
MQTT_ERROR BrokerSideClient::recvConnackMessage(ConnackMessage* m) {return INVALID_MESSAGE_CAME;}
MQTT_ERROR BrokerSideClient::recvPublishMessage(PublishMessage* m) {
    if (m->fh->Dup) {
        // re-delivered
    } else {
        // first time delivery
    }

    MQTT_ERROR err = NO_ERROR;
    if (m->fh->Retain) {
        std::string data = m->payload;
        if (m->fh->QoS == 0 && data.size() > 0) {
            data = "";
        }
        broker->topicRoot->applyRetain(m->topicName, m->fh->QoS, data, err);
        if (err != NO_ERROR) {
            return err;
        }
    }

    std::vector<TopicNode*> nodes = broker->topicRoot->getTopicNode(m->topicName, true, err);
    if (err != NO_ERROR) {
        return err;
    }

    for (std::map<std::string, uint8_t>::iterator it = nodes[0]->subscribers.begin(); it != nodes[0]->subscribers.end(); it++) {
        if (nodes[0]->subscribers.find(it->first) == nodes[0]->subscribers.end()) {
            continue;
        }
        BrokerSideClient* subscriber = broker->clients[it->first];
        err = broker->checkQoSAndPublish(subscriber, m->fh->QoS, it->second, false, m->topicName, m->payload);
        }

    switch (m->fh->QoS) {
    case 0:
        if (m->fh->PacketID != 0){
            return PACKET_ID_SHOULD_BE_ZERO;
        }
    case 1:
        sendMessage(new PubackMessage(m->fh->PacketID));
    case 2:
        sendMessage(new PubrecMessage(m->fh->PacketID));
    }

    return err;
}

MQTT_ERROR BrokerSideClient::recvPubackMessage(PubackMessage* m) {
    if (m->fh->PacketID > 0) {
        return ackMessage(m->fh->PacketID);
    }
    return NO_ERROR;
}

MQTT_ERROR BrokerSideClient::recvPubrecMessage(PubrecMessage* m) {
    MQTT_ERROR err = ackMessage(m->fh->PacketID);
    if (err < 0) {
        return err;
    }
    err = sendMessage(new PubrelMessage(m->fh->PacketID));
    return err;
}

MQTT_ERROR BrokerSideClient::recvPubrelMessage(PubrelMessage* m) {
    MQTT_ERROR err = ackMessage(m->fh->PacketID);
    if (err < 0) {
        return err;
    }
    err = sendMessage(new PubcompMessage(m->fh->PacketID));
    return err;
}

MQTT_ERROR BrokerSideClient::recvPubcompMessage(PubcompMessage* m) {
    return ackMessage(m->fh->PacketID);
}

MQTT_ERROR BrokerSideClient::recvSubscribeMessage(SubscribeMessage* m) {
    std::vector<SubackCode> returnCodes;

    MQTT_ERROR err; // this sould be duplicate?
    for (std::vector<SubscribeTopic*>::iterator it = m->subTopics.begin(); it != m->subTopics.end(); it++) {
        std::vector<TopicNode*> nodes = broker->topicRoot->getTopicNode((*it)->topic, true, err);
        SubackCode code = (SubackCode)(*it)->qos;

        if (err != NO_ERROR) {
            code = FAILURE;
        } else {
            for (std::vector<TopicNode*>::iterator nIt = nodes.begin(); nIt != nodes.end(); nIt++) {
                (*nIt)->subscribers[ID] = (*it)->qos;
                subTopics[(*it)->topic] = (*it)->qos;
                if ((*nIt)->retainMessage.size() > 0) {
                    err = this->broker->checkQoSAndPublish(this, (*nIt)->retainQoS, (*it)->qos, true, (*nIt)->fullPath,(*nIt)->retainMessage);
                    if (err != NO_ERROR) {
                        return err;
                    }
                }
            }
        }
        returnCodes.push_back(code);
    }
    return sendMessage(new SubackMessage(m->fh->PacketID, returnCodes));
}

MQTT_ERROR BrokerSideClient::recvSubackMessage(SubackMessage* m) {return INVALID_MESSAGE_CAME;}

MQTT_ERROR BrokerSideClient::recvUnsubscribeMessage(UnsubscribeMessage* m) {
    if (m->topics.size() == 0) {
        return PROTOCOL_VIOLATION;
    }

    MQTT_ERROR err = NO_ERROR;
    for (std::vector<std::string>::iterator it = m->topics.begin(); it != m->topics.end(); it++) {
        this->broker->topicRoot->deleteSubscriber(this->ID, *it, err);
        this->subTopics.erase(*it);
    }

    this->sendMessage(new UnsubackMessage(m->fh->PacketID));
    return err;
}

MQTT_ERROR BrokerSideClient::recvUnsubackMessage(UnsubackMessage* m) {return INVALID_MESSAGE_CAME;}
MQTT_ERROR BrokerSideClient::recvPingreqMessage(PingreqMessage* m) {return NO_ERROR;}
MQTT_ERROR BrokerSideClient::recvPingrespMessage(PingrespMessage* m) {return INVALID_MESSAGE_CAME;}
MQTT_ERROR BrokerSideClient::recvDisconnectMessage(DisconnectMessage* m) {return NO_ERROR;}
<commit_msg>add recvConnectMessage inside<commit_after>#include "broker.h"
#include "frame.h"
#include <sstream>
#include <thread>
#include <sys/socket.h>

Broker::Broker() {
    topicRoot = new TopicNode("", "");
}

Broker::~Broker() {
    delete topicRoot;
}

MQTT_ERROR Broker::Start() {
    struct sockaddr_in addr;
    int listener = socket(AF_INET, SOCK_STREAM, 0);
    addr.sin_family = AF_INET;
    addr.sin_port = 8883;
    addr.sin_addr.s_addr = INADDR_ANY;
    bind(listener, (struct sockaddr *)&addr, sizeof(addr));
    listen(listener, 5);
    while (true) {
        struct sockaddr_in client;
        unsigned int len = sizeof(client);
        int sock = accept(listener, (struct sockaddr *)&client, &len);
        BrokerSideClient* bc = new BrokerSideClient(new Transport(sock, &client), this);
        std::thread t(readLoop, bc);
        t.join();
        bc->readThread = &t;
    }

    return NO_ERROR;
}

MQTT_ERROR Broker::checkQoSAndPublish(BrokerSideClient* requestClient, uint8_t publisherQoS, uint8_t requestedQoS, bool retain, std::string topic, std::string message) {
    uint16_t id = 0;
    MQTT_ERROR err = NO_ERROR;
    uint8_t qos = publisherQoS;
    if (requestedQoS < publisherQoS) {
        // QoS downgrade
        qos = requestedQoS;
    }
    if (qos > 0) {
        err = requestClient->getUsablePacketID(&id);
        if (err != NO_ERROR) {
            return err;
        }
    }
    err = requestClient->sendMessage(new PublishMessage(false, qos, retain, id, topic, message));
    return err;
}

std::string Broker::ApplyDummyClientID() {
    std::stringstream ss;
    ss << "DummyClientID" << clients.size() + 1;
    return ss.str();
}

BrokerSideClient::BrokerSideClient(Transport* ct, Broker* b) : broker(b), Terminal("", NULL, 0, NULL) {
    this->ct = ct;
}

BrokerSideClient::~BrokerSideClient() {}

void BrokerSideClient::setPreviousSession(BrokerSideClient* ps) {
    subTopics = ps->subTopics;
    packetIDMap = ps->packetIDMap;
    cleanSession = ps->cleanSession;
    will = ps->will;
    user = ps->user;
    keepAlive = ps->keepAlive;
}

MQTT_ERROR BrokerSideClient::recvConnectMessage(ConnectMessage* m) {
    if (m->Protocol.name != MQTT_3_1_1.name) {
        return INVALID_PROTOCOL_NAME;
    }
    if (m->Protocol.level != MQTT_3_1_1.level) {
        sendMessage(new ConnackMessage(false, CONNECT_UNNACCEPTABLE_PROTOCOL_VERSION));
        return INVALID_PROTOCOL_NAME;
    }
    std::map<std::string, BrokerSideClient*>::iterator bc = broker->clients.find(m->ClientID);
    if (bc != broker->clients.end() && bc->second->isConnecting) {
        sendMessage(new ConnackMessage(false, CONNECT_IDENTIFIER_REJECTED));
        return CLIENT_ID_IS_USED_ALREADY;
    }
    bool cs = (ConnectFlag)(m->Flags&CLEANSESSION_FLAG) == CLEANSESSION_FLAG;
    if (bc != broker->clients.end() && !cleanSession) {
        // set previous session
    } else if (!cs && m->ClientID.size() == 0) {
        sendMessage(new ConnackMessage(false, CONNECT_IDENTIFIER_REJECTED));
        return CLEANSESSION_MUST_BE_TRUE;
    }

    bool sessionPresent = bc != broker->clients.end();
    if (cs || !sessionPresent) {
        // set torelant Duration
        if (m->ClientID.size() == 0) {
            m->ClientID = broker->ApplyDummyClientID();
        }
        ID = m->ClientID;
        user = m->user;
        will = m->will;
        keepAlive = m->KeepAlive;
        cleanSession = cs;
        sessionPresent = false;
    }
    broker->clients[m->ClientID] = this;

    if ((ConnectFlag)(m->Flags&WILL_FLAG) == WILL_FLAG) {
        will = m->will;
    } else {

    }
    if (m->KeepAlive != 0) {
        // start keepalive timer/loop
    }
    isConnecting = true;
    sendMessage(new ConnackMessage(sessionPresent, CONNECT_ACCEPTED));
    // redelivery
    return NO_ERROR;

}
MQTT_ERROR BrokerSideClient::recvConnackMessage(ConnackMessage* m) {return INVALID_MESSAGE_CAME;}
MQTT_ERROR BrokerSideClient::recvPublishMessage(PublishMessage* m) {
    if (m->fh->Dup) {
        // re-delivered
    } else {
        // first time delivery
    }

    MQTT_ERROR err = NO_ERROR;
    if (m->fh->Retain) {
        std::string data = m->payload;
        if (m->fh->QoS == 0 && data.size() > 0) {
            data = "";
        }
        broker->topicRoot->applyRetain(m->topicName, m->fh->QoS, data, err);
        if (err != NO_ERROR) {
            return err;
        }
    }

    std::vector<TopicNode*> nodes = broker->topicRoot->getTopicNode(m->topicName, true, err);
    if (err != NO_ERROR) {
        return err;
    }

    for (std::map<std::string, uint8_t>::iterator it = nodes[0]->subscribers.begin(); it != nodes[0]->subscribers.end(); it++) {
        if (nodes[0]->subscribers.find(it->first) == nodes[0]->subscribers.end()) {
            continue;
        }
        BrokerSideClient* subscriber = broker->clients[it->first];
        err = broker->checkQoSAndPublish(subscriber, m->fh->QoS, it->second, false, m->topicName, m->payload);
        }

    switch (m->fh->QoS) {
    case 0:
        if (m->fh->PacketID != 0){
            return PACKET_ID_SHOULD_BE_ZERO;
        }
    case 1:
        sendMessage(new PubackMessage(m->fh->PacketID));
    case 2:
        sendMessage(new PubrecMessage(m->fh->PacketID));
    }

    return err;
}

MQTT_ERROR BrokerSideClient::recvPubackMessage(PubackMessage* m) {
    if (m->fh->PacketID > 0) {
        return ackMessage(m->fh->PacketID);
    }
    return NO_ERROR;
}

MQTT_ERROR BrokerSideClient::recvPubrecMessage(PubrecMessage* m) {
    MQTT_ERROR err = ackMessage(m->fh->PacketID);
    if (err < 0) {
        return err;
    }
    err = sendMessage(new PubrelMessage(m->fh->PacketID));
    return err;
}

MQTT_ERROR BrokerSideClient::recvPubrelMessage(PubrelMessage* m) {
    MQTT_ERROR err = ackMessage(m->fh->PacketID);
    if (err < 0) {
        return err;
    }
    err = sendMessage(new PubcompMessage(m->fh->PacketID));
    return err;
}

MQTT_ERROR BrokerSideClient::recvPubcompMessage(PubcompMessage* m) {
    return ackMessage(m->fh->PacketID);
}

MQTT_ERROR BrokerSideClient::recvSubscribeMessage(SubscribeMessage* m) {
    std::vector<SubackCode> returnCodes;

    MQTT_ERROR err; // this sould be duplicate?
    for (std::vector<SubscribeTopic*>::iterator it = m->subTopics.begin(); it != m->subTopics.end(); it++) {
        std::vector<TopicNode*> nodes = broker->topicRoot->getTopicNode((*it)->topic, true, err);
        SubackCode code = (SubackCode)(*it)->qos;

        if (err != NO_ERROR) {
            code = FAILURE;
        } else {
            for (std::vector<TopicNode*>::iterator nIt = nodes.begin(); nIt != nodes.end(); nIt++) {
                (*nIt)->subscribers[ID] = (*it)->qos;
                subTopics[(*it)->topic] = (*it)->qos;
                if ((*nIt)->retainMessage.size() > 0) {
                    err = this->broker->checkQoSAndPublish(this, (*nIt)->retainQoS, (*it)->qos, true, (*nIt)->fullPath,(*nIt)->retainMessage);
                    if (err != NO_ERROR) {
                        return err;
                    }
                }
            }
        }
        returnCodes.push_back(code);
    }
    return sendMessage(new SubackMessage(m->fh->PacketID, returnCodes));
}

MQTT_ERROR BrokerSideClient::recvSubackMessage(SubackMessage* m) {return INVALID_MESSAGE_CAME;}

MQTT_ERROR BrokerSideClient::recvUnsubscribeMessage(UnsubscribeMessage* m) {
    if (m->topics.size() == 0) {
        return PROTOCOL_VIOLATION;
    }

    MQTT_ERROR err = NO_ERROR;
    for (std::vector<std::string>::iterator it = m->topics.begin(); it != m->topics.end(); it++) {
        this->broker->topicRoot->deleteSubscriber(this->ID, *it, err);
        this->subTopics.erase(*it);
    }

    this->sendMessage(new UnsubackMessage(m->fh->PacketID));
    return err;
}

MQTT_ERROR BrokerSideClient::recvUnsubackMessage(UnsubackMessage* m) {return INVALID_MESSAGE_CAME;}
MQTT_ERROR BrokerSideClient::recvPingreqMessage(PingreqMessage* m) {return NO_ERROR;}
MQTT_ERROR BrokerSideClient::recvPingrespMessage(PingrespMessage* m) {return INVALID_MESSAGE_CAME;}
MQTT_ERROR BrokerSideClient::recvDisconnectMessage(DisconnectMessage* m) {return NO_ERROR;}
<|endoftext|>


<commit_before>#include "btree.h"
#include <memory>
#include <cmath>
#include <string>
#include <iostream>

namespace {
using std::unique_ptr;
using std::move;
using std::vector;
using std::ceil;
using std::string;
using std::to_string;
using std::cout;
using std::endl;
}

namespace btree {
void node::check_invariants() {
  for(auto i = size + 1; i != range_max + 1; ++i) {
    if(children[i].get() != nullptr) {
      fprintf(stderr, "node found with child past size. Debugging suggested.");
    }
  }
}

bool node::is_leaf() {
  for(size_t i = 0, end = size; i != end; ++i) {
    if((bool) children[i])
      return false;
  }
  return true;
}

size_t node::find_pos(const key_t& key) {
  size_t pos = 0;
  for(size_t end = size; pos != end && keys[pos] < key; ++pos);
  return pos;
}

void node::place_key(const key_t& key, const size_t pos) {
  check_invariants();

  if(size > 0) {
    for(size_t i = size; i > pos; --i) {
      keys[i] = keys[i - 1];
      if((bool) children[i+1])
        size = size; // debug
      children[i+1] = move(children[i]);
    }
  }
  keys[pos] = key;
  ++size;

  check_invariants();
}

void node::insert(key_t key) {
  check_invariants();

  // assert(parent)                   // required by split
  // assert(parent->size < range_max) // required by split

  if(!is_leaf()) {
    auto key_pos = find_pos(key);
    if(!children[key_pos])
      children[key_pos] = unique_ptr<node>(new node(this, tree));
    else if(children[key_pos]->size == range_max) {
      split(children[key_pos].get());
      key_pos = find_pos(key);
    }
    children[key_pos]->insert(key);

    check_invariants();
    return;
  }

  place_key(key, find_pos(key));

  check_invariants();
}

void node::add(key_t key, unique_ptr<node>& other) {
  check_invariants();

  // assert(size < range_max)
  // assert(other.get() != nullptr)

  const auto pos = find_pos(key);
  place_key(key, pos);
  children[pos + 1] = move(other);
  children[pos + 1]->parent = this;

  check_invariants();
}

/// @todo make member of node. static??
void node::split(node* old_node) {
  old_node->check_invariants();
  old_node->parent->check_invariants();

  // assert(old_node)
  // assert(old_node->parent)
  // assert(old_node->parent->size < range_max)

  unique_ptr<node> new_node(new node(old_node->parent, old_node->tree));
  node* new_node_raw = new_node.get();

  const size_t median = range_max / 2;
  const key_t median_key = old_node->keys[median];

  if((bool) old_node->children[median + 1]) {
    new_node->children[0] = move(old_node->children[median + 1]);
    new_node->children[0]->parent = new_node_raw;
  }
  for(size_t i = median + 1, new_node_i = 0, end = range_max; i != end; ++i, ++new_node_i) {
    new_node->keys[new_node_i] = old_node->keys[i];
    if(old_node->children[i + 1]) {
      new_node->children[new_node_i + 1] = move(old_node->children[i + 1]);
      new_node->children[new_node_i + 1]->parent = new_node.get();
    }
    ++new_node->size;
    --old_node->size;
  }
  --old_node->size; // remove the median

  old_node->parent->add(median_key, new_node);

  old_node->check_invariants();
  new_node_raw->check_invariants();
  old_node->parent->check_invariants();
}

void tree::reroot() {
  // assert(root)
  root.get()->check_invariants();

  auto new_root = unique_ptr<node>(new node(nullptr, this));
  auto old_root_raw = root.get();
  root->parent = new_root.get();
  new_root->children[0] = move(root);
  new_root->children[0]->parent = new_root.get();
  root = move(new_root);
  node::split(old_root_raw);

  root.get()->check_invariants();
  old_root_raw->check_invariants();
}

void tree::insert(key_t key) {
  if(root->size == range_max)
    reroot();
  root->insert(key);
}

string node::str() {
  string s;
//  s += "["; // debug
  for(size_t i = 0, end = size; i != end; ++i) {
    if((bool) children[i])
      s += children[i]->str() + ", ";
    s += to_string(keys[i]) + ", ";
  }

  if((bool) children[size])
    s += children[size]->str();
  else
    s.erase(s.end() -2, s.end()); // erase the last ", "
//  s += "]"; // debug
  return s;
}

string tree::str() {
  return "[" + root->str() + "]";
}

}  // namespace btree
<commit_msg>changed check_invariants() to not execute if NDEBUG is defined<commit_after>#include "btree.h"
#include <memory>
#include <cmath>
#include <string>
#include <iostream>

namespace {
using std::unique_ptr;
using std::move;
using std::vector;
using std::ceil;
using std::string;
using std::to_string;
using std::cout;
using std::endl;
}

namespace btree {
void node::check_invariants() {
#ifdef NDEBUG
  return
#else
  for(auto i = size + 1; i != range_max + 1; ++i) {
    if(children[i].get() != nullptr) {
      fprintf(stderr, "node found with child past size. Debugging suggested.");
    }
  }
#endif
}

bool node::is_leaf() {
  for(size_t i = 0, end = size; i != end; ++i) {
    if((bool) children[i])
      return false;
  }
  return true;
}

size_t node::find_pos(const key_t& key) {
  size_t pos = 0;
  for(size_t end = size; pos != end && keys[pos] < key; ++pos);
  return pos;
}

void node::place_key(const key_t& key, const size_t pos) {
  check_invariants();

  if(size > 0) {
    for(size_t i = size; i > pos; --i) {
      keys[i] = keys[i - 1];
      if((bool) children[i+1])
        size = size; // debug
      children[i+1] = move(children[i]);
    }
  }
  keys[pos] = key;
  ++size;

  check_invariants();
}

void node::insert(key_t key) {
  check_invariants();

  // assert(parent)                   // required by split
  // assert(parent->size < range_max) // required by split

  if(!is_leaf()) {
    auto key_pos = find_pos(key);
    if(!children[key_pos])
      children[key_pos] = unique_ptr<node>(new node(this, tree));
    else if(children[key_pos]->size == range_max) {
      split(children[key_pos].get());
      key_pos = find_pos(key);
    }
    children[key_pos]->insert(key);

    check_invariants();
    return;
  }

  place_key(key, find_pos(key));

  check_invariants();
}

void node::add(key_t key, unique_ptr<node>& other) {
  check_invariants();

  // assert(size < range_max)
  // assert(other.get() != nullptr)

  const auto pos = find_pos(key);
  place_key(key, pos);
  children[pos + 1] = move(other);
  children[pos + 1]->parent = this;

  check_invariants();
}

/// @todo make member of node. static??
void node::split(node* old_node) {
  old_node->check_invariants();
  old_node->parent->check_invariants();

  // assert(old_node)
  // assert(old_node->parent)
  // assert(old_node->parent->size < range_max)

  unique_ptr<node> new_node(new node(old_node->parent, old_node->tree));
  node* new_node_raw = new_node.get();

  const size_t median = range_max / 2;
  const key_t median_key = old_node->keys[median];

  if((bool) old_node->children[median + 1]) {
    new_node->children[0] = move(old_node->children[median + 1]);
    new_node->children[0]->parent = new_node_raw;
  }
  for(size_t i = median + 1, new_node_i = 0, end = range_max; i != end; ++i, ++new_node_i) {
    new_node->keys[new_node_i] = old_node->keys[i];
    if(old_node->children[i + 1]) {
      new_node->children[new_node_i + 1] = move(old_node->children[i + 1]);
      new_node->children[new_node_i + 1]->parent = new_node.get();
    }
    ++new_node->size;
    --old_node->size;
  }
  --old_node->size; // remove the median

  old_node->parent->add(median_key, new_node);

  old_node->check_invariants();
  new_node_raw->check_invariants();
  old_node->parent->check_invariants();
}

void tree::reroot() {
  // assert(root)
  root.get()->check_invariants();

  auto new_root = unique_ptr<node>(new node(nullptr, this));
  auto old_root_raw = root.get();
  root->parent = new_root.get();
  new_root->children[0] = move(root);
  new_root->children[0]->parent = new_root.get();
  root = move(new_root);
  node::split(old_root_raw);

  root.get()->check_invariants();
  old_root_raw->check_invariants();
}

void tree::insert(key_t key) {
  if(root->size == range_max)
    reroot();
  root->insert(key);
}

string node::str() {
  string s;
//  s += "["; // debug
  for(size_t i = 0, end = size; i != end; ++i) {
    if((bool) children[i])
      s += children[i]->str() + ", ";
    s += to_string(keys[i]) + ", ";
  }

  if((bool) children[size])
    s += children[size]->str();
  else
    s.erase(s.end() -2, s.end()); // erase the last ", "
//  s += "]"; // debug
  return s;
}

string tree::str() {
  return "[" + root->str() + "]";
}

}  // namespace btree
<|endoftext|>