<commit_before>/*
1. Treat each edge id as a cluster, unordered map from edgeId to a set
2. also store size of each cluster which will 0 in the begining
//  $ g++ -std=c++0x -O3 -o calcDensityForDiffThresh calcDensityForDiffThresh.cpp
//  $ ./calcDensityForDiffThresh networkEdgeIdMap.csv network.jaccs sortedjaccs.csv  Nthresholds threshDensity.csv
*/
#include <math.h>
#include <ctime>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <unordered_map>
#include <set>
#include <map>
#include <utility>   // for pairs
#include <algorithm> // for swap
using namespace std;

int main (int argc, char const *argv[]){
    //************* make sure args are present:
    if (argc != 6){
        cout << "ERROR: something wrong with the inputs" << endl;
        cout << "usage:\n    " << argv[0] << " networkEdgeIdMap.csv network.jaccs sortedjaccs.csv  "
                    << " Nthresholds threshDensity.csv" << endl;
        exit(1);
    }
    // Nthresholds is the total thresholds user wants us to try
    int nThresh = atoi(argv[4]);
    cout << "nThresh = " << nThresh << endl;
    int gapBetweenthresh = 0;
    float threshold = 0;
    float D = 0.0;
    int mc, nc;
    int M = 0, Mns = 0;
    double wSum = 0.0;
    float highestD=0.0;
    float highestDThr = 0.0;
    //************* got the args
    clock_t begin = clock();

    //************* start load edgelist
    ifstream inFile;
    inFile.open( argv[1] );
    if (!inFile) {
        cout << "ERROR: unable to open input file" << endl;
        exit(1); // terminate with error
    }
    // store edge ids in a map
    // each edge id will be a cluster of it's own in the begining
    // each cluster will be og size 1
    unordered_map< int,  pair<int,int> > idEdgePairMap;
    unordered_map< int,  set<int > > index2cluster; // O(log n) access too slow?
    unordered_map< int,  unordered_map< int, set<int > >::iterator > edge2iter;
    int ni, nj, edgeId, index = 0;
    while (inFile >> ni >> nj >> edgeId){
        idEdgePairMap[ edgeId ] = make_pair(ni,nj);
        index2cluster[ index ].insert(edgeId);         // build cluster index to set of edge-pairs map
        edge2iter[edgeId] = index2cluster.find(index);
        index++;
    }
    inFile.close(); inFile.clear();
    cout << "There were " << index2cluster.size() << " edges. ";
    cout << "Time taken = " << double(clock() - begin)/ CLOCKS_PER_SEC << " seconds. "<< endl;
    /// end reading edge ids -----

    //----- ----- ----- -----
    ifstream sortedjaccFile;
    sortedjaccFile.open( argv[3] );
    if (!sortedjaccFile) {
        cout << "ERROR: unable to open sortedjaccFile file" << endl;
        exit(1); // terminate with error
    }
    int totalThresh = 0;
    int edgeId1,edgeId2;
    double jacc;
    // Count totalines in the file, we are setting
    while ( sortedjaccFile  >> jacc ) {
        if(jacc>0 && jacc<=1.0)
            totalThresh++;
    }
    sortedjaccFile.close(); sortedjaccFile.clear();
    cout << "Done counting totalines in the file, \nTotal unique Jaccs = " << totalThresh;
    cout << ".  Time taken = " << double(clock() - begin)/ CLOCKS_PER_SEC << " seconds. "<< endl;
    if(totalThresh==0){
        cout << "ERROR: there are 0 Jaccs!!!" << endl;
        exit(1); // terminate with error
    }
    // now we want gap between two consecutive thresholds
    // we want to consider
    gapBetweenthresh =  totalThresh/nThresh;
    if(totalThresh < nThresh)
            gapBetweenthresh = totalThresh;
    set<float> thresholdSet;
    set<float> ::reverse_iterator thIt;
    cout << "thresholds" << endl;
    // ----------------------------
    totalThresh = -1;
    sortedjaccFile.open( argv[3] );
    while ( sortedjaccFile  >> jacc ){
        totalThresh++;
        if(totalThresh%gapBetweenthresh!=0){
            continue;
        }
        cout << jacc << endl;
        thresholdSet.insert(jacc);
    }
    sortedjaccFile.close(); sortedjaccFile.clear();
    thresholdSet.insert(1.1);
    cout << "Done with thresholdSet creation.";
    cout << "  Time taken = " << double(clock() - begin)/ CLOCKS_PER_SEC << " seconds. "<< endl;
    // ---------------------------

    ifstream jaccFile;
    jaccFile.open(argv[2]);
    // read first line
    jaccFile >> edgeId1 >> edgeId2 >> jacc ;
    // open the outputfile
    unordered_map< int, set< int> >::iterator iter_i,iter_j;
    set<int>::iterator iterS;
    FILE * threshDensityFile = fopen( argv[5], "w" );
    fclose(threshDensityFile);
    fprintf( threshDensityFile, "thresh  D\n" );
    long long done = 0;
    float percDone = 0.01;
    clock_t lastBegin = clock();
    for(thIt = thresholdSet.rbegin(); thIt!=thresholdSet.rend(); thIt++){
        threshold = *thIt;
        if (threshold < 0.0 || threshold > 1.11){
            cout << "ERROR: specified threshold not in [0,1]: " << threshold << endl;
            exit(1);
        }
        cout << " Starting new clustering...... " ;
        do{
            if( jacc < threshold )
                break;
            iter_i = edge2iter[ edgeId1 ];
            iter_j = edge2iter[ edgeId2 ];
            if ( iter_i != iter_j ) {
                cout << edgeId1 << " " << edgeId2 << " " << jacc << endl;
                // always merge smaller cluster into bigger:
                if ( (*iter_j).second.size() > (*iter_i).second.size() ){ // !!!!!!
                    swap(iter_i, iter_j);
                }
                // merge cluster j into i and update index for all elements in j:
                cout << "merging cluster " << endl;
                for (iterS = iter_j->second.begin(); iterS != iter_j->second.end(); iterS++){
                    iter_i->second.insert( *iterS );
                    edge2iter[ *iterS ] = iter_i;
                }

                // delete cluster j:
                cout << "Deleting cluster " << endl;
                index2cluster.erase(iter_j);
            }
        }while ( jaccFile >> edgeId1 >> edgeId2 >> jacc );
        cout << " Done!" << endl;
        // all done clustering, write to file (and calculated partition density):
        M = 0, Mns = 0;
        wSum = 0.0;
        set< int >::iterator S;
        set<int> clusterNodes;
        unordered_map< int, set< int > >::iterator it;
        for ( it = index2cluster.begin(); it != index2cluster.end(); it++ ) {
            clusterNodes.clear();
            for (S = it->second.begin(); S != it->second.end(); S++ ){
                //fprintf( clustersFile, "%i ", *S ); // this leaves a trailing space...!
                clusterNodes.insert(idEdgePairMap[*S].first);
                clusterNodes.insert(idEdgePairMap[*S].second);
            }
            mc = it->second.size();
            nc = clusterNodes.size();
            M += mc;
            if (nc > 2) {
                Mns  += mc;
                wSum += mc * (mc - (nc-1.0)) / ((nc-2.0)*(nc-1.0));
            }
        }
        threshDensityFile = fopen( argv[5], "a" );
        D = 2.0 * wSum / M;
        if (isinf(D)){
            fprintf( threshDensityFile, "\nERROR: D == -inf \n\n");
            fclose(threshDensityFile);
            exit(1);
        }
        //*************
        fprintf( threshDensityFile, "%.6f %.6f \n", threshold, D);
        fclose(threshDensityFile);
        if(D > highestD){
            highestD = D;
            highestDThr = threshold;
        }
        done++;
        if((float)done/(float)thresholdSet.size() >= percDone){
            cout << percDone*100 << " pc done.\n" << endl;
            percDone += 0.01;
        }
        cout << "Time taken = " << double(clock() - lastBegin)/ CLOCKS_PER_SEC << " seconds. "<< endl;
        lastBegin = clock();
    }
    jaccFile.close(); jaccFile.clear();
    fprintf( threshDensityFile, "\n highest D=%.6f at thresh:%.6f.\n", highestD, highestDThr);
    fclose(threshDensityFile);
    cout << "Time taken = " << double(clock() - begin)/ CLOCKS_PER_SEC << " seconds. "<< endl;
    return 0;
}
<commit_msg>Update calcDensityForDiffThresh.cpp<commit_after>/*
1. Treat each edge id as a cluster, unordered map from edgeId to a set
2. also store size of each cluster which will 0 in the begining
//  $ g++ -std=c++0x -O3 -o calcDensityForDiffThresh calcDensityForDiffThresh.cpp
//  $ ./calcDensityForDiffThresh networkEdgeIdMap.csv network.jaccs sortedjaccs.csv  Nthresholds threshDensity.csv
*/
#include <math.h>
#include <ctime>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <map>
#include <utility>   // for pairs
#include <algorithm> // for swap
using namespace std;

int main (int argc, char const *argv[]){
    //************* make sure args are present:
    if (argc != 6){
        cout << "ERROR: something wrong with the inputs" << endl;
        cout << "usage:\n    " << argv[0] << " networkEdgeIdMap.csv network.jaccs sortedjaccs.csv  "
                    << " Nthresholds threshDensity.csv" << endl;
        exit(1);
    }
    // Nthresholds is the total thresholds user wants us to try
    int nThresh = atoi(argv[4]);
    cout << "nThresh = " << nThresh << endl;
    int gapBetweenthresh = 0;
    float threshold = 0;
    float D = 0.0;
    int mc, nc;
    int M = 0, Mns = 0;
    double wSum = 0.0;
    float highestD=0.0;
    float highestDThr = 0.0;
    //************* got the args
    clock_t begin = clock();

    //************* start load edgelist
    ifstream inFile;
    inFile.open( argv[1] );
    if (!inFile) {
        cout << "ERROR: unable to open input file" << endl;
        exit(1); // terminate with error
    }
    // store edge ids in a map
    // each edge id will be a cluster of it's own in the begining
    // each cluster will be og size 1
    map< int,  pair<int,int> > idEdgePairMap;
    map< int,  set<int > > index2cluster; // O(log n) access too slow?
    map< int,  map< int, set<int > >::iterator > edge2iter;
    int ni, nj, edgeId, index = 0;
    while (inFile >> ni >> nj >> edgeId){
        idEdgePairMap[ edgeId ] = make_pair(ni,nj);
        index2cluster[ index ].insert(edgeId);         // build cluster index to set of edge-pairs map
        edge2iter[edgeId] = index2cluster.find(index);
        index++;
    }
    inFile.close(); inFile.clear();
    cout << "There were " << index2cluster.size() << " edges. ";
    cout << "Time taken = " << double(clock() - begin)/ CLOCKS_PER_SEC << " seconds. "<< endl;
    /// end reading edge ids -----

    //----- ----- ----- -----
    ifstream sortedjaccFile;
    sortedjaccFile.open( argv[3] );
    if (!sortedjaccFile) {
        cout << "ERROR: unable to open sortedjaccFile file" << endl;
        exit(1); // terminate with error
    }
    int totalThresh = 0;
    int edgeId1,edgeId2;
    double jacc;
    // Count totalines in the file, we are setting
    while ( sortedjaccFile  >> jacc ) {
        if(jacc>0 && jacc<=1.0)
            totalThresh++;
    }
    sortedjaccFile.close(); sortedjaccFile.clear();
    cout << "Done counting totalines in the file, \nTotal unique Jaccs = " << totalThresh;
    cout << ".  Time taken = " << double(clock() - begin)/ CLOCKS_PER_SEC << " seconds. "<< endl;
    if(totalThresh==0){
        cout << "ERROR: there are 0 Jaccs!!!" << endl;
        exit(1); // terminate with error
    }
    // now we want gap between two consecutive thresholds
    // we want to consider
    gapBetweenthresh =  totalThresh/nThresh;
    if(totalThresh < nThresh)
            gapBetweenthresh = totalThresh;
    set<float> thresholdSet;
    set<float> ::reverse_iterator thIt;
    cout << "thresholds" << endl;
    // ----------------------------
    totalThresh = -1;
    sortedjaccFile.open( argv[3] );
    while ( sortedjaccFile  >> jacc ){
        totalThresh++;
        if(totalThresh%gapBetweenthresh!=0){
            continue;
        }
        cout << jacc << endl;
        thresholdSet.insert(jacc);
    }
    sortedjaccFile.close(); sortedjaccFile.clear();
    thresholdSet.insert(1.1);
    cout << "Done with thresholdSet creation.";
    cout << "  Time taken = " << double(clock() - begin)/ CLOCKS_PER_SEC << " seconds. "<< endl;
    // ---------------------------

    ifstream jaccFile;
    jaccFile.open(argv[2]);
    // read first line
    jaccFile >> edgeId1 >> edgeId2 >> jacc ;
    // open the outputfile
    map< int, set< int> >::iterator iter_i,iter_j;
    set<int>::iterator iterS;
    FILE * threshDensityFile = fopen( argv[5], "w" );
    fclose(threshDensityFile);
    fprintf( threshDensityFile, "thresh  D\n" );
    long long done = 0;
    float percDone = 0.01;
    clock_t lastBegin = clock();
    for(thIt = thresholdSet.rbegin(); thIt!=thresholdSet.rend(); thIt++){
        threshold = *thIt;
        if (threshold < 0.0 || threshold > 1.11){
            cout << "ERROR: specified threshold not in [0,1]: " << threshold << endl;
            exit(1);
        }
        cout << " Starting new clustering...... " ;
        do{
            if( jacc < threshold )
                break;
            iter_i = edge2iter[ edgeId1 ];
            iter_j = edge2iter[ edgeId2 ];
            if ( iter_i != iter_j ) {
                //cout << edgeId1 << " " << edgeId2 << " " << jacc << endl;
                // always merge smaller cluster into bigger:
                if ( (*iter_j).second.size() > (*iter_i).second.size() ){ // !!!!!!
                    swap(iter_i, iter_j);
                }
                // merge cluster j into i and update index for all elements in j:
                //cout << "merging cluster " << endl;
                for (iterS = iter_j->second.begin(); iterS != iter_j->second.end(); iterS++){
                    iter_i->second.insert( *iterS );
                    edge2iter[ *iterS ] = iter_i;
                }

                // delete cluster j:
                cout << "Deleting cluster " << endl;
                index2cluster.erase(iter_j);
                cout << "Done deleteing " << endl;
            }
        }while ( jaccFile >> edgeId1 >> edgeId2 >> jacc );
        cout << " Done!" << endl;
        // all done clustering, write to file (and calculated partition density):
        M = 0, Mns = 0;
        wSum = 0.0;
        set< int >::iterator S;
        set<int> clusterNodes;
        map< int, set< int > >::iterator it;
        for ( it = index2cluster.begin(); it != index2cluster.end(); it++ ) {
            clusterNodes.clear();
            for (S = it->second.begin(); S != it->second.end(); S++ ){
                //fprintf( clustersFile, "%i ", *S ); // this leaves a trailing space...!
                clusterNodes.insert(idEdgePairMap[*S].first);
                clusterNodes.insert(idEdgePairMap[*S].second);
            }
            mc = it->second.size();
            nc = clusterNodes.size();
            M += mc;
            if (nc > 2) {
                Mns  += mc;
                wSum += mc * (mc - (nc-1.0)) / ((nc-2.0)*(nc-1.0));
            }
        }
        threshDensityFile = fopen( argv[5], "a" );
        D = 2.0 * wSum / M;
        if (isinf(D)){
            fprintf( threshDensityFile, "\nERROR: D == -inf \n\n");
            fclose(threshDensityFile);
            exit(1);
        }
        //*************
        fprintf( threshDensityFile, "%.6f %.6f \n", threshold, D);
        fclose(threshDensityFile);
        if(D > highestD){
            highestD = D;
            highestDThr = threshold;
        }
        done++;
        if((float)done/(float)thresholdSet.size() >= percDone){
            cout << percDone*100 << " pc done.\n" << endl;
            percDone += 0.01;
        }
        cout << "Time taken = " << double(clock() - lastBegin)/ CLOCKS_PER_SEC << " seconds. "<< endl;
        lastBegin = clock();
    }
    jaccFile.close(); jaccFile.clear();
    fprintf( threshDensityFile, "\n highest D=%.6f at thresh:%.6f.\n", highestD, highestDThr);
    fclose(threshDensityFile);
    cout << "Time taken = " << double(clock() - begin)/ CLOCKS_PER_SEC << " seconds. "<< endl;
    return 0;
}
<|endoftext|>


<commit_before>/* bzflag
* Copyright (c) 1993 - 2004 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <assert.h>
#include <string>
#include <string.h>

#include "common.h"
#include "bzfgl.h"
#include "TextureManager.h"
#include "TextureFont.h"
#include "bzfio.h"

#include "OpenGLGState.h"

TextureFont::TextureFont()
{
  for (int i = 0; i < 128; i++) {
    listIDs[i] = _GL_INVALID_ID;
    fontMetrics[i].charWidth = -1;
  }

  size = -1;
  textureID = -1;

  textureXSize = -1;
  textureYSize = -1;
  textureZStep = -1;
  numberOfCharacters = -1;
}

TextureFont::~TextureFont()
{
  for (int i = 0; i < 128; i++) {
    if (listIDs[i] != _GL_INVALID_ID)
      glDeleteLists(listIDs[i], 1);
  }
}

int TextureFont::getSize()
{
  return size;
}

const char* TextureFont::getFaceName()
{
  return faceName.c_str();
}

/* read values in Key: Value form from font metrics (.fmt) files */
bool TextureFont::fmtRead(OSFile &file, std::string expectedLeft, std::string &retval)
{
  static std::string workingFile;
  static int line = 0;

  // reset line number if we've switched files
  if (workingFile != file.getFileName()) {
    workingFile = file.getFileName();
    line = 0;
  }

  std::string tmpBuf;

  // allow for blank lines with native or foreign linebreaks, comment lines
  while (tmpBuf.size() == 0 || tmpBuf[0] == '#' || tmpBuf[0] == 10 || tmpBuf[0] == 13) {
    tmpBuf = file.readLine();
    // keep a line counter
    line++;
  }

  if (tmpBuf.substr(0, tmpBuf.find(":")) == expectedLeft) {
    retval = tmpBuf.substr(tmpBuf.find(":") + 1, tmpBuf.size());
    return true;
  } else {
    DEBUG2("Unexpected line in font metrics file %s, line %d (expected %s)\n",
      file.getFileName(), line, expectedLeft.c_str());
    return false;
  }
}

bool TextureFont::load(OSFile &file)
{
  const char *extension = file.getExtension();

  if (!extension)
    return false;

  if (!file.open("rb"))
    return false;

  std::string tmpBuf;

  if (!fmtRead(file, "NumChars", tmpBuf)) return false;
  sscanf(tmpBuf.c_str(), " %d", &numberOfCharacters);
  if (!fmtRead(file, "TextureWidth", tmpBuf)) return false;
  sscanf(tmpBuf.c_str(), " %d", &textureXSize);
  if (!fmtRead(file, "TextureHeight", tmpBuf)) return false;
  sscanf(tmpBuf.c_str(), " %d", &textureYSize);
  if (!fmtRead(file, "TextZStep", tmpBuf)) return false;
  sscanf(tmpBuf.c_str(), " %d", &textureZStep);

  int i;
  for (i = 0; i < numberOfCharacters; i++) {
    // check character
    if (!fmtRead(file, "Char", tmpBuf)) return false;
    if ((tmpBuf.size() < 3) ||
	(tmpBuf[1] != '\"' || tmpBuf[2] != (i + 32) || tmpBuf[3] != '\"')) {
      DEBUG2("Unexpected character: %s, in font metrics file %s (expected \"%c\").\n",
	tmpBuf.c_str(), file.getFileName(), (char)(i + 32));
      return false;
    }
    // read metrics
    if (!fmtRead(file, "InitialDist", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].initialDist);
    if (!fmtRead(file, "Width", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].charWidth);
    if (!fmtRead(file, "Whitespace", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].whiteSpaceDist);
    if (!fmtRead(file, "StartX", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].startX);
    if (!fmtRead(file, "EndX", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].endX);
    if (!fmtRead(file, "StartY", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].startY);
    if (!fmtRead(file, "EndY", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].endY);
  }

  file.close();

  // now compute the names
  std::string fullName = file.getStdName();
  char *temp;

  // get just the file part
  temp = strrchr(fullName.c_str(), '/');
  if (temp)
    faceName = temp + 1;
  else
    faceName = fullName;

  // now get the texture name
  texture = faceName;

  // now wack off the extension;
  if (extension)
    faceName.erase(faceName.size() - (strlen(extension) + 1), faceName.size());

  temp = strrchr(faceName.c_str(), '_');

  if (temp) {
    size = atoi(temp+1);
    faceName.resize(temp - faceName.c_str());
  }

  // faceName.erase(faceName.size()-strlen(temp),faceName.size());

  if (extension)
    texture.erase(texture.size() - (strlen(extension) + 1), texture.size());

  return (numberOfCharacters > 0);
}

void TextureFont::build(void)
{
  preLoadLists();
}

void TextureFont::preLoadLists(void)
{
  if (texture.size() < 1) {
    DEBUG2("Font %s does not have an associated texture name, not loading\n", texture.c_str());
    return;
  }

  // load up the texture
  TextureManager &tm = TextureManager::instance();
  std::string textureAndDir = "fonts/" + texture;
  textureID = tm.getTextureID(textureAndDir.c_str());

  DEBUG4("Font %s (face %s) has texture ID %d\n", texture.c_str(), faceName.c_str(), textureID);

  if (textureID == -1) {
    DEBUG2("Font texture %s has invalid ID\n", texture.c_str());
    return;
  }

  glPushMatrix();
  for (int i = 0; i < numberOfCharacters; i++) {
    if (listIDs[i] != _GL_INVALID_ID)
      glDeleteLists(listIDs[i], 1);
    listIDs[i] = glGenLists(1);
    glLoadIdentity();

    glNewList(listIDs[i], GL_COMPILE);

    glTranslatef((float)fontMetrics[i].initialDist, 0, 0);

    float fFontY = (float)fontMetrics[i].endY - fontMetrics[i].startY;
    float fFontX = (float)fontMetrics[i].endX - fontMetrics[i].startX;

    glBegin(GL_QUADS);
      glNormal3f(0, 0, 1);
      glTexCoord2f((float)fontMetrics[i].startX / (float)textureXSize, 1.0f - (float)fontMetrics[i].startY / (float)textureYSize);
      glVertex3f(0, fFontY, 0);

      glTexCoord2f((float)fontMetrics[i].startX / (float)textureXSize, 1.0f - (float)fontMetrics[i].endY / (float)textureYSize);
      glVertex3f(0, 0, 0);

      glTexCoord2f((float)fontMetrics[i].endX / (float)textureXSize, 1.0f - (float)fontMetrics[i].endY / (float)textureYSize);
      glVertex3f(fFontX, 0, 0);

      glTexCoord2f((float)fontMetrics[i].endX / (float)textureXSize, 1.0f - (float)fontMetrics[i].startY / (float)textureYSize);
      glVertex3f(fFontX, fFontY, 0);
    glEnd();

    glTranslatef(fFontX, 0, 0);

    glEndList();
  }
  glPopMatrix();

  // create GState
  OpenGLGStateBuilder builder(gstate);
  builder.setTexture(textureID);
  builder.setBlending();
  builder.setAlphaFunc();
  builder.enableTextureReplace(false);
  gstate = builder.getState();
}

float TextureFont::getStrLength(float scale, const char *str)
{
  int len = (int)strlen(str);
  int charToUse = 0;
  int lastCharacter = 0;

  float totalLen = 0;
  float thisPassLen = 0;

  for (int i = 0; i < len; i++) {
    if (str[i] == '\n') {	// newline, get back to the intial X and push down
      thisPassLen = 0;
    } else {
      lastCharacter = charToUse;
      if ((str[i] < 32) || (str[i] < 9))
	charToUse = 32;
      else if (str[i] > numberOfCharacters + 32)
	charToUse = 32;
      else
	charToUse = str[i];

      charToUse -= 32;

      if (charToUse == 0) {
	if (i == 0)
	  thisPassLen += fontMetrics[charToUse].initialDist + fontMetrics[charToUse].charWidth+fontMetrics[charToUse].whiteSpaceDist;
	else
	  thisPassLen += fontMetrics[lastCharacter].whiteSpaceDist + fontMetrics[charToUse].whiteSpaceDist+fontMetrics[charToUse].initialDist + fontMetrics[charToUse].charWidth;
      } else {
	float fFontX = (float)fontMetrics[charToUse].endX - fontMetrics[charToUse].startX;
	thisPassLen += fFontX + (float)fontMetrics[charToUse].initialDist;
      }
    }
    if (thisPassLen > totalLen)
      totalLen = thisPassLen;
  }

  return totalLen * scale;
}

void TextureFont::free(void)
{
  textureID = -1;
}

void TextureFont::drawString(float scale, GLfloat color[3], const char *str)
{
  if (!str)
    return;

  if (textureID == -1)
    preLoadLists();

  if (textureID == -1)
    return;

  gstate.setState();

  TextureManager &tm = TextureManager::instance();
  if (!tm.bind(textureID))
    return;

  if (color[0] >= 0)
    glColor3fv(color);

  glPushMatrix();
  glScalef(scale, scale, 1);

  glPushMatrix();
  int len = (int)strlen(str);
  int charToUse = 0;
  int lastCharacter = 0;
  for (int i = 0; i < len; i++) {
    if (str[i] == '\n') {	// newline, get back to the intial X and push down
      glPopMatrix();
      glTranslatef(0, -(float)textureZStep, 0);
      glPushMatrix();
    } else {
      lastCharacter = charToUse;
      if ((str[i] < 32) || (str[i] < 9))
	charToUse = 32;
      else if (str[i] > numberOfCharacters + 32)
	charToUse = 32;
      else
	charToUse = str[i];

      charToUse -= 32;

      if (charToUse == 0) {
	if (i == 0)
	  glTranslatef((float)fontMetrics[charToUse].initialDist + (float)fontMetrics[charToUse].charWidth + (float)fontMetrics[charToUse].whiteSpaceDist, 0, 0);
	else
	  glTranslatef((float)fontMetrics[lastCharacter].whiteSpaceDist + (float)fontMetrics[charToUse].whiteSpaceDist + fontMetrics[charToUse].initialDist + (float)fontMetrics[charToUse].charWidth, 0, 0);
      } else {
	glCallList(listIDs[charToUse]);
      }
    }
  }
  glPopMatrix();
  if (color[0] >= 0)
    glColor4f(1, 1, 1, 1);
  glPopMatrix();
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>clean up a bit<commit_after>/* bzflag
* Copyright (c) 1993 - 2004 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <assert.h>
#include <string>
#include <string.h>

#include "common.h"
#include "bzfgl.h"
#include "TextureManager.h"
#include "TextureFont.h"
#include "bzfio.h"

#include "OpenGLGState.h"

TextureFont::TextureFont()
{
  for (int i = 0; i < 128; i++) {
    listIDs[i] = _GL_INVALID_ID;
    fontMetrics[i].charWidth = -1;
  }

  size = -1;
  textureID = -1;

  textureXSize = -1;
  textureYSize = -1;
  textureZStep = -1;
  numberOfCharacters = -1;
}

TextureFont::~TextureFont()
{
  for (int i = 0; i < 128; i++) {
    if (listIDs[i] != _GL_INVALID_ID)
      glDeleteLists(listIDs[i], 1);
  }
}

int TextureFont::getSize()
{
  return size;
}

const char* TextureFont::getFaceName()
{
  return faceName.c_str();
}

/* read values in Key: Value form from font metrics (.fmt) files */
bool TextureFont::fmtRead(OSFile &file, std::string expectedLeft, std::string &retval)
{
  static std::string workingFile;
  static int line = 0;

  // reset line number if we've switched files
  if (workingFile != file.getFileName()) {
    workingFile = file.getFileName();
    line = 0;
  }

  std::string tmpBuf;

  // allow for blank lines with native or foreign linebreaks, comment lines
  while (tmpBuf.size() == 0 || tmpBuf[0] == '#' || tmpBuf[0] == 10 || tmpBuf[0] == 13) {
    tmpBuf = file.readLine();
    // keep a line counter
    line++;
  }

  if (tmpBuf.substr(0, tmpBuf.find(":")) == expectedLeft) {
    retval = tmpBuf.substr(tmpBuf.find(":") + 1, tmpBuf.size());
    return true;
  } else {
    DEBUG2("Unexpected line in font metrics file %s, line %d (expected %s)\n",
      file.getFileName(), line, expectedLeft.c_str());
    return false;
  }
}

bool TextureFont::load(OSFile &file)
{
  const char *extension = file.getExtension();

  if (!extension)
    return false;

  if (!file.open("rb"))
    return false;

  std::string tmpBuf;

  if (!fmtRead(file, "NumChars", tmpBuf)) return false;
  sscanf(tmpBuf.c_str(), " %d", &numberOfCharacters);
  if (!fmtRead(file, "TextureWidth", tmpBuf)) return false;
  sscanf(tmpBuf.c_str(), " %d", &textureXSize);
  if (!fmtRead(file, "TextureHeight", tmpBuf)) return false;
  sscanf(tmpBuf.c_str(), " %d", &textureYSize);
  if (!fmtRead(file, "TextZStep", tmpBuf)) return false;
  sscanf(tmpBuf.c_str(), " %d", &textureZStep);

  int i;
  for (i = 0; i < numberOfCharacters; i++) {
    // check character
    if (!fmtRead(file, "Char", tmpBuf)) return false;
    if ((tmpBuf.size() < 3) ||
	(tmpBuf[1] != '\"' || tmpBuf[2] != (i + 32) || tmpBuf[3] != '\"')) {
      DEBUG2("Unexpected character: %s, in font metrics file %s (expected \"%c\").\n",
	tmpBuf.c_str(), file.getFileName(), (char)(i + 32));
      return false;
    }
    // read metrics
    if (!fmtRead(file, "InitialDist", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].initialDist);
    if (!fmtRead(file, "Width", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].charWidth);
    if (!fmtRead(file, "Whitespace", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].whiteSpaceDist);
    if (!fmtRead(file, "StartX", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].startX);
    if (!fmtRead(file, "EndX", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].endX);
    if (!fmtRead(file, "StartY", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].startY);
    if (!fmtRead(file, "EndY", tmpBuf)) return false;
    sscanf(tmpBuf.c_str(), " %d", &fontMetrics[i].endY);
  }

  file.close();

  // now compute the names
  std::string fullName = file.getStdName();
  char *temp;

  // get just the file part
  temp = strrchr(fullName.c_str(), '/');
  if (temp)
    faceName = temp + 1;
  else
    faceName = fullName;

  // now get the texture name
  texture = faceName;

  // now wack off the extension;
  if (extension)
    faceName.erase(faceName.size() - (strlen(extension) + 1), faceName.size());

  temp = strrchr(faceName.c_str(), '_');

  if (temp) {
    size = atoi(temp+1);
    faceName.resize(temp - faceName.c_str());
  }

  // faceName.erase(faceName.size()-strlen(temp),faceName.size());

  if (extension)
    texture.erase(texture.size() - (strlen(extension) + 1), texture.size());

  return (numberOfCharacters > 0);
}

void TextureFont::build(void)
{
  preLoadLists();
}

void TextureFont::preLoadLists(void)
{
  if (texture.size() < 1) {
    DEBUG2("Font %s does not have an associated texture name, not loading\n", texture.c_str());
    return;
  }

  // load up the texture
  TextureManager &tm = TextureManager::instance();
  std::string textureAndDir = "fonts/" + texture;
  textureID = tm.getTextureID(textureAndDir.c_str());

  DEBUG4("Font %s (face %s) has texture ID %d\n", texture.c_str(), faceName.c_str(), textureID);

  if (textureID == -1) {
    DEBUG2("Font texture %s has invalid ID\n", texture.c_str());
    return;
  }

  glPushMatrix();
  for (int i = 0; i < numberOfCharacters; i++) {
    if (listIDs[i] != _GL_INVALID_ID)
      glDeleteLists(listIDs[i], 1);
    listIDs[i] = glGenLists(1);
    glLoadIdentity();

    glNewList(listIDs[i], GL_COMPILE);

    glTranslatef((float)fontMetrics[i].initialDist, 0, 0);

    float fFontY = (float)fontMetrics[i].endY - fontMetrics[i].startY;
    float fFontX = (float)fontMetrics[i].endX - fontMetrics[i].startX;

    glBegin(GL_QUADS);
      glNormal3f(0, 0, 1);
      glTexCoord2f((float)fontMetrics[i].startX / (float)textureXSize, 1.0f - (float)fontMetrics[i].startY / (float)textureYSize);
      glVertex3f(0, fFontY, 0);

      glTexCoord2f((float)fontMetrics[i].startX / (float)textureXSize, 1.0f - (float)fontMetrics[i].endY / (float)textureYSize);
      glVertex3f(0, 0, 0);

      glTexCoord2f((float)fontMetrics[i].endX / (float)textureXSize, 1.0f - (float)fontMetrics[i].endY / (float)textureYSize);
      glVertex3f(fFontX, 0, 0);

      glTexCoord2f((float)fontMetrics[i].endX / (float)textureXSize, 1.0f - (float)fontMetrics[i].startY / (float)textureYSize);
      glVertex3f(fFontX, fFontY, 0);
    glEnd();

    glTranslatef(fFontX, 0, 0);

    glEndList();
  }
  glPopMatrix();

  // create GState
  OpenGLGStateBuilder builder(gstate);
  builder.setTexture(textureID);
  builder.setBlending();
  builder.setAlphaFunc();
  builder.enableTextureReplace(false);
  gstate = builder.getState();
}

float TextureFont::getStrLength(float scale, const char *str)
{
  int len = (int)strlen(str);
  int charToUse = 0;
  int lastCharacter = 0;

  float totalLen = 0;
  float thisPassLen = 0;

  for (int i = 0; i < len; i++) {
    if (str[i] == '\n') {	// newline, get back to the intial X and push down
      thisPassLen = 0;
    } else {
      lastCharacter = charToUse;
      if ((str[i] < 32) || (str[i] < 9))
	charToUse = 32;
      else if (str[i] > numberOfCharacters + 32)
	charToUse = 32;
      else
	charToUse = str[i];

      charToUse -= 32;

      if (charToUse == 0) {
	if (i == 0)
	  thisPassLen += fontMetrics[charToUse].initialDist + fontMetrics[charToUse].charWidth + fontMetrics[charToUse].whiteSpaceDist;
	else
	  thisPassLen += fontMetrics[lastCharacter].whiteSpaceDist + fontMetrics[charToUse].whiteSpaceDist + fontMetrics[charToUse].initialDist + fontMetrics[charToUse].charWidth;
      } else {
	thisPassLen += fontMetrics[charToUse].endX - fontMetrics[charToUse].startX + fontMetrics[charToUse].initialDist;
      }
    }
    if (thisPassLen > totalLen)
      totalLen = thisPassLen;
  }

  return totalLen * scale;
}

void TextureFont::free(void)
{
  textureID = -1;
}

void TextureFont::drawString(float scale, GLfloat color[3], const char *str)
{
  if (!str)
    return;

  if (textureID == -1)
    preLoadLists();

  if (textureID == -1)
    return;

  gstate.setState();

  TextureManager &tm = TextureManager::instance();
  if (!tm.bind(textureID))
    return;

  if (color[0] >= 0)
    glColor3fv(color);

  glPushMatrix();
  glScalef(scale, scale, 1);

  glPushMatrix();
  int len = (int)strlen(str);
  int charToUse = 0;
  int lastCharacter = 0;
  for (int i = 0; i < len; i++) {
    if (str[i] == '\n') {	// newline, get back to the intial X and push down
      glPopMatrix();
      glTranslatef(0, -(float)textureZStep, 0);
      glPushMatrix();
    } else {
      lastCharacter = charToUse;
      if ((str[i] < 32) || (str[i] < 9))
	charToUse = 32;
      else if (str[i] > numberOfCharacters + 32)
	charToUse = 32;
      else
	charToUse = str[i];

      charToUse -= 32;

      if (charToUse == 0) {
	if (i == 0)
	  glTranslatef((float)fontMetrics[charToUse].initialDist + (float)fontMetrics[charToUse].charWidth + (float)fontMetrics[charToUse].whiteSpaceDist, 0, 0);
	else
	  glTranslatef((float)fontMetrics[lastCharacter].whiteSpaceDist + (float)fontMetrics[charToUse].whiteSpaceDist + fontMetrics[charToUse].initialDist + (float)fontMetrics[charToUse].charWidth, 0, 0);
      } else {
	glCallList(listIDs[charToUse]);
      }
    }
  }
  glPopMatrix();
  if (color[0] >= 0)
    glColor4f(1, 1, 1, 1);
  glPopMatrix();
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>#define MS_CLASS "RTC::RTCP::CompoundPacket"
// #define MS_LOG_DEV

#include "RTC/RTCP/CompoundPacket.h"
#include "Logger.h"

namespace RTC { namespace RTCP
{
	/* Instance methods. */

	void CompoundPacket::Serialize(uint8_t* data)
	{
		MS_TRACE();

		this->header = data;

		// Calculate the total required size for the entire message.
		if (this->senderReportPacket.GetCount())
		{
			this->size = this->senderReportPacket.GetSize();

			if (this->receiverReportPacket.GetCount())
				this->size += sizeof(ReceiverReport::Header) * this->receiverReportPacket.GetCount();
		}
		// If no sender nor receiver reports are present send an empty Receiver Report
		// packet as the head of the compound packet.
		else
		{
			this->size = this->receiverReportPacket.GetSize();
		}

		if (this->sdesPacket.GetCount())
			this->size += this->sdesPacket.GetSize();

		// Fill it.
		size_t offset = 0;

		if (this->senderReportPacket.GetCount())
		{
			this->senderReportPacket.Serialize(this->header);
			offset = this->senderReportPacket.GetSize();

			if (this->receiverReportPacket.GetCount())
			{
				// Fix header length.
				Packet::CommonHeader* header = (Packet::CommonHeader*)this->header;
				header->length += (sizeof(ReceiverReport::Header) * this->receiverReportPacket.GetCount()) / 4;

				ReceiverReportPacket::Iterator it = this->receiverReportPacket.Begin();
				for (; it != this->receiverReportPacket.End(); ++it)
				{
					ReceiverReport* report = (*it);

					report->Serialize(this->header + offset);
					offset += sizeof(ReceiverReport::Header);
				}
			}
		}
		else
		{
			this->receiverReportPacket.Serialize(this->header);
			offset = this->receiverReportPacket.GetSize();
		}

		if (this->sdesPacket.GetCount())
		{
			this->sdesPacket.Serialize(this->header + offset);
			offset += this->sdesPacket.GetSize();
		}
	}

	void CompoundPacket::Dump()
	{
		#ifdef MS_LOG_DEV

		MS_TRACE();

		if (this->senderReportPacket.GetCount())
		{
			this->senderReportPacket.Dump();

			if (this->receiverReportPacket.GetCount())
			{
				ReceiverReportPacket::Iterator it = this->receiverReportPacket.Begin();

				for (; it != this->receiverReportPacket.End(); ++it)
				{
					(*it)->Dump();
				}
			}
		}
		else
		{
			this->receiverReportPacket.Dump();
		}

		if (this->sdesPacket.GetCount())
			this->sdesPacket.Dump();

		#endif
	}

	void CompoundPacket::AddSenderReport(SenderReport* report)
	{
		MS_ASSERT(this->senderReportPacket.GetCount() == 0, "a sender report is already present");

		this->senderReportPacket.AddReport(report);
	}
}}
<commit_msg>Rtcp: fix compound packet length and count fields<commit_after>#define MS_CLASS "RTC::RTCP::CompoundPacket"
// #define MS_LOG_DEV

#include "RTC/RTCP/CompoundPacket.h"
#include "Logger.h"

namespace RTC { namespace RTCP
{
	/* Instance methods. */

	void CompoundPacket::Serialize(uint8_t* data)
	{
		MS_TRACE();

		this->header = data;

		// Calculate the total required size for the entire message.
		if (this->senderReportPacket.GetCount())
		{
			this->size = this->senderReportPacket.GetSize();

			if (this->receiverReportPacket.GetCount())
				this->size += sizeof(ReceiverReport::Header) * this->receiverReportPacket.GetCount();
		}
		// If no sender nor receiver reports are present send an empty Receiver Report
		// packet as the head of the compound packet.
		else
		{
			this->size = this->receiverReportPacket.GetSize();
		}

		if (this->sdesPacket.GetCount())
			this->size += this->sdesPacket.GetSize();

		// Fill it.
		size_t offset = 0;

		if (this->senderReportPacket.GetCount())
		{
			this->senderReportPacket.Serialize(this->header);
			offset = this->senderReportPacket.GetSize();

			if (this->receiverReportPacket.GetCount())
			{
				// Fix header length field.
				Packet::CommonHeader* header = (Packet::CommonHeader*)this->header;
				size_t length = ((sizeof(SenderReport::Header) + (sizeof(ReceiverReport::Header) * this->receiverReportPacket.GetCount())) / 4);
				header->length = htons(length);

				// Fix header count field.
				header->count = this->receiverReportPacket.GetCount();

				ReceiverReportPacket::Iterator it = this->receiverReportPacket.Begin();
				for (; it != this->receiverReportPacket.End(); ++it)
				{
					ReceiverReport* report = (*it);

					report->Serialize(this->header + offset);
					offset += sizeof(ReceiverReport::Header);
				}
			}
		}
		else
		{
			this->receiverReportPacket.Serialize(this->header);
			offset = this->receiverReportPacket.GetSize();
		}

		if (this->sdesPacket.GetCount())
		{
			this->sdesPacket.Serialize(this->header + offset);
			offset += this->sdesPacket.GetSize();
		}
	}

	void CompoundPacket::Dump()
	{
		#ifdef MS_LOG_DEV

		MS_TRACE();

		if (this->senderReportPacket.GetCount())
		{
			this->senderReportPacket.Dump();

			if (this->receiverReportPacket.GetCount())
			{
				ReceiverReportPacket::Iterator it = this->receiverReportPacket.Begin();

				for (; it != this->receiverReportPacket.End(); ++it)
				{
					(*it)->Dump();
				}
			}
		}
		else
		{
			this->receiverReportPacket.Dump();
		}

		if (this->sdesPacket.GetCount())
			this->sdesPacket.Dump();

		#endif
	}

	void CompoundPacket::AddSenderReport(SenderReport* report)
	{
		MS_ASSERT(this->senderReportPacket.GetCount() == 0, "a sender report is already present");

		this->senderReportPacket.AddReport(report);
	}
}}
<|endoftext|>


<commit_before>/*
   TCPAcceptor.cpp

   TCPAcceptor class definition. TCPAcceptor provides methods to passively
   establish TCP/IP connections with clients.

   ------------------------------------------

   Copyright  2013 [Vic Hargrave - http://vichargrave.com]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "tcpsockets/TCPAcceptor.h"

#include <cstdio>
#include <cstring>
#ifdef _WIN32
#include <WinSock2.h>
#include <Ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#endif

#include "llvm/SmallString.h"
#include "support/Logger.h"
#include "tcpsockets/SocketError.h"

using namespace wpi;

TCPAcceptor::TCPAcceptor(int port, const char* address, Logger& logger)
    : m_lsd(0),
      m_port(port),
      m_address(address),
      m_listening(false),
      m_logger(logger) {
  m_shutdown = false;
#ifdef _WIN32
  WSAData wsaData;
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSAStartup(wVersionRequested, &wsaData);
#endif
}

TCPAcceptor::~TCPAcceptor() {
  if (m_lsd > 0) {
    shutdown();
#ifdef _WIN32
    closesocket(m_lsd);
#else
    close(m_lsd);
#endif
  }
#ifdef _WIN32
  WSACleanup();
#endif
}

int TCPAcceptor::start() {
  if (m_listening) return 0;

  m_lsd = socket(PF_INET, SOCK_STREAM, 0);
  if (m_lsd < 0) {
    WPI_ERROR(m_logger, "could not create socket");
    return -1;
  }
  struct sockaddr_in address;

  std::memset(&address, 0, sizeof(address));
  address.sin_family = PF_INET;
  if (m_address.size() > 0) {
#ifdef _WIN32
    llvm::SmallString<128> addr_copy(m_address);
    addr_copy.push_back('\0');
    int res = InetPton(PF_INET, addr_copy.data(), &(address.sin_addr));
#else
    int res = inet_pton(PF_INET, m_address.c_str(), &(address.sin_addr));
#endif
    if (res != 1) {
      WPI_ERROR(m_logger, "could not resolve " << m_address << " address");
      return -1;
    }
  } else {
    address.sin_addr.s_addr = INADDR_ANY;
  }
  address.sin_port = htons(m_port);

  int optval = 1;
  setsockopt(m_lsd, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof optval);

  int result = bind(m_lsd, (struct sockaddr*)&address, sizeof(address));
  if (result != 0) {
    WPI_ERROR(m_logger, "bind() to port " << m_port
                                          << " failed: " << SocketStrerror());
    return result;
  }

  result = listen(m_lsd, 5);
  if (result != 0) {
    WPI_ERROR(m_logger, "listen() on port " << m_port
                                            << " failed: " << SocketStrerror());
    return result;
  }
  m_listening = true;
  return result;
}

void TCPAcceptor::shutdown() {
  m_shutdown = true;
#ifdef _WIN32
  ::shutdown(m_lsd, SD_BOTH);

  // this is ugly, but the easiest way to do this
  // force wakeup of accept() with a non-blocking connect to ourselves
  struct sockaddr_in address;

  std::memset(&address, 0, sizeof(address));
  address.sin_family = PF_INET;
  llvm::SmallString<128> addr_copy;
  if (m_address.size() > 0)
    addr_copy = m_address;
  else
    addr_copy = "127.0.0.1";
  addr_copy.push_back('\0');
  int size = sizeof(address);
  if (WSAStringToAddress(addr_copy.data(), PF_INET, nullptr,
                         (struct sockaddr*)&address, &size) != 0)
    return;
  address.sin_port = htons(m_port);

  fd_set sdset;
  struct timeval tv;
  int result = -1, valopt, sd = socket(AF_INET, SOCK_STREAM, 0);
  if (sd < 0) return;

  // Set socket to non-blocking
  u_long mode = 1;
  ioctlsocket(sd, FIONBIO, &mode);

  // Try to connect
  ::connect(sd, (struct sockaddr*)&address, sizeof(address));

  // Close
  ::closesocket(sd);

#else
  ::shutdown(m_lsd, SHUT_RDWR);
  int nullfd = ::open("/dev/null", O_RDONLY);
  if (nullfd >= 0) {
    ::dup2(nullfd, m_lsd);
    ::close(nullfd);
  }
#endif
}

std::unique_ptr<NetworkStream> TCPAcceptor::accept() {
  if (!m_listening || m_shutdown) return nullptr;

  struct sockaddr_in address;
#ifdef _WIN32
  int len = sizeof(address);
#else
  socklen_t len = sizeof(address);
#endif
  std::memset(&address, 0, sizeof(address));
  int sd = ::accept(m_lsd, (struct sockaddr*)&address, &len);
  if (sd < 0) {
    if (!m_shutdown)
      WPI_ERROR(m_logger, "accept() on port "
                              << m_port << " failed: " << SocketStrerror());
    return nullptr;
  }
  if (m_shutdown) {
#ifdef _WIN32
    closesocket(sd);
#else
    close(sd);
#endif
    return nullptr;
  }
  return std::unique_ptr<NetworkStream>(new TCPStream(sd, &address));
}
<commit_msg>Fixes TCPAcceptor able to use an empty string (#172)<commit_after>/*
   TCPAcceptor.cpp

   TCPAcceptor class definition. TCPAcceptor provides methods to passively
   establish TCP/IP connections with clients.

   ------------------------------------------

   Copyright  2013 [Vic Hargrave - http://vichargrave.com]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "tcpsockets/TCPAcceptor.h"

#include <cstdio>
#include <cstring>
#ifdef _WIN32
#include <WinSock2.h>
#include <Ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#endif

#include "llvm/SmallString.h"
#include "support/Logger.h"
#include "tcpsockets/SocketError.h"

using namespace wpi;

TCPAcceptor::TCPAcceptor(int port, const char* address, Logger& logger)
    : m_lsd(0),
      m_port(port),
      m_address(address),
      m_listening(false),
      m_logger(logger) {
  m_shutdown = false;
#ifdef _WIN32
  WSAData wsaData;
  WORD wVersionRequested = MAKEWORD(2, 2);
  WSAStartup(wVersionRequested, &wsaData);
#endif
}

TCPAcceptor::~TCPAcceptor() {
  if (m_lsd > 0) {
    shutdown();
#ifdef _WIN32
    closesocket(m_lsd);
#else
    close(m_lsd);
#endif
  }
#ifdef _WIN32
  WSACleanup();
#endif
}

int TCPAcceptor::start() {
  if (m_listening) return 0;

  m_lsd = socket(PF_INET, SOCK_STREAM, 0);
  if (m_lsd < 0) {
    WPI_ERROR(m_logger, "could not create socket");
    return -1;
  }
  struct sockaddr_in address;

  std::memset(&address, 0, sizeof(address));
  address.sin_family = PF_INET;
  if (m_address.size() > 0) {
#ifdef _WIN32
    llvm::SmallString<128> addr_copy(m_address);
    addr_copy.push_back('\0');
    int res = InetPton(PF_INET, addr_copy.data(), &(address.sin_addr));
#else
    int res = inet_pton(PF_INET, m_address.c_str(), &(address.sin_addr));
#endif
    if (res != 1 && !m_address.empty()) {
      WPI_ERROR(m_logger, "could not resolve " << m_address << " address");
      return -1;
    }
  } else {
    address.sin_addr.s_addr = INADDR_ANY;
  }
  address.sin_port = htons(m_port);

  int optval = 1;
  setsockopt(m_lsd, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof optval);

  int result = bind(m_lsd, (struct sockaddr*)&address, sizeof(address));
  if (result != 0) {
    WPI_ERROR(m_logger, "bind() to port " << m_port
                                          << " failed: " << SocketStrerror());
    return result;
  }

  result = listen(m_lsd, 5);
  if (result != 0) {
    WPI_ERROR(m_logger, "listen() on port " << m_port
                                            << " failed: " << SocketStrerror());
    return result;
  }
  m_listening = true;
  return result;
}

void TCPAcceptor::shutdown() {
  m_shutdown = true;
#ifdef _WIN32
  ::shutdown(m_lsd, SD_BOTH);

  // this is ugly, but the easiest way to do this
  // force wakeup of accept() with a non-blocking connect to ourselves
  struct sockaddr_in address;

  std::memset(&address, 0, sizeof(address));
  address.sin_family = PF_INET;
  llvm::SmallString<128> addr_copy;
  if (m_address.size() > 0)
    addr_copy = m_address;
  else
    addr_copy = "127.0.0.1";
  addr_copy.push_back('\0');
  int size = sizeof(address);
  if (WSAStringToAddress(addr_copy.data(), PF_INET, nullptr,
                         (struct sockaddr*)&address, &size) != 0)
    return;
  address.sin_port = htons(m_port);

  fd_set sdset;
  struct timeval tv;
  int result = -1, valopt, sd = socket(AF_INET, SOCK_STREAM, 0);
  if (sd < 0) return;

  // Set socket to non-blocking
  u_long mode = 1;
  ioctlsocket(sd, FIONBIO, &mode);

  // Try to connect
  ::connect(sd, (struct sockaddr*)&address, sizeof(address));

  // Close
  ::closesocket(sd);

#else
  ::shutdown(m_lsd, SHUT_RDWR);
  int nullfd = ::open("/dev/null", O_RDONLY);
  if (nullfd >= 0) {
    ::dup2(nullfd, m_lsd);
    ::close(nullfd);
  }
#endif
}

std::unique_ptr<NetworkStream> TCPAcceptor::accept() {
  if (!m_listening || m_shutdown) return nullptr;

  struct sockaddr_in address;
#ifdef _WIN32
  int len = sizeof(address);
#else
  socklen_t len = sizeof(address);
#endif
  std::memset(&address, 0, sizeof(address));
  int sd = ::accept(m_lsd, (struct sockaddr*)&address, &len);
  if (sd < 0) {
    if (!m_shutdown)
      WPI_ERROR(m_logger, "accept() on port "
                              << m_port << " failed: " << SocketStrerror());
    return nullptr;
  }
  if (m_shutdown) {
#ifdef _WIN32
    closesocket(sd);
#else
    close(sd);
#endif
    return nullptr;
  }
  return std::unique_ptr<NetworkStream>(new TCPStream(sd, &address));
}
<|endoftext|>


<commit_before>//
// TreeView.cpp
//
// Copyright (c) 2001 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "App.h"
#include "TreeView.h"
#include "MenuEnum.h"	// for TreeTest_Ctrl
#include "Frame.h"
#include "BuilderView.h"

DECLARE_APP(MyApp)

// Under Windows, the icons are in the .rc file; on Unix, they are included
// from .xpm files.
#ifndef __WXMSW__
	#include "building.xpm"
	#include "file1.xpm"
	#include "file2.xpm"
	#include "folder1.xpm"
	#include "folder2.xpm"
	#include "folder3.xpm"

	#include "grid.xpm"
	#include "image.xpm"
	#include "raw.xpm"
	#include "road.xpm"
	#include "veg1.xpm"
	#include "water.xpm"
	#include "util.xpm"
#endif

/////////////////////////////////////////////////

// MyTreeCtrl implementation
IMPLEMENT_DYNAMIC_CLASS(MyTreeCtrl, wxTreeCtrl)

MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id,
					   const wxPoint& pos, const wxSize& size,
					   long style)
		  : wxTreeCtrl(parent, id, pos, size, style)
{
	m_reverseSort = false;
	m_imageListNormal = NULL;
	m_bShowPaths = true;

	CreateImageList(16);

	// Add some items to the tree
	RefreshTreeItems(NULL);
}

void MyTreeCtrl::CreateImageList(int size)
{
	delete m_imageListNormal;

	if ( size == -1 )
	{
		m_imageListNormal = NULL;
		return;
	}

	// Make an image list containing small icons
	m_imageListNormal = new wxImageList(size, size, TRUE);

	// should correspond to TreeCtrlIcon_xxx enum
	wxIcon icons[14];
	icons[0] = wxICON(file1);
	icons[1] = wxICON(file2);
	icons[2] = wxICON(folder1);
	icons[3] = wxICON(folder2);
	icons[4] = wxICON(folder3);
	icons[5] = wxICON(building);
	icons[6] = wxICON(road);
	icons[7] = wxICON(grid);
	icons[8] = wxICON(image);
	icons[9] = wxICON(veg1);
	icons[10] = wxICON(water);
	icons[11] = wxICON(transit);
	icons[12] = wxICON(util);
	icons[13] = wxICON(raw);

	int sizeOrig = icons[0].GetWidth();
	for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
	{
		if ( size == sizeOrig )
			m_imageListNormal->Add(icons[i]);
		else
			m_imageListNormal->Add(wxImage(icons[i]).Rescale(size, size).
									ConvertToBitmap());
	}

	SetImageList(m_imageListNormal);
}

MyTreeCtrl::~MyTreeCtrl()
{
	delete m_imageListNormal;
}

int MyTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
							   const wxTreeItemId& item2)
{
	if ( m_reverseSort )
	{
		// just exchange 1st and 2nd items
		return wxTreeCtrl::OnCompareItems(item2, item1);
	}
	else
	{
		return wxTreeCtrl::OnCompareItems(item1, item2);
	}
}

wxTreeItemId rootId;

wxTreeItemId MyTreeCtrl::AddRootItem(int image, const char *text)
{
	wxTreeItemId id = AppendItem(rootId, text, image);
	SetItemBold(id);
	return id;
}

wxString MyTreeCtrl::MakeItemName(vtLayerPtr lp)
{
	wxString str;
	if (lp->GetModified())
		str += "(*) ";
	wxString fullpath = lp->GetFilename();
	if (!m_bShowPaths)
	{
		if (fullpath.Find('/') != -1)
			fullpath = fullpath.AfterLast('/');
		if (fullpath.Find('\\') != -1)
			fullpath = fullpath.AfterLast('\\');
		if (fullpath.Find(':') != -1)
			fullpath = fullpath.AfterLast(':');
	}
	str += fullpath;
	return str;
}

void MyTreeCtrl::RefreshTreeItems(MainFrame *pFrame)
{
	DeleteAllItems();

	rootId = AddRoot("Layers");
	SetItemBold(rootId);

	int	image, imageSel;

	wxTreeItemId elevId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Grid, "Elevation");
//	wxTreeItemId imageId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Image, "Images");
	wxTreeItemId buildId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Building, "Structures");
	wxTreeItemId roadId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Road, "Roads");
	wxTreeItemId vegId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Veg1, "Vegetation");
	wxTreeItemId waterId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Water, "Water");
#if SUPPORT_TRANSIT
	wxTreeItemId transId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Transit, "Transit");
#endif
	wxTreeItemId utilityId = AddRootItem(MyTreeCtrl::TreeCtrlIcon_Utility, "Utilities");
	wxTreeItemId rawId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Raw, "Raw");

	image = TreeCtrlIcon_File;
	imageSel = TreeCtrlIcon_FileSelected;
	vtLayerPtr lp;
	int iLayers = 0;
	if (pFrame) iLayers = pFrame->m_Layers.GetSize();
	for (int i = 0; i < iLayers; i++)
	{
		lp = pFrame->m_Layers.GetAt(i);

		wxString str = MakeItemName(lp);

		wxTreeItemId hItem;
		switch (lp->GetType())
		{
			case LT_ELEVATION:
				hItem = AppendItem(elevId, str, image, imageSel);
				break;
			case LT_ROAD:
				hItem = AppendItem(roadId, str, image, imageSel);
				break;
			case LT_STRUCTURE:
				hItem = AppendItem(buildId, str, image, imageSel);
				break;
			case LT_VEG:
				hItem = AppendItem(vegId, str, image, imageSel);
				break;
			case LT_WATER:
				hItem = AppendItem(waterId, str, image, imageSel);
				break;
#if SUPPORT_TRANSIT
			case LT_TRANSIT:
				hItem = AppendItem(transId, str, image, imageSel);
				break;
#endif
			case LT_UTILITY:
				hItem = AppendItem(utilityId, str, image, imageSel);
				break;
			case LT_RAW:
				hItem = AppendItem(rawId, str, image, imageSel);
				break;
		}
		SetItemData(hItem, new MyTreeItemData(lp));

		if (lp == pFrame->GetActiveLayer())
			SelectItem(hItem);
	}

	Expand(rootId);
	Expand(elevId);
//	Expand(imageId);
	Expand(roadId);
	Expand(buildId);
	Expand(vegId);
	Expand(waterId);
#if SUPPORT_TRANSIT
	Expand(transId);
#endif
	Expand(utilityId);
	Expand(rawId);
}

void MyTreeCtrl::RefreshTreeStatus(MainFrame *pFrame)
{
	wxTreeItemId root = GetRootItem();
	wxTreeItemId parent, item;
	long cookie = 0, cookie2 = 1;

	for (parent = GetFirstChild(root, cookie); parent; parent = GetNextChild(root, cookie))
	{
//		wxString str = GetItemText(parent);
		for (item = GetFirstChild(parent, cookie2); item; item = GetNextChild(parent, cookie2))
		{
			MyTreeItemData *data = (MyTreeItemData *)GetItemData(item);
//			wxString str2 = GetItemText(item);
			if (data)
			{
				SetItemText(item, MakeItemName(data->m_pLayer));
				if (data->m_pLayer == pFrame->GetActiveLayer())
					SelectItem(item);
			}
		}
	}
}

// avoid repetition
#define TREE_EVENT_HANDLER(name)			\
void MyTreeCtrl::name(wxTreeEvent& event)	\
{											\
 /*	wxLogMessage(#name); */					\
	event.Skip();							\
}

TREE_EVENT_HANDLER(OnBeginRDrag)
TREE_EVENT_HANDLER(OnDeleteItem)
TREE_EVENT_HANDLER(OnGetInfo)
TREE_EVENT_HANDLER(OnSetInfo)
TREE_EVENT_HANDLER(OnItemExpanded)
TREE_EVENT_HANDLER(OnItemExpanding)
TREE_EVENT_HANDLER(OnItemCollapsed)
TREE_EVENT_HANDLER(OnSelChanging)
TREE_EVENT_HANDLER(OnTreeKeyDown)

#undef TREE_EVENT_HANDLER

void MyTreeCtrl::OnSelChanged(wxTreeEvent& event)
{
	wxTreeItemId item = event.GetItem();
	MyTreeItemData *data = (MyTreeItemData *)GetItemData(item);
	vtLayerPtr lp = NULL;
	if (data)
		lp = data->m_pLayer;

	vtLayerPtr last = GetMainFrame()->GetActiveLayer();
	if (lp != last)
		GetMainFrame()->GetView()->SetActiveLayer(lp);

	LayerType last_ltype = last ? last->GetType() : LT_UNKNOWN;
	if (lp && lp->GetType() != last_ltype)
		GetMainFrame()->RefreshToolbar();
}

void MyTreeCtrl::OnBeginDrag(wxTreeEvent& event)
{
}

void MyTreeCtrl::OnEndDrag(wxTreeEvent& event)
{
}

void MyTreeCtrl::OnBeginLabelEdit(wxTreeEvent& event)
{
#if 0
	wxLogMessage("OnBeginLabelEdit");

	// for testing, prevent this items label editing
	wxTreeItemId itemId = event.GetItem();
	if ( IsTestItem(itemId) )
	{
		wxMessageBox("You can't edit this item.");

		event.Veto();
	}
#endif
}

void MyTreeCtrl::OnEndLabelEdit(wxTreeEvent& event)
{
#if 0
	wxLogMessage("OnEndLabelEdit");

	// don't allow anything except letters in the labels
	if ( !event.GetLabel().IsWord() )
	{
		wxMessageBox("The label should contain only letters.");

		event.Veto();
	}
#endif
}

void MyTreeCtrl::OnItemCollapsing(wxTreeEvent& event)
{
#if 0
	wxLogMessage("OnItemCollapsing");

	// for testing, prevent the user from collapsing the first child folder
	wxTreeItemId itemId = event.GetItem();
	if ( IsTestItem(itemId) )
	{
		wxMessageBox("You can't collapse this item.");

		event.Veto();
	}
#endif
}

void MyTreeCtrl::OnItemActivated(wxTreeEvent& event)
{
#if 0
	// show some info about this item
	wxTreeItemId itemId = event.GetItem();
	MyTreeItemData *item = (MyTreeItemData *)GetItemData(itemId);

	if ( item != NULL )
	{
		item->ShowInfo(this);
	}
	wxLogMessage("OnItemActivated");
#endif
}

void MyTreeCtrl::OnRMouseDClick(wxMouseEvent& event)
{
#if 0
	wxTreeItemId id = HitTest(event.GetPosition());
	if ( !id )
		wxLogMessage("No item under mouse");
	else
	{
		MyTreeItemData *item = (MyTreeItemData *)GetItemData(id);
		if ( item )
			wxLogMessage("Item '%s' under mouse", item->GetDesc());
	}
#endif
}

/////////////////////////////////////////////////

BEGIN_EVENT_TABLE(MyTreeCtrl, wxTreeCtrl)
	EVT_TREE_BEGIN_DRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginDrag)
	EVT_TREE_BEGIN_RDRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginRDrag)
	EVT_TREE_END_DRAG(TreeTest_Ctrl, MyTreeCtrl::OnEndDrag)
	EVT_TREE_BEGIN_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnBeginLabelEdit)
	EVT_TREE_END_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnEndLabelEdit)
	EVT_TREE_DELETE_ITEM(TreeTest_Ctrl, MyTreeCtrl::OnDeleteItem)
	EVT_TREE_SET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnSetInfo)
	EVT_TREE_ITEM_EXPANDED(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanded)
	EVT_TREE_ITEM_EXPANDING(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanding)
	EVT_TREE_ITEM_COLLAPSED(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsed)
	EVT_TREE_ITEM_COLLAPSING(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsing)
	EVT_TREE_SEL_CHANGED(TreeTest_Ctrl, MyTreeCtrl::OnSelChanged)
	EVT_TREE_SEL_CHANGING(TreeTest_Ctrl, MyTreeCtrl::OnSelChanging)
	EVT_TREE_KEY_DOWN(TreeTest_Ctrl, MyTreeCtrl::OnTreeKeyDown)
	EVT_TREE_ITEM_ACTIVATED(TreeTest_Ctrl, MyTreeCtrl::OnItemActivated)
	EVT_RIGHT_DCLICK(MyTreeCtrl::OnRMouseDClick)
END_EVENT_TABLE()

<commit_msg>added transit.xpm<commit_after>//
// TreeView.cpp
//
// Copyright (c) 2001 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "App.h"
#include "TreeView.h"
#include "MenuEnum.h"	// for TreeTest_Ctrl
#include "Frame.h"
#include "BuilderView.h"

DECLARE_APP(MyApp)

// Under Windows, the icons are in the .rc file; on Unix, they are included
// from .xpm files.
#ifndef __WXMSW__
#include "building.xpm"
#include "file1.xpm"
#include "file2.xpm"
#include "folder1.xpm"
#include "folder2.xpm"
#include "folder3.xpm"

#include "grid.xpm"
#include "image.xpm"
#include "raw.xpm"
#include "road.xpm"
#include "veg1.xpm"
#include "water.xpm"
#include "util.xpm"
#include "transit.xpm"
#endif

/////////////////////////////////////////////////

// MyTreeCtrl implementation
	IMPLEMENT_DYNAMIC_CLASS(MyTreeCtrl, wxTreeCtrl)

MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id,
	const wxPoint& pos, const wxSize& size,
	long style)
: wxTreeCtrl(parent, id, pos, size, style)
{
	m_reverseSort = false;
	m_imageListNormal = NULL;
	m_bShowPaths = true;

	CreateImageList(16);

	// Add some items to the tree
	RefreshTreeItems(NULL);
}

void MyTreeCtrl::CreateImageList(int size)
{
	delete m_imageListNormal;

	if ( size == -1 )
	{
		m_imageListNormal = NULL;
		return;
	}

	// Make an image list containing small icons
	m_imageListNormal = new wxImageList(size, size, TRUE);

	// should correspond to TreeCtrlIcon_xxx enum
	wxIcon icons[14];
	icons[0] = wxICON(file1);
	icons[1] = wxICON(file2);
	icons[2] = wxICON(folder1);
	icons[3] = wxICON(folder2);
	icons[4] = wxICON(folder3);
	icons[5] = wxICON(building);
	icons[6] = wxICON(road);
	icons[7] = wxICON(grid);
	icons[8] = wxICON(image);
	icons[9] = wxICON(veg1);
	icons[10] = wxICON(water);
	icons[11] = wxICON(transit);
	icons[12] = wxICON(util);
	icons[13] = wxICON(raw);

	int sizeOrig = icons[0].GetWidth();
	for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
	{
		if ( size == sizeOrig )
			m_imageListNormal->Add(icons[i]);
		else
			m_imageListNormal->Add(wxImage(icons[i]).Rescale(size, size).
				ConvertToBitmap());
	}

	SetImageList(m_imageListNormal);
}

MyTreeCtrl::~MyTreeCtrl()
{
	delete m_imageListNormal;
}

int MyTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
	const wxTreeItemId& item2)
{
	if ( m_reverseSort )
	{
		// just exchange 1st and 2nd items
		return wxTreeCtrl::OnCompareItems(item2, item1);
	}
	else
	{
		return wxTreeCtrl::OnCompareItems(item1, item2);
	}
}

wxTreeItemId rootId;

wxTreeItemId MyTreeCtrl::AddRootItem(int image, const char *text)
{
	wxTreeItemId id = AppendItem(rootId, text, image);
	SetItemBold(id);
	return id;
}

wxString MyTreeCtrl::MakeItemName(vtLayerPtr lp)
{
	wxString str;
	if (lp->GetModified())
		str += "(*) ";
	wxString fullpath = lp->GetFilename();
	if (!m_bShowPaths)
	{
		if (fullpath.Find('/') != -1)
			fullpath = fullpath.AfterLast('/');
		if (fullpath.Find('\\') != -1)
			fullpath = fullpath.AfterLast('\\');
		if (fullpath.Find(':') != -1)
			fullpath = fullpath.AfterLast(':');
	}
	str += fullpath;
	return str;
}

void MyTreeCtrl::RefreshTreeItems(MainFrame *pFrame)
{
	DeleteAllItems();

	rootId = AddRoot("Layers");
	SetItemBold(rootId);

	int	image, imageSel;

	wxTreeItemId elevId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Grid, "Elevation");
//	wxTreeItemId imageId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Image, "Images");
	wxTreeItemId buildId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Building, "Structures");
	wxTreeItemId roadId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Road, "Roads");
	wxTreeItemId vegId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Veg1, "Vegetation");
	wxTreeItemId waterId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Water, "Water");
#if SUPPORT_TRANSIT
	wxTreeItemId transId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Transit, "Transit");
#endif
	wxTreeItemId utilityId = AddRootItem(MyTreeCtrl::TreeCtrlIcon_Utility, "Utilities");
	wxTreeItemId rawId =	AddRootItem(MyTreeCtrl::TreeCtrlIcon_Raw, "Raw");

	image = TreeCtrlIcon_File;
	imageSel = TreeCtrlIcon_FileSelected;
	vtLayerPtr lp;
	int iLayers = 0;
	if (pFrame) iLayers = pFrame->m_Layers.GetSize();
	for (int i = 0; i < iLayers; i++)
	{
		lp = pFrame->m_Layers.GetAt(i);

		wxString str = MakeItemName(lp);

		wxTreeItemId hItem;
		switch (lp->GetType())
		{
			case LT_ELEVATION:
				hItem = AppendItem(elevId, str, image, imageSel);
				break;
			case LT_ROAD:
				hItem = AppendItem(roadId, str, image, imageSel);
				break;
			case LT_STRUCTURE:
				hItem = AppendItem(buildId, str, image, imageSel);
				break;
			case LT_VEG:
				hItem = AppendItem(vegId, str, image, imageSel);
				break;
			case LT_WATER:
				hItem = AppendItem(waterId, str, image, imageSel);
				break;
#if SUPPORT_TRANSIT
			case LT_TRANSIT:
				hItem = AppendItem(transId, str, image, imageSel);
				break;
#endif
			case LT_UTILITY:
				hItem = AppendItem(utilityId, str, image, imageSel);
				break;
			case LT_RAW:
				hItem = AppendItem(rawId, str, image, imageSel);
				break;
		}
		SetItemData(hItem, new MyTreeItemData(lp));

		if (lp == pFrame->GetActiveLayer())
			SelectItem(hItem);
	}

	Expand(rootId);
	Expand(elevId);
//	Expand(imageId);
	Expand(roadId);
	Expand(buildId);
	Expand(vegId);
	Expand(waterId);
#if SUPPORT_TRANSIT
	Expand(transId);
#endif
	Expand(utilityId);
	Expand(rawId);
}

void MyTreeCtrl::RefreshTreeStatus(MainFrame *pFrame)
{
	wxTreeItemId root = GetRootItem();
	wxTreeItemId parent, item;
	long cookie = 0, cookie2 = 1;

	for (parent = GetFirstChild(root, cookie); parent; parent = GetNextChild(root, cookie))
	{
//		wxString str = GetItemText(parent);
		for (item = GetFirstChild(parent, cookie2); item; item = GetNextChild(parent, cookie2))
		{
			MyTreeItemData *data = (MyTreeItemData *)GetItemData(item);
//			wxString str2 = GetItemText(item);
			if (data)
			{
				SetItemText(item, MakeItemName(data->m_pLayer));
				if (data->m_pLayer == pFrame->GetActiveLayer())
					SelectItem(item);
			}
		}
	}
}

// avoid repetition
#define TREE_EVENT_HANDLER(name)			\
void MyTreeCtrl::name(wxTreeEvent& event)	\
{											\
 /*	wxLogMessage(#name); */					\
	event.Skip();							\
}

TREE_EVENT_HANDLER(OnBeginRDrag)
	TREE_EVENT_HANDLER(OnDeleteItem)
	TREE_EVENT_HANDLER(OnGetInfo)
	TREE_EVENT_HANDLER(OnSetInfo)
	TREE_EVENT_HANDLER(OnItemExpanded)
	TREE_EVENT_HANDLER(OnItemExpanding)
	TREE_EVENT_HANDLER(OnItemCollapsed)
	TREE_EVENT_HANDLER(OnSelChanging)
	TREE_EVENT_HANDLER(OnTreeKeyDown)

#undef TREE_EVENT_HANDLER

	void MyTreeCtrl::OnSelChanged(wxTreeEvent& event)
{
	wxTreeItemId item = event.GetItem();
	MyTreeItemData *data = (MyTreeItemData *)GetItemData(item);
	vtLayerPtr lp = NULL;
	if (data)
		lp = data->m_pLayer;

	vtLayerPtr last = GetMainFrame()->GetActiveLayer();
	if (lp != last)
		GetMainFrame()->GetView()->SetActiveLayer(lp);

	LayerType last_ltype = last ? last->GetType() : LT_UNKNOWN;
	if (lp && lp->GetType() != last_ltype)
		GetMainFrame()->RefreshToolbar();
}

void MyTreeCtrl::OnBeginDrag(wxTreeEvent& event)
{
}

void MyTreeCtrl::OnEndDrag(wxTreeEvent& event)
{
}

void MyTreeCtrl::OnBeginLabelEdit(wxTreeEvent& event)
{
#if 0
	wxLogMessage("OnBeginLabelEdit");

	// for testing, prevent this items label editing
	wxTreeItemId itemId = event.GetItem();
	if ( IsTestItem(itemId) )
	{
		wxMessageBox("You can't edit this item.");

		event.Veto();
	}
#endif
}

void MyTreeCtrl::OnEndLabelEdit(wxTreeEvent& event)
{
#if 0
	wxLogMessage("OnEndLabelEdit");

	// don't allow anything except letters in the labels
	if ( !event.GetLabel().IsWord() )
	{
		wxMessageBox("The label should contain only letters.");

		event.Veto();
	}
#endif
}

void MyTreeCtrl::OnItemCollapsing(wxTreeEvent& event)
{
#if 0
	wxLogMessage("OnItemCollapsing");

	// for testing, prevent the user from collapsing the first child folder
	wxTreeItemId itemId = event.GetItem();
	if ( IsTestItem(itemId) )
	{
		wxMessageBox("You can't collapse this item.");

		event.Veto();
	}
#endif
}

void MyTreeCtrl::OnItemActivated(wxTreeEvent& event)
{
#if 0
	// show some info about this item
	wxTreeItemId itemId = event.GetItem();
	MyTreeItemData *item = (MyTreeItemData *)GetItemData(itemId);

	if ( item != NULL )
	{
		item->ShowInfo(this);
	}
	wxLogMessage("OnItemActivated");
#endif
}

void MyTreeCtrl::OnRMouseDClick(wxMouseEvent& event)
{
#if 0
	wxTreeItemId id = HitTest(event.GetPosition());
	if ( !id )
		wxLogMessage("No item under mouse");
	else
	{
		MyTreeItemData *item = (MyTreeItemData *)GetItemData(id);
		if ( item )
			wxLogMessage("Item '%s' under mouse", item->GetDesc());
	}
#endif
}

/////////////////////////////////////////////////

BEGIN_EVENT_TABLE(MyTreeCtrl, wxTreeCtrl)
EVT_TREE_BEGIN_DRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginDrag)
EVT_TREE_BEGIN_RDRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginRDrag)
EVT_TREE_END_DRAG(TreeTest_Ctrl, MyTreeCtrl::OnEndDrag)
EVT_TREE_BEGIN_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnBeginLabelEdit)
EVT_TREE_END_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnEndLabelEdit)
EVT_TREE_DELETE_ITEM(TreeTest_Ctrl, MyTreeCtrl::OnDeleteItem)
EVT_TREE_SET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnSetInfo)
EVT_TREE_ITEM_EXPANDED(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanded)
EVT_TREE_ITEM_EXPANDING(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanding)
EVT_TREE_ITEM_COLLAPSED(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsed)
EVT_TREE_ITEM_COLLAPSING(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsing)
EVT_TREE_SEL_CHANGED(TreeTest_Ctrl, MyTreeCtrl::OnSelChanged)
EVT_TREE_SEL_CHANGING(TreeTest_Ctrl, MyTreeCtrl::OnSelChanging)
EVT_TREE_KEY_DOWN(TreeTest_Ctrl, MyTreeCtrl::OnTreeKeyDown)
EVT_TREE_ITEM_ACTIVATED(TreeTest_Ctrl, MyTreeCtrl::OnItemActivated)
EVT_RIGHT_DCLICK(MyTreeCtrl::OnRMouseDClick)
END_EVENT_TABLE()
<|endoftext|>


<commit_before>/*
Copyright (c) 2012, William Magato
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ''AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the copyright holder(s) or contributors.
*/

#include <cstdint>
#include <cstring>

#include <ios>
#include <stdexcept>

#include <xen/xen.h>
#include <xen/features.h>
#include <xen/version.h>

#include <llamaos/memory/memory.h>
#include <llamaos/xen/Hypercall.h>
#include <llamaos/xen/Hypervisor.h>
#include <llamaos/config.h>
#include <llamaos/trace.h>

using namespace std;
using namespace llamaos;
using namespace llamaos::xen;

namespace llamaos {
namespace memory {

// needs initialized by startup logic
extern uint64_t *machine_table;
extern uint64_t  machine_table_size;
extern uint64_t *pseudo_table;
extern uint64_t  pseudo_table_size;

} }

// runtime stack memory
char RUNTIME_STACK [2 * llamaos::STACK_SIZE];

uint8_t xen_features [XENFEAT_NR_SUBMAPS * 32];

static bool verify_magic (const start_info_t *start_info)
{
   if (   (nullptr != start_info)
       && (0 == strncmp (start_info->magic, "xen-", 4)))
   {
      return true;
   }

   return false;
}

static void trace_startup (const start_info_t *start_info)
{
   trace ("\n\n\n*********************************\n");
   trace (      "****  starting llamaOS (Xen)  ***\n");
   trace (      "*********************************\n\n\n");

   trace ("%s\n\n", VERSION_TEXT);

   trace ("=== start_info ===\n");
   trace ("  magic: %s\n", start_info->magic);
   trace ("  nr_pages: %x\n", start_info->nr_pages);
   trace ("  shared_info: %x\n", start_info->shared_info);
   trace ("  flags: %x\n", start_info->flags);
   trace ("  store_mfn: %x\n", start_info->store_mfn);
   trace ("  store_evtchn: %x\n", start_info->store_evtchn);
   trace ("  console.domU.mfn: %x\n", start_info->console.domU.mfn);
   trace ("  console.domU.evtchn: %x\n", start_info->console.domU.evtchn);
   trace ("  pt_base: %x\n", start_info->pt_base);
   trace ("  nr_pt_frames: %x\n", start_info->nr_pt_frames);
   trace ("  mfn_list: %x\n", start_info->mfn_list);
   trace ("  mod_start: %x\n", start_info->mod_start);
   trace ("  mod_len: %x\n", start_info->mod_len);
   trace ("  cmd_line: %s\n", start_info->cmd_line);
   trace ("  first_p2m_pfn: %x\n", start_info->first_p2m_pfn);
   trace ("  nr_p2m_frames: %x\n", start_info->nr_p2m_frames);
   trace ("\n");
}

extern int main (int, char*[]);

void register_glibc_exports ();

typedef void (*func_ptr) (void);
extern func_ptr __CTOR_LIST__[];
extern func_ptr __DTOR_LIST__[];

static const char *program_name = "llamaOS";

extern "C"
void start (start_info_t *start_info)
{
   if (verify_magic (start_info))
   {
      trace_startup (start_info);

      // initialize memory management
      memory::machine_table = memory::address_to_pointer<uint64_t>(MACH2PHYS_VIRT_START);
      memory::machine_table_size = MACH2PHYS_NR_ENTRIES;
      memory::pseudo_table = memory::address_to_pointer<uint64_t> (start_info->mfn_list);
      memory::pseudo_table_size = start_info->nr_pages;

      memory::initialize (start_info->pt_base, start_info->nr_pages, 1024);

      // register callbacks to the glibc library
      register_glibc_exports ();

      uint64_t ctor_size = reinterpret_cast<uint64_t>(__CTOR_LIST__[0]);
      trace ("__CTOR_LIST__[0]: %lx\n", ctor_size);
      for (uint64_t i = ctor_size; i >= 1; i--)
      {
         __CTOR_LIST__[i] ();
      }

      // initialize libstdc++
      ios_base::Init ios_base_init;

      try
      {
         // create the one and only hypervisor object
         trace ("Creating Hypervisor...\n");
         Hypervisor hypervisor (start_info);

         // start the application
         char *argv [2];
         argv [0] = const_cast<char *>(program_name);
         argv [1] = 0;

         main (1, argv);

         trace ("ending llamaOS...\n");
      }
      catch (const std::runtime_error &e)
      {
         trace ("*** runtime_error: %s ***\n", e.what ());
      }
      catch (...)
      {
         trace ("*** unknown exception ***\n");
      }

      for (;;)
      {
         Hypercall::sched_op_block ();
      }

      uint64_t dtor_size = reinterpret_cast<uint64_t>(__DTOR_LIST__[0]);
      trace ("__DTOR_LIST__[0]: %lx\n", dtor_size);
      for (uint64_t i = dtor_size; i >= 1; i--)
      {
         __DTOR_LIST__[i] ();
      }

//      Hypercall::sched_op_shutdown ();
   }
   // else
   // something terrible is wrong and nothing can be done about it!
}
<commit_msg>looking for crash at close of app main<commit_after>/*
Copyright (c) 2012, William Magato
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ''AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the copyright holder(s) or contributors.
*/

#include <cstdint>
#include <cstring>

#include <ios>
#include <stdexcept>

#include <xen/xen.h>
#include <xen/features.h>
#include <xen/version.h>

#include <llamaos/memory/memory.h>
#include <llamaos/xen/Hypercall.h>
#include <llamaos/xen/Hypervisor.h>
#include <llamaos/config.h>
#include <llamaos/trace.h>

using namespace std;
using namespace llamaos;
using namespace llamaos::xen;

namespace llamaos {
namespace memory {

// needs initialized by startup logic
extern uint64_t *machine_table;
extern uint64_t  machine_table_size;
extern uint64_t *pseudo_table;
extern uint64_t  pseudo_table_size;

} }

// runtime stack memory
char RUNTIME_STACK [2 * llamaos::STACK_SIZE];

uint8_t xen_features [XENFEAT_NR_SUBMAPS * 32];

static bool verify_magic (const start_info_t *start_info)
{
   if (   (nullptr != start_info)
       && (0 == strncmp (start_info->magic, "xen-", 4)))
   {
      return true;
   }

   return false;
}

static void trace_startup (const start_info_t *start_info)
{
   trace ("\n\n\n*********************************\n");
   trace (      "****  starting llamaOS (Xen)  ***\n");
   trace (      "*********************************\n\n\n");

   trace ("%s\n\n", VERSION_TEXT);

   trace ("=== start_info ===\n");
   trace ("  magic: %s\n", start_info->magic);
   trace ("  nr_pages: %x\n", start_info->nr_pages);
   trace ("  shared_info: %x\n", start_info->shared_info);
   trace ("  flags: %x\n", start_info->flags);
   trace ("  store_mfn: %x\n", start_info->store_mfn);
   trace ("  store_evtchn: %x\n", start_info->store_evtchn);
   trace ("  console.domU.mfn: %x\n", start_info->console.domU.mfn);
   trace ("  console.domU.evtchn: %x\n", start_info->console.domU.evtchn);
   trace ("  pt_base: %x\n", start_info->pt_base);
   trace ("  nr_pt_frames: %x\n", start_info->nr_pt_frames);
   trace ("  mfn_list: %x\n", start_info->mfn_list);
   trace ("  mod_start: %x\n", start_info->mod_start);
   trace ("  mod_len: %x\n", start_info->mod_len);
   trace ("  cmd_line: %s\n", start_info->cmd_line);
   trace ("  first_p2m_pfn: %x\n", start_info->first_p2m_pfn);
   trace ("  nr_p2m_frames: %x\n", start_info->nr_p2m_frames);
   trace ("\n");
}

extern int main (int, char*[]);

void register_glibc_exports ();

typedef void (*func_ptr) (void);
extern func_ptr __CTOR_LIST__[];
extern func_ptr __DTOR_LIST__[];

static const char *program_name = "llamaOS";

extern "C"
void start (start_info_t *start_info)
{
   if (verify_magic (start_info))
   {
      trace_startup (start_info);

      // initialize memory management
      memory::machine_table = memory::address_to_pointer<uint64_t>(MACH2PHYS_VIRT_START);
      memory::machine_table_size = MACH2PHYS_NR_ENTRIES;
      memory::pseudo_table = memory::address_to_pointer<uint64_t> (start_info->mfn_list);
      memory::pseudo_table_size = start_info->nr_pages;

      memory::initialize (start_info->pt_base, start_info->nr_pages, 1024);

      // register callbacks to the glibc library
      register_glibc_exports ();

      uint64_t ctor_size = reinterpret_cast<uint64_t>(__CTOR_LIST__[0]);
      trace ("__CTOR_LIST__[0]: %lx\n", ctor_size);
      for (uint64_t i = ctor_size; i >= 1; i--)
      {
         __CTOR_LIST__[i] ();
      }

      // initialize libstdc++
      ios_base::Init ios_base_init;

      try
      {
         // create the one and only hypervisor object
         trace ("Creating Hypervisor...\n");
         Hypervisor hypervisor (start_info);

         // start the application
         char *argv [2];
         argv [0] = const_cast<char *>(program_name);
         argv [1] = 0;

         main (1, argv);

         trace ("ending llamaOS...\n");
      }
      catch (const std::runtime_error &e)
      {
         trace ("*** runtime_error: %s ***\n", e.what ());
      }
      catch (...)
      {
         trace ("*** unknown exception ***\n");
      }

      for (int i = 0; i < 100; i++)
      {
         Hypercall::sched_op_yield ();
      }

      uint64_t dtor_size = reinterpret_cast<uint64_t>(__DTOR_LIST__[0]);
      trace ("__DTOR_LIST__[0]: %lx\n", dtor_size);
      for (uint64_t i = dtor_size; i >= 1; i--)
      {
         __DTOR_LIST__[i] ();
      }

      Hypercall::sched_op_shutdown ();
   }
   // else
   // something terrible is wrong and nothing can be done about it!
}
<|endoftext|>


<commit_before><commit_msg>fix several memory leaks in ParameterGrp when removing nodes from DOM document<commit_after><|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include <Syncs/GameAgent.h>
#include <Syncs/Interface.h>
#include <Tasks/BasicTask.h>

using namespace Hearthstonepp;

TEST(BasicCard, EX1_066)
{
    GameAgent agent(
        Player(new Account("Player 1", ""), new Deck("", CardClass::WARRIOR)),
        Player(new Account("Player 2", ""), new Deck("", CardClass::MAGE)));
    agent.GetPlayer1().totalMana = agent.GetPlayer1().existMana = 10;
    agent.GetPlayer2().totalMana = agent.GetPlayer2().existMana = 10;

    agent.Process(agent.GetPlayer1(),
                  BasicTask::DrawTask(
                      Cards::GetInstance()->FindCardByName("Fiery War Axe")));
    EXPECT_EQ(agent.GetPlayer1().hand.size(), static_cast<size_t>(1));

    agent.Process(agent.GetPlayer2(),
                  BasicTask::DrawTask(Cards::GetInstance()->FindCardByName(
                      "Acidic Swamp Ooze")));
    EXPECT_EQ(agent.GetPlayer2().hand.size(), static_cast<size_t>(1));

    agent.Process(
        agent.GetPlayer1(),
        BasicTask::PlayCardTask(0));
    EXPECT_EQ(agent.GetPlayer1().hero->weapon != nullptr, true);

    agent.Process(
        agent.GetPlayer2(),
        BasicTask::PlayCardTask(0, 0));
    EXPECT_EQ(agent.GetPlayer1().hero->weapon != nullptr, false);
}

TEST(BasicCard, CS2_041)
{
    GameAgent agent(
        Player(new Account("Player 1", ""), new Deck("", CardClass::SHAMAN)),
        Player(new Account("Player 2", ""), new Deck("", CardClass::MAGE)));
    agent.GetPlayer1().totalMana = agent.GetPlayer1().existMana = 10;
    agent.GetPlayer2().totalMana = agent.GetPlayer2().existMana = 10;

    agent.Process(agent.GetPlayer1(),
                  BasicTask::DrawTask(Cards::GetInstance()->FindCardByName(
                      "Acidic Swamp Ooze")));
    agent.Process(agent.GetPlayer1(),
                  BasicTask::DrawTask(Cards::GetInstance()->FindCardByName(
                      "Ancestral Healing")));
    EXPECT_EQ(agent.GetPlayer1().hand.size(), static_cast<size_t>(2));

    agent.Process(agent.GetPlayer1(), BasicTask::PlayCardTask(0, 0));
    auto minion = dynamic_cast<Character*>(agent.GetPlayer1().field.at(0));
    minion->health -= 1;
    EXPECT_EQ(minion->health, 1);

    agent.Process(agent.GetPlayer1(),
                  BasicTask::PlayCardTask(0, -1, TargetType::MY_FIELD, 1));
    // EXPECT_EQ(static_cast<bool>(minion->gameTags[GameTag::TAUNT]), true);
    // EXPECT_EQ(minion->health, 2);
}<commit_msg>Fix 'sign-compare' warning message<commit_after>#include "gtest/gtest.h"

#include <Syncs/GameAgent.h>
#include <Syncs/Interface.h>
#include <Tasks/BasicTask.h>

using namespace Hearthstonepp;

TEST(BasicCard, EX1_066)
{
    GameAgent agent(
        Player(new Account("Player 1", ""), new Deck("", CardClass::WARRIOR)),
        Player(new Account("Player 2", ""), new Deck("", CardClass::MAGE)));
    agent.GetPlayer1().totalMana = agent.GetPlayer1().existMana = 10;
    agent.GetPlayer2().totalMana = agent.GetPlayer2().existMana = 10;

    agent.Process(agent.GetPlayer1(),
                  BasicTask::DrawTask(
                      Cards::GetInstance()->FindCardByName("Fiery War Axe")));
    EXPECT_EQ(agent.GetPlayer1().hand.size(), static_cast<size_t>(1));

    agent.Process(agent.GetPlayer2(),
                  BasicTask::DrawTask(Cards::GetInstance()->FindCardByName(
                      "Acidic Swamp Ooze")));
    EXPECT_EQ(agent.GetPlayer2().hand.size(), static_cast<size_t>(1));

    agent.Process(
        agent.GetPlayer1(),
        BasicTask::PlayCardTask(0));
    EXPECT_EQ(agent.GetPlayer1().hero->weapon != nullptr, true);

    agent.Process(
        agent.GetPlayer2(),
        BasicTask::PlayCardTask(0, 0));
    EXPECT_EQ(agent.GetPlayer1().hero->weapon != nullptr, false);
}

TEST(BasicCard, CS2_041)
{
    GameAgent agent(
        Player(new Account("Player 1", ""), new Deck("", CardClass::SHAMAN)),
        Player(new Account("Player 2", ""), new Deck("", CardClass::MAGE)));
    agent.GetPlayer1().totalMana = agent.GetPlayer1().existMana = 10;
    agent.GetPlayer2().totalMana = agent.GetPlayer2().existMana = 10;

    agent.Process(agent.GetPlayer1(),
                  BasicTask::DrawTask(Cards::GetInstance()->FindCardByName(
                      "Acidic Swamp Ooze")));
    agent.Process(agent.GetPlayer1(),
                  BasicTask::DrawTask(Cards::GetInstance()->FindCardByName(
                      "Ancestral Healing")));
    EXPECT_EQ(agent.GetPlayer1().hand.size(), static_cast<size_t>(2));

    agent.Process(agent.GetPlayer1(), BasicTask::PlayCardTask(0, 0));
    auto minion = dynamic_cast<Character*>(agent.GetPlayer1().field.at(0));
    minion->health -= 1;
    EXPECT_EQ(minion->health, 1u);

    agent.Process(agent.GetPlayer1(),
                  BasicTask::PlayCardTask(0, -1, TargetType::MY_FIELD, 1));
    // EXPECT_EQ(static_cast<bool>(minion->gameTags[GameTag::TAUNT]), true);
    // EXPECT_EQ(minion->health, 2);
}<|endoftext|>