<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    LinExtrd.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "LinExtrd.hh"

// Description:
// Create object with normal extrusion type, capping on, scale factor=1.0,
// vector (0,0,1), and extrusion point (0,0,0).
vtkLinearExtrusionFilter::vtkLinearExtrusionFilter()
{
  this->ExtrusionType = NORMAL_EXTRUSION;
  this->Capping = 1;
  this->ScaleFactor = 1.0;
  this->Vector[0] = this->Vector[1] = 0.0; this->Vector[2] = 1.0;
  this->ExtrusionPoint[0] = this->ExtrusionPoint[1] = this->ExtrusionPoint[2] = 0.0;
}

float *vtkLinearExtrusionFilter::ViaNormal(float x[3], int id, vtkNormals *n)
{
  static float xNew[3], *normal;
  int i;

  normal = n->GetNormal(id);
  for (i=0; i<3; i++)
    xNew[i] = x[i] + this->ScaleFactor*normal[i];

  return xNew;
}

float *vtkLinearExtrusionFilter::ViaVector(float x[3], int id, vtkNormals *n)
{
  static float xNew[3];
  int i;

  for (i=0; i<3; i++)
    xNew[i] = x[i] + this->ScaleFactor*this->Vector[i];

  return xNew;
}

float *vtkLinearExtrusionFilter::ViaPoint(float x[3], int id, vtkNormals *n)
{
  static float xNew[3];
  int i;

  for (i=0; i<3; i++)
    xNew[i] = x[i] + this->ScaleFactor*(x[i] - this->ExtrusionPoint[i]);

  return xNew;
}

void vtkLinearExtrusionFilter::Execute()
{
  int numPts, numCells;
  vtkPolyData *input=(vtkPolyData *)this->Input;
  vtkPointData *pd=input->GetPointData();
  vtkNormals *inNormals;
  vtkPolyData mesh;
  vtkPoints *inPts;
  vtkCellArray *inVerts, *inLines, *inPolys, *inStrips;
  int npts, *pts, numEdges, cellId, dim;
  int ptId, ncells, ptIds[MAX_CELL_SIZE], i, j, k, p1, p2;
  float *x;
  vtkFloatPoints *newPts;
  vtkCellArray *newLines=NULL, *newPolys=NULL, *newStrips=NULL;
  vtkCell *cell, *edge;
  vtkIdList cellIds(MAX_CELL_SIZE), *cellPts;
//
// Initialize / check input
//
  vtkDebugMacro(<<"Linearly extruding data");
  this->Initialize();

  if ( (numPts=input->GetNumberOfPoints()) < 1 ||
  (numCells=input->GetNumberOfCells()) < 1 )
    {
    vtkErrorMacro(<<"No data to extrude!");
    return;
    }
//
// Decide which vector to use for extrusion
//
  if ( this->ExtrusionType == POINT_EXTRUSION )
    {
    this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaPoint;
    }
  else if ( this->ExtrusionType == NORMAL_EXTRUSION  &&
  (inNormals = pd->GetNormals()) != NULL )
    {
    this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaNormal;
    inNormals = pd->GetNormals();
    }
  else // Vector_EXTRUSION
    {
    this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaVector;
    }
//
// Build cell data structure.
//
  inPts = input->GetPoints();
  inVerts = input->GetVerts();
  inLines = input->GetLines();
  inPolys = input->GetPolys();
  inStrips = input->GetStrips();
  mesh.SetPoints(inPts);
  mesh.SetVerts(inVerts);
  mesh.SetLines(inLines);
  mesh.SetPolys(inPolys);
  mesh.SetStrips(inStrips);
  if ( inPolys || inStrips ) mesh.BuildLinks();
//
// Allocate memory for output. We don't copy normals because surface geometry
// is modified. Copy all points - this is the usual requirement and it makes
// creation of skirt much easier.
//
  this->PointData.CopyNormalsOff();
  this->PointData.CopyAllocate(pd,2*numPts);
  newPts = new vtkFloatPoints(2*numPts);
  if ( (ncells=inVerts->GetNumberOfCells()) > 0 )
    {
    newLines = new vtkCellArray;
    newLines->Allocate(newLines->EstimateSize(ncells,2));
    }
  // arbitrary initial allocation size
  ncells = inLines->GetNumberOfCells() + inPolys->GetNumberOfCells()/10 +
           inStrips->GetNumberOfCells()/10;
  ncells = (ncells < 100 ? 100 : ncells);
  newStrips = new vtkCellArray;
  newStrips->Allocate(newStrips->EstimateSize(ncells,4));

  // copy points
  for (ptId=0; ptId < numPts; ptId++)
    {
    x = inPts->GetPoint(ptId);
    newPts->SetPoint(ptId,x);
    newPts->SetPoint(ptId+numPts,(this->*(ExtrudePoint))(x,ptId,inNormals));
    this->PointData.CopyData(pd,ptId,ptId);
    this->PointData.CopyData(pd,ptId,ptId+numPts);
    }
//
// If capping is on, copy 2D cells to output (plus create cap)
//
  if ( this->Capping )
    {
    if ( inPolys->GetNumberOfCells() > 0 )
      {
      newPolys = new vtkCellArray(inPolys->GetSize());
      for ( inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); )
        {
        newPolys->InsertNextCell(npts,pts);
        newPolys->InsertNextCell(npts);
        for (i=0; i < npts; i++)
          newPolys->InsertCellPoint(pts[i] + numPts);
        }
      }

    if ( inStrips->GetNumberOfCells() > 0 )
      {
      for ( inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); )
        {
        newStrips->InsertNextCell(npts,pts);
        newStrips->InsertNextCell(npts);
        for (i=0; i < npts; i++)
          newStrips->InsertCellPoint(pts[i] + numPts);
        }
      }
    }
//
// Loop over all polygons and triangle strips searching for boundary edges.
// If boundary edge found, extrude triangle strip.
//
  for ( cellId=0; cellId < numCells; cellId++)
    {
    cell = mesh.GetCell(cellId);
    cellPts = cell->GetPointIds();

    if ( (dim=cell->GetCellDimension()) == 0 ) //create lines from points
      {
      for (i=0; i<cellPts->GetNumberOfIds(); i++)
        {
        newLines->InsertNextCell(2);
        ptId = cellPts->GetId(i);
        newLines->InsertCellPoint(ptId);
        newLines->InsertCellPoint(ptId+numPts);
        }
      }

    else if ( dim == 1 ) // create strips from lines
      {
      for (i=0; i < (cellPts->GetNumberOfIds()-1); i++)
        {
        p1 = cellPts->GetId(i);
        p2 = cellPts->GetId(i+1);
        newStrips->InsertNextCell(4);
        newStrips->InsertCellPoint(p1);
        newStrips->InsertCellPoint(p2);
        newStrips->InsertCellPoint(p1+numPts);
        newStrips->InsertCellPoint(p2+numPts);
        }
      }

    else if ( dim == 2 ) // create strips from boundary edges
      {
      numEdges = cell->GetNumberOfEdges();
      for (i=0; i<numEdges; i++)
        {
        edge = cell->GetEdge(i);
        for (j=0; j<(edge->GetNumberOfPoints()-1); j++)
          {
          p1 = edge->PointIds.GetId(j);
          p2 = edge->PointIds.GetId(j+1);
          mesh.GetCellEdgeNeighbors(cellId, p1, p2, cellIds);

          if ( cellIds.GetNumberOfIds() < 1 ) //generate strip
            {
            newStrips->InsertNextCell(4);
            newStrips->InsertCellPoint(p1);
            newStrips->InsertCellPoint(p2);
            newStrips->InsertCellPoint(p1+numPts);
            newStrips->InsertCellPoint(p2+numPts);
            }
          } //for each sub-edge
        } //for each edge
      } //for each polygon or triangle strip
    } //for each cell
//
// Send data to output and release memory
//
  this->SetPoints(newPts);
  newPts->Delete();

  if ( newLines )
    {
    this->SetLines(newLines);
    newLines->Delete();
    }

  if ( newPolys )
    {
    this->SetPolys(newPolys);
    newPolys->Delete();
    }

  this->SetStrips(newStrips);
  newStrips->Delete();

  this->Squeeze();
}

void vtkLinearExtrusionFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyToPolyFilter::PrintSelf(os,indent);

  if ( this->ExtrusionType == VECTOR_EXTRUSION )
    {
    os << indent << "Extrusion Type: Extrude along vector\n";
    os << indent << "Vector: (" << this->Vector[0] << ", "
       << this->Vector[1] << ", " << this->Vector[2] << ")\n";
    }
  else if ( this->ExtrusionType == NORMAL_EXTRUSION )
    {
    os << indent << "Extrusion Type: Extrude along vertex normals\n";
    }
  else //POINT_EXTRUSION
    {
    os << indent << "Extrusion Type: Extrude towards point\n";
    os << indent << "Extrusion Point: (" << this->ExtrusionPoint[0] << ", "
       << this->ExtrusionPoint[1] << ", " << this->ExtrusionPoint[2] << ")\n";
    }

  os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
  os << indent << "Scale Factor: " << this->ScaleFactor << "\n";
}

<commit_msg>removed some unused variables<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    LinExtrd.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "LinExtrd.hh"

// Description:
// Create object with normal extrusion type, capping on, scale factor=1.0,
// vector (0,0,1), and extrusion point (0,0,0).
vtkLinearExtrusionFilter::vtkLinearExtrusionFilter()
{
  this->ExtrusionType = NORMAL_EXTRUSION;
  this->Capping = 1;
  this->ScaleFactor = 1.0;
  this->Vector[0] = this->Vector[1] = 0.0; this->Vector[2] = 1.0;
  this->ExtrusionPoint[0] = this->ExtrusionPoint[1] = this->ExtrusionPoint[2] = 0.0;
}

float *vtkLinearExtrusionFilter::ViaNormal(float x[3], int id, vtkNormals *n)
{
  static float xNew[3], *normal;
  int i;

  normal = n->GetNormal(id);
  for (i=0; i<3; i++)
    xNew[i] = x[i] + this->ScaleFactor*normal[i];

  return xNew;
}

float *vtkLinearExtrusionFilter::ViaVector(float x[3], int id, vtkNormals *n)
{
  static float xNew[3];
  int i;

  for (i=0; i<3; i++)
    xNew[i] = x[i] + this->ScaleFactor*this->Vector[i];

  return xNew;
}

float *vtkLinearExtrusionFilter::ViaPoint(float x[3], int id, vtkNormals *n)
{
  static float xNew[3];
  int i;

  for (i=0; i<3; i++)
    xNew[i] = x[i] + this->ScaleFactor*(x[i] - this->ExtrusionPoint[i]);

  return xNew;
}

void vtkLinearExtrusionFilter::Execute()
{
  int numPts, numCells;
  vtkPolyData *input=(vtkPolyData *)this->Input;
  vtkPointData *pd=input->GetPointData();
  vtkNormals *inNormals;
  vtkPolyData mesh;
  vtkPoints *inPts;
  vtkCellArray *inVerts, *inLines, *inPolys, *inStrips;
  int npts, *pts, numEdges, cellId, dim;
  int ptId, ncells, i, j, p1, p2;
  float *x;
  vtkFloatPoints *newPts;
  vtkCellArray *newLines=NULL, *newPolys=NULL, *newStrips=NULL;
  vtkCell *cell, *edge;
  vtkIdList cellIds(MAX_CELL_SIZE), *cellPts;
//
// Initialize / check input
//
  vtkDebugMacro(<<"Linearly extruding data");
  this->Initialize();

  if ( (numPts=input->GetNumberOfPoints()) < 1 ||
  (numCells=input->GetNumberOfCells()) < 1 )
    {
    vtkErrorMacro(<<"No data to extrude!");
    return;
    }
//
// Decide which vector to use for extrusion
//
  if ( this->ExtrusionType == POINT_EXTRUSION )
    {
    this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaPoint;
    }
  else if ( this->ExtrusionType == NORMAL_EXTRUSION  &&
  (inNormals = pd->GetNormals()) != NULL )
    {
    this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaNormal;
    inNormals = pd->GetNormals();
    }
  else // Vector_EXTRUSION
    {
    this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaVector;
    }
//
// Build cell data structure.
//
  inPts = input->GetPoints();
  inVerts = input->GetVerts();
  inLines = input->GetLines();
  inPolys = input->GetPolys();
  inStrips = input->GetStrips();
  mesh.SetPoints(inPts);
  mesh.SetVerts(inVerts);
  mesh.SetLines(inLines);
  mesh.SetPolys(inPolys);
  mesh.SetStrips(inStrips);
  if ( inPolys || inStrips ) mesh.BuildLinks();
//
// Allocate memory for output. We don't copy normals because surface geometry
// is modified. Copy all points - this is the usual requirement and it makes
// creation of skirt much easier.
//
  this->PointData.CopyNormalsOff();
  this->PointData.CopyAllocate(pd,2*numPts);
  newPts = new vtkFloatPoints(2*numPts);
  if ( (ncells=inVerts->GetNumberOfCells()) > 0 )
    {
    newLines = new vtkCellArray;
    newLines->Allocate(newLines->EstimateSize(ncells,2));
    }
  // arbitrary initial allocation size
  ncells = inLines->GetNumberOfCells() + inPolys->GetNumberOfCells()/10 +
           inStrips->GetNumberOfCells()/10;
  ncells = (ncells < 100 ? 100 : ncells);
  newStrips = new vtkCellArray;
  newStrips->Allocate(newStrips->EstimateSize(ncells,4));

  // copy points
  for (ptId=0; ptId < numPts; ptId++)
    {
    x = inPts->GetPoint(ptId);
    newPts->SetPoint(ptId,x);
    newPts->SetPoint(ptId+numPts,(this->*(ExtrudePoint))(x,ptId,inNormals));
    this->PointData.CopyData(pd,ptId,ptId);
    this->PointData.CopyData(pd,ptId,ptId+numPts);
    }
//
// If capping is on, copy 2D cells to output (plus create cap)
//
  if ( this->Capping )
    {
    if ( inPolys->GetNumberOfCells() > 0 )
      {
      newPolys = new vtkCellArray(inPolys->GetSize());
      for ( inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); )
        {
        newPolys->InsertNextCell(npts,pts);
        newPolys->InsertNextCell(npts);
        for (i=0; i < npts; i++)
          newPolys->InsertCellPoint(pts[i] + numPts);
        }
      }

    if ( inStrips->GetNumberOfCells() > 0 )
      {
      for ( inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); )
        {
        newStrips->InsertNextCell(npts,pts);
        newStrips->InsertNextCell(npts);
        for (i=0; i < npts; i++)
          newStrips->InsertCellPoint(pts[i] + numPts);
        }
      }
    }
//
// Loop over all polygons and triangle strips searching for boundary edges.
// If boundary edge found, extrude triangle strip.
//
  for ( cellId=0; cellId < numCells; cellId++)
    {
    cell = mesh.GetCell(cellId);
    cellPts = cell->GetPointIds();

    if ( (dim=cell->GetCellDimension()) == 0 ) //create lines from points
      {
      for (i=0; i<cellPts->GetNumberOfIds(); i++)
        {
        newLines->InsertNextCell(2);
        ptId = cellPts->GetId(i);
        newLines->InsertCellPoint(ptId);
        newLines->InsertCellPoint(ptId+numPts);
        }
      }

    else if ( dim == 1 ) // create strips from lines
      {
      for (i=0; i < (cellPts->GetNumberOfIds()-1); i++)
        {
        p1 = cellPts->GetId(i);
        p2 = cellPts->GetId(i+1);
        newStrips->InsertNextCell(4);
        newStrips->InsertCellPoint(p1);
        newStrips->InsertCellPoint(p2);
        newStrips->InsertCellPoint(p1+numPts);
        newStrips->InsertCellPoint(p2+numPts);
        }
      }

    else if ( dim == 2 ) // create strips from boundary edges
      {
      numEdges = cell->GetNumberOfEdges();
      for (i=0; i<numEdges; i++)
        {
        edge = cell->GetEdge(i);
        for (j=0; j<(edge->GetNumberOfPoints()-1); j++)
          {
          p1 = edge->PointIds.GetId(j);
          p2 = edge->PointIds.GetId(j+1);
          mesh.GetCellEdgeNeighbors(cellId, p1, p2, cellIds);

          if ( cellIds.GetNumberOfIds() < 1 ) //generate strip
            {
            newStrips->InsertNextCell(4);
            newStrips->InsertCellPoint(p1);
            newStrips->InsertCellPoint(p2);
            newStrips->InsertCellPoint(p1+numPts);
            newStrips->InsertCellPoint(p2+numPts);
            }
          } //for each sub-edge
        } //for each edge
      } //for each polygon or triangle strip
    } //for each cell
//
// Send data to output and release memory
//
  this->SetPoints(newPts);
  newPts->Delete();

  if ( newLines )
    {
    this->SetLines(newLines);
    newLines->Delete();
    }

  if ( newPolys )
    {
    this->SetPolys(newPolys);
    newPolys->Delete();
    }

  this->SetStrips(newStrips);
  newStrips->Delete();

  this->Squeeze();
}

void vtkLinearExtrusionFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyToPolyFilter::PrintSelf(os,indent);

  if ( this->ExtrusionType == VECTOR_EXTRUSION )
    {
    os << indent << "Extrusion Type: Extrude along vector\n";
    os << indent << "Vector: (" << this->Vector[0] << ", "
       << this->Vector[1] << ", " << this->Vector[2] << ")\n";
    }
  else if ( this->ExtrusionType == NORMAL_EXTRUSION )
    {
    os << indent << "Extrusion Type: Extrude along vertex normals\n";
    }
  else //POINT_EXTRUSION
    {
    os << indent << "Extrusion Type: Extrude towards point\n";
    os << indent << "Extrusion Point: (" << this->ExtrusionPoint[0] << ", "
       << this->ExtrusionPoint[1] << ", " << this->ExtrusionPoint[2] << ")\n";
    }

  os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
  os << indent << "Scale Factor: " << this->ScaleFactor << "\n";
}

<|endoftext|>


<commit_before>/**
 * Created by Jian Chen
 * @since  2016.05.27
 * @author Jian Chen <admin@chensoft.com>
 * @link   http://chensoft.com
 */
#pragma once

#include <chen/chen.hpp>
#include <gtest/gtest.h>

TEST(BaseRegexTest, General)
{
    // regex support is incomplete in gcc 4.8.x, so I comment out these codes
#if defined(__GNUC__) && !defined(__clang__)
#if __GNUC__ <= 4 && __GNUC_MINOR__ <= 8
    PILogD("test: regex support is incomplete below gcc 4.8, skip it");
    return;
#endif
#endif

    EXPECT_TRUE(chen::regex::match("12345", "^\\d+$"));
    EXPECT_EQ("chenjian", chen::regex::replace("chensoft.com", "soft\\.com", "jian"));

    auto group = chen::regex::group("127.0.0.1", "(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)");
    EXPECT_EQ(5, group.size());
    EXPECT_EQ("127", group[1]);
    EXPECT_EQ("0", group[2]);
    EXPECT_EQ("0", group[3]);
    EXPECT_EQ("1", group[4]);
}<commit_msg>test: use pragma directive to warning regex unit test below gcc 4.9<commit_after>/**
 * Created by Jian Chen
 * @since  2016.05.27
 * @author Jian Chen <admin@chensoft.com>
 * @link   http://chensoft.com
 */
#pragma once

#include <chen/chen.hpp>
#include <gtest/gtest.h>

TEST(BaseRegexTest, General)
{
    // regex support is incomplete in gcc 4.8.x, so I comment out these codes
#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ <= 8)
    #pragma message("regex support is incomplete below gcc 4.8, skip it")
#else
    EXPECT_TRUE(chen::regex::match("12345", "^\\d+$"));
    EXPECT_EQ("chenjian", chen::regex::replace("chensoft.com", "soft\\.com", "jian"));

    auto group = chen::regex::group("127.0.0.1", "(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)");
    EXPECT_EQ(5, group.size());
    EXPECT_EQ("127", group[1]);
    EXPECT_EQ("0", group[2]);
    EXPECT_EQ("0", group[3]);
    EXPECT_EQ("1", group[4]);
#endif
}<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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 <os>
#include <net/inet4>
#include <net/dhcp/dh4client.hpp>
#include <math.h> // rand()
#include <sstream>

// An IP-stack object
std::unique_ptr<net::Inet4<VirtioNet> > inet;

using namespace std::chrono;

std::string header(int content_size) {
  std::string head="HTTP/1.1 200 OK \n "                \
    "Date: Mon, 01 Jan 1970 00:00:01 GMT \n"            \
    "Server: IncludeOS prototype 4.0 \n"                \
    "Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT \n"     \
    "Content-Type: text/html; charset=UTF-8 \n"            \
    "Content-Length: "+std::to_string(content_size)+"\n"   \
    "Accept-Ranges: bytes\n"                               \
    "Connection: close\n\n";

  return head;
}

std::string html() {
  int color = rand();
  std::stringstream stream;

  /* HTML Fonts */
  std::string ubuntu_medium  = "font-family: \'Ubuntu\', sans-serif; font-weight: 500; ";
  std::string ubuntu_normal  = "font-family: \'Ubuntu\', sans-serif; font-weight: 400; ";
  std::string ubuntu_light  = "font-family: \'Ubuntu\', sans-serif; font-weight: 300; ";

  /* HTML */
  stream << ""
         << "<link href='https://fonts.googleapis.com/css?family=Ubuntu:500,300' rel='stylesheet' type='text/css'>"
         << ""
         << "<h1 style= \"color: " << "#" << std::hex << (color >> 8) << "\">"
         <<  "IncludeOS
"
         <<  "
Now speaks TCP!
"
    // .... generate more dynamic content
         << "
 This is improvised http, but proper suff is in the works.
"
         << "
 © 2016, IncludeOS AS @ 60° north "
         << "\n";

  std::string html = stream.str();

  return html;
}

const std::string NOT_FOUND = "HTTP/1.1 404 Not Found \n Connection: close\n\n";

extern char _end;

void Service::start() {
  // Assign a driver (VirtioNet) to a network interface (eth0)
  // @note: We could determine the appropirate driver dynamically, but then we'd
  // have to include all the drivers into the image, which  we want to avoid.
  hw::Nic<VirtioNet>& eth0 = hw::Dev::eth<0,VirtioNet>();

  // Bring up a network stack, attached to the nic
  // @note : No parameters after 'nic' means we'll use DHCP for IP config.
  inet = std::make_unique<net::Inet4<VirtioNet> >(eth0);

  // Static IP configuration, until we (possibly) get DHCP
  // @note : Mostly to get a robust demo service that it works with and without DHCP
  inet->network_config( { 10,0,0,42 },      // IP
                        { 255,255,255,0 },  // Netmask
                        { 10,0,0,1 },       // Gateway
                        { 8,8,8,8 } );      // DNS

  srand(OS::cycles_since_boot());

  // Set up a TCP server
  auto& server = inet->tcp().bind(80);
  auto& server_mem = inet->tcp().bind(4243);

  // Set up a UDP server
  net::UDP::port_t port = 4242;
  auto& conn = inet->udp().bind(port);

  net::UDP::port_t port_mem = 4243;
  auto& conn_mem = inet->udp().bind(port_mem);

  hw::PIT::instance().on_repeated_timeout(10s, []{
      printf("<Service> TCP STATUS:\n%s \n", inet->tcp().status().c_str());
      printf("Current memory usage: %u MB \n", OS::memory_usage() / 1000000);
    });

  server_mem.onConnect([] (auto conn) {
      conn->read(1024, [conn](net::TCP::buffer_t buf, size_t n) {
          // create string from buffer
          std::string received { (char*)buf.get(), n };
          auto reply = std::to_string(OS::memory_usage())+"\n";
          // Send the first packet, and then wait for ARP
          printf("TCP Mem: Reporting memory size as %s bytes\n", reply.c_str());
          conn->write(reply.c_str(), reply.size(), [conn](size_t n) {
              conn->close();
            });
        });
    });

  // Add a TCP connection handler - here a hardcoded HTTP-service
  server.onAccept([] (auto conn) -> bool {
      return true; // allow all connections

    }).onConnect([] (auto conn) {
        // read async with a buffer size of 1024 bytes
        // define what to do when data is read
        conn->read(1024, [conn](net::TCP::buffer_t buf, size_t n) {
            // create string from buffer
            std::string data { (char*)buf.get(), n };

            if (data.find("GET / ") != std::string::npos) {

              auto htm = html();
              auto hdr = header(htm.size());

              // create response
              conn->write(hdr.data(), hdr.size(), [](size_t n) {});
              conn->write(htm.data(), htm.size(), [](size_t n) {});
            }
            else {
              conn->write(NOT_FOUND.data(), NOT_FOUND.size());
            }
          });

      }).onDisconnect([](auto conn, auto reason) {
          conn->close();
        }).onPacketReceived([](auto, auto packet) {});

  // UDP connection handler
  conn.on_read([&] (net::UDP::addr_t addr, net::UDP::port_t port, const char* data, int len) {
      std::string received = std::string(data,len);
      std::string reply = received;

      // Send the first packet, and then wait for ARP
      conn.sendto(addr, port, reply.c_str(), reply.size());
    });

  // UDP utility to return memory usage
  conn_mem.on_read([&] (net::UDP::addr_t addr, net::UDP::port_t port, const char* data, int len) {
      std::string received = std::string(data,len);
      Expects(received == "memsize");
      auto reply = std::to_string(OS::memory_usage());
      // Send the first packet, and then wait for ARP
      printf("Reporting memory size as %s bytes\n", reply.c_str());
      conn.sendto(addr, port, reply.c_str(), reply.size());
    });

  printf("*** TEST SERVICE STARTED *** \n");
  printf("Current memory usage: %u MB \n", OS::memory_usage() / 1000000);
  printf("Ready to start\n");
  printf("Ready for UDP\n");
  printf("Ready for ICMP\n");
  printf("Ready for TCP\n");
}
<commit_msg>Backported test to old timer API<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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 <os>
#include <net/inet4>
#include <net/dhcp/dh4client.hpp>
#include <math.h> // rand()
#include <sstream>

// An IP-stack object
std::unique_ptr<net::Inet4<VirtioNet> > inet;

using namespace std::chrono;

std::string header(int content_size) {
  std::string head="HTTP/1.1 200 OK \n "                \
    "Date: Mon, 01 Jan 1970 00:00:01 GMT \n"            \
    "Server: IncludeOS prototype 4.0 \n"                \
    "Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT \n"     \
    "Content-Type: text/html; charset=UTF-8 \n"            \
    "Content-Length: "+std::to_string(content_size)+"\n"   \
    "Accept-Ranges: bytes\n"                               \
    "Connection: close\n\n";

  return head;
}

std::string html() {
  int color = rand();
  std::stringstream stream;

  /* HTML Fonts */
  std::string ubuntu_medium  = "font-family: \'Ubuntu\', sans-serif; font-weight: 500; ";
  std::string ubuntu_normal  = "font-family: \'Ubuntu\', sans-serif; font-weight: 400; ";
  std::string ubuntu_light  = "font-family: \'Ubuntu\', sans-serif; font-weight: 300; ";

  /* HTML */
  stream << ""
         << "<link href='https://fonts.googleapis.com/css?family=Ubuntu:500,300' rel='stylesheet' type='text/css'>"
         << ""
         << "<h1 style= \"color: " << "#" << std::hex << (color >> 8) << "\">"
         <<  "IncludeOS
"
         <<  "
Now speaks TCP!
"
    // .... generate more dynamic content
         << "
 This is improvised http, but proper suff is in the works.
"
         << "
 © 2016, IncludeOS AS @ 60° north "
         << "\n";

  std::string html = stream.str();

  return html;
}

const std::string NOT_FOUND = "HTTP/1.1 404 Not Found \n Connection: close\n\n";

extern char _end;

void Service::start() {
  // Assign a driver (VirtioNet) to a network interface (eth0)
  // @note: We could determine the appropirate driver dynamically, but then we'd
  // have to include all the drivers into the image, which  we want to avoid.
  hw::Nic<VirtioNet>& eth0 = hw::Dev::eth<0,VirtioNet>();

  // Bring up a network stack, attached to the nic
  // @note : No parameters after 'nic' means we'll use DHCP for IP config.
  inet = std::make_unique<net::Inet4<VirtioNet> >(eth0);

  // Static IP configuration, until we (possibly) get DHCP
  // @note : Mostly to get a robust demo service that it works with and without DHCP
  inet->network_config( { 10,0,0,42 },      // IP
                        { 255,255,255,0 },  // Netmask
                        { 10,0,0,1 },       // Gateway
                        { 8,8,8,8 } );      // DNS

  srand(OS::cycles_since_boot());

  // Set up a TCP server
  auto& server = inet->tcp().bind(80);
  auto& server_mem = inet->tcp().bind(4243);

  // Set up a UDP server
  net::UDP::port_t port = 4242;
  auto& conn = inet->udp().bind(port);

  net::UDP::port_t port_mem = 4243;
  auto& conn_mem = inet->udp().bind(port_mem);

  hw::PIT::instance().onRepeatedTimeout(10s, []{
      printf("<Service> TCP STATUS:\n%s \n", inet->tcp().status().c_str());
      printf("Current memory usage: %u MB \n", OS::memory_usage() / 1000000);
    });

  server_mem.onConnect([] (auto conn) {
      conn->read(1024, [conn](net::TCP::buffer_t buf, size_t n) {
          // create string from buffer
          std::string received { (char*)buf.get(), n };
          auto reply = std::to_string(OS::memory_usage())+"\n";
          // Send the first packet, and then wait for ARP
          printf("TCP Mem: Reporting memory size as %s bytes\n", reply.c_str());
          conn->write(reply.c_str(), reply.size(), [conn](size_t n) {
              conn->close();
            });
        });
    });

  // Add a TCP connection handler - here a hardcoded HTTP-service
  server.onAccept([] (auto conn) -> bool {
      return true; // allow all connections

    }).onConnect([] (auto conn) {
        // read async with a buffer size of 1024 bytes
        // define what to do when data is read
        conn->read(1024, [conn](net::TCP::buffer_t buf, size_t n) {
            // create string from buffer
            std::string data { (char*)buf.get(), n };

            if (data.find("GET / ") != std::string::npos) {

              auto htm = html();
              auto hdr = header(htm.size());

              // create response
              conn->write(hdr.data(), hdr.size(), [](size_t n) {});
              conn->write(htm.data(), htm.size(), [](size_t n) {});
            }
            else {
              conn->write(NOT_FOUND.data(), NOT_FOUND.size());
            }
          });

      }).onDisconnect([](auto conn, auto reason) {
          conn->close();
        }).onPacketReceived([](auto, auto packet) {});

  // UDP connection handler
  conn.on_read([&] (net::UDP::addr_t addr, net::UDP::port_t port, const char* data, int len) {
      std::string received = std::string(data,len);
      std::string reply = received;

      // Send the first packet, and then wait for ARP
      conn.sendto(addr, port, reply.c_str(), reply.size());
    });

  // UDP utility to return memory usage
  conn_mem.on_read([&] (net::UDP::addr_t addr, net::UDP::port_t port, const char* data, int len) {
      std::string received = std::string(data,len);
      Expects(received == "memsize");
      auto reply = std::to_string(OS::memory_usage());
      // Send the first packet, and then wait for ARP
      printf("Reporting memory size as %s bytes\n", reply.c_str());
      conn.sendto(addr, port, reply.c_str(), reply.size());
    });

  printf("*** TEST SERVICE STARTED *** \n");
  printf("Current memory usage: %u MB \n", OS::memory_usage() / 1000000);
  printf("Ready to start\n");
  printf("Ready for UDP\n");
  printf("Ready for ICMP\n");
  printf("Ready for TCP\n");
}
<|endoftext|>


<commit_before>#include "tables.h"
#include "daemoncomm.h"

bool editor::validateHexChar(char a)
{
    if(a >= 'a')
        a -= 32;
    return(a <= '9' && a >= '0' || a >= 'A' && a <= 'F');
}

bool editor::validate64(char str[2])
{
    //values < 64 have to start with 0 to 3
    //invalid ascii characters are filterred
    return str[0] < '4' && str[0] >= '0' && validateHexChar(str[1]);
}
unsigned char editor::charHex(char c)
{
    if(c<='9' && c>='0')
        return c-'0';
    if(c >= 'a')
        c -= 32;
    if(c>='A' && c <= 'F')
        return c-55;
    return -1;
}

char *editor::byteString(char *string, unsigned char byte)
{
    unsigned char d = byte % 0x10;
    string[1] = hexnums[d];
    byte /=0x10;
    d = byte % 0x10;
    string[0] = hexnums[d];
    return string;
}
char *editor::intString(char *string, unsigned int integer, const unsigned int &strlen)
{
    unsigned char d;
    for(int i = 0; i < strlen; i++)
    {
        d = integer & 0xF;
        string[strlen-i-1]= hexnums[d];
        integer >>= 4;
    }
    return string;
}

char *editor::shortString(char *string,  unsigned short shrt, const unsigned int &strlen)
{
    unsigned char d;
    for(int i = 0; i < strlen; i++)
    {
        d = shrt & 0xF;
        string[strlen-i-1]= hexnums[d];
        shrt >>= 4;
    }
    return string;
}

unsigned char editor::parseHexChar(char str[2])
{
    //values < 64 have to start with 0 to 3
    //invalid ascii characters are filterred
    unsigned char out = charHex(str[0])*0x10;
    out + charHex(str[1]);
    return out;
}

void editor::inform(const char *message)
{
    int length = strlen(message);
    int msglen = length;
    if(length < 64)
        length = 64;
    attroff(-1);
    attron(COLOR_PAIR(patternedtr::COL_META_SSU));
    mvprintw(3,4,"+--------------------------------------------------------------+",stdscr);

    mvprintw(8,4,"+--------------------------------------------------------------+",stdscr);
    attroff(-1);
    attron(COLOR_PAIR(patternedtr::COL_META_US));
    mvprintw(4,4,"                                                                ",stdscr);
    mvprintw(5,4,message,stdscr);
    if(msglen < 64)
        for(int i = msglen; i < 64; i++)
            mvprintw(5, 4+i, " ", stdscr);
    mvprintw(6,4,"                                                                ",stdscr);
    mvprintw(7,4," Press [Space] to continue                                      ",stdscr);
    editor::lastwin = editor::dialog;
    int ch;
    while((ch=getch()) != ' ' && ch != '\n');
    return;
}
bool editor::confirm(const char *message)
{
    int length = strlen(message);
    int msglen = length;
    if(length < 64)
        length = 64;
    attroff(-1);
    attron(COLOR_PAIR(patternedtr::COL_META_SSU));
    //modify these to output to the length
    mvprintw(3,4,"+--------------------------------------------------------------+",stdscr);
    mvprintw(8,4,"+--------------------------------------------------------------+",stdscr);
    attroff(-1);
    attron(COLOR_PAIR(patternedtr::COL_META_US));
    mvprintw(4,4,"                                                                ",stdscr);
    mvprintw(5,4,message,stdscr);
    if(msglen < 64)
        for(int i = msglen; i < 64; i++)
            mvprintw(5, 4+i, " ", stdscr);
    mvprintw(6,4,"                                                                ",stdscr);
    mvprintw(7,4," Are you sure? [y/n]                                            ",stdscr);
    editor::lastwin = editor::dialog;

    int ch;
    while((ch=getch()) != 'y' && ch != 'n' && ch != 27);
    if(ch == 'y')
        return true;
    return false;
}
void editor::displayAbout()
{
    attroff(-1);
    attron(COLOR_PAIR(patternedtr::COL_META_SSU));
    mvprintw(3,4, "+---------------------------------+",stdscr);
    mvprintw(15,4,"+---------------------------------+",stdscr);
    attroff(-1);
    attron(COLOR_PAIR(patternedtr::COL_META_US));
    mvprintw(4,4, "  Welcome to PLEBTracker!       v1 ",stdscr);
    mvprintw(5,4, "                                   ",stdscr);
    mvprintw(6,4, "Press TAB to switch windows        ",stdscr);
    mvprintw(7,4, "Press :   to open the command bar  ",stdscr);
    mvprintw(8,4, "                                   ",stdscr);
    mvprintw(9,4, "To view a list of commands, see    ",stdscr);
    mvprintw(10,4,"   the man page for plebtrkraw(1)  ",stdscr);
    mvprintw(11,4,"                                   ",stdscr);
    mvprintw(12,4,"                      -Dan Frazier ",stdscr);
    mvprintw(13,4,"                                   ",stdscr);
    mvprintw(14,4," Press [Space] to continue         ",stdscr);
    editor::lastwin = editor::dialog;
    int ch;
    while((ch=getch()) != ' ' && ch != '\n');
    return;
}

const char *editor::locateFile(bool save)
{
    return NULL;
    /*
    struct dirent *de=NULL;
    DIR *dir;

    int selection = 0;
    int viewport = 0;
    std::vector<dirent*> files;

    dir = opendir(".");
    if(dir == NULL)
    {
        std::cerr << "Failed to open current directory\n";
        return NULL;
    }
    while(de = readdir(dir))
        files.push_back(de);

    mvprintw(3,4, "+----------------------------------------------------------+",stdscr);
    if(save)
        mvprintw(4,4, "                         SAVE SONG                          ",stdscr);
    else
        mvprintw(4,4, "                         OPEN SONG                          ",stdscr);
    mvprintw(5,4, "                                                            ",stdscr);
    mvprintw(6,4, "                                                            ",stdscr);
    mvprintw(7,4, "                                                            ",stdscr);
    mvprintw(8,4, "                                                            ",stdscr);
    mvprintw(9,4, "                                                            ",stdscr);
    mvprintw(10,4,"                                                            ",stdscr);
    mvprintw(11,4,"                                                            ",stdscr);
    mvprintw(12,4,"                                                            ",stdscr);
    mvprintw(13,4,"                                                            ",stdscr);
    mvprintw(14,4,"                                                            ",stdscr);
    mvprintw(15,4,"+----------------------------------------------------------+",stdscr);

    closedir(dir);
*/
    editor::lastwin = editor::dialog;
}

void editor::setPID(int PID)
{
    //Prepare the paths that the daemon will use
    std::string playpath("/var/tmp/plebtrk/");
    if(PID)
        playpath += std::to_string(PID);
    std::string signalpath(playpath + "signal");
    playpath+= "playback.plb";

    editor::playbackpath = new char[playpath.length()];
    for(int i = 0; i < playpath.length(); i++)
        editor::playbackpath[i]=playpath.at(i);

    editor::signalpath = new char[signalpath.length()];
    for(int i = 0; i < signalpath.length(); i++)
        editor::signalpath[i]=signalpath.at(i);
}
<commit_msg>Removed utility.cpp<commit_after><|endoftext|>


<commit_before>/* cuda_wrapper/thread.hpp
 *
 * Copyright (C) 2007  Peter Colberg
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * CUDA thread management
 */

#ifndef CUDA_THREAD_HPP
#define CUDA_THREAD_HPP

#include <cuda_runtime.h>
#include <cuda_wrapper/error.hpp>

namespace cuda
{

/*
 * blocks until the device has completed all preceding requested tasks
 */
static void thread_synchronize()
{
    CUDA_CALL(cudaThreadSynchronize());
}

/*
 * cleans up all runtime-related resources associated with calling thread
 */
static void thread_exit()
{
    CUDA_CALL(cudaThreadExit());
}

}

#endif /* ! CUDA_THREAD_HPP */
<commit_msg>Inline CUDA thread management functions<commit_after>/* cuda_wrapper/thread.hpp
 *
 * Copyright (C) 2007  Peter Colberg
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * CUDA thread management
 */

#ifndef CUDA_THREAD_HPP
#define CUDA_THREAD_HPP

#include <cuda_runtime.h>
#include <cuda_wrapper/error.hpp>

namespace cuda
{

/*
 * blocks until the device has completed all preceding requested tasks
 */
__inline__ void thread_synchronize()
{
    CUDA_CALL(cudaThreadSynchronize());
}

/*
 * cleans up all runtime-related resources associated with calling thread
 */
__inline__ void thread_exit()
{
    CUDA_CALL(cudaThreadExit());
}

}

#endif /* ! CUDA_THREAD_HPP */
<|endoftext|>


<commit_before>//===-- asan_activation.cc --------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// ASan activation/deactivation logic.
//===----------------------------------------------------------------------===//

#include "asan_activation.h"
#include "asan_allocator.h"
#include "asan_flags.h"
#include "asan_internal.h"
#include "asan_poisoning.h"
#include "asan_stack.h"
#include "sanitizer_common/sanitizer_flags.h"

namespace __asan {

static struct AsanDeactivatedFlags {
  AllocatorOptions allocator_options;
  int malloc_context_size;
  bool poison_heap;
  bool coverage;
  const char *coverage_dir;

  void OverrideFromActivationFlags() {
    Flags f;
    CommonFlags cf;

    // Copy the current activation flags.
    allocator_options.CopyTo(&f, &cf);
    cf.malloc_context_size = malloc_context_size;
    f.poison_heap = poison_heap;

    // Check if activation flags need to be overriden.
    // FIXME: Add diagnostic to check that activation flags string doesn't
    // contain any other flags.
    if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) {
      cf.ParseFromString(env);
      ParseFlagsFromString(&f, env);
    }

    // Override from getprop asan.options.
    char buf[100];
    GetExtraActivationFlags(buf, sizeof(buf));
    cf.ParseFromString(buf);
    ParseFlagsFromString(&f, buf);

    allocator_options.SetFrom(&f, &cf);
    malloc_context_size = cf.malloc_context_size;
    poison_heap = f.poison_heap;
    coverage = cf.coverage;
    coverage_dir = cf.coverage_dir;
  }

  void Print() {
    Report(
        "quarantine_size_mb %d, max_redzone %d, poison_heap %d, "
        "malloc_context_size %d, alloc_dealloc_mismatch %d, "
        "allocator_may_return_null %d, coverage %d, coverage_dir %s\n",
        allocator_options.quarantine_size_mb, allocator_options.max_redzone,
        poison_heap, malloc_context_size,
        allocator_options.alloc_dealloc_mismatch,
        allocator_options.may_return_null, coverage, coverage_dir);
  }
} asan_deactivated_flags;

static bool asan_is_deactivated;

void AsanDeactivate() {
  CHECK(!asan_is_deactivated);
  VReport(1, "Deactivating ASan\n");

  // Stash runtime state.
  GetAllocatorOptions(&asan_deactivated_flags.allocator_options);
  asan_deactivated_flags.malloc_context_size = GetMallocContextSize();
  asan_deactivated_flags.poison_heap = CanPoisonMemory();
  asan_deactivated_flags.coverage = common_flags()->coverage;
  asan_deactivated_flags.coverage_dir = common_flags()->coverage_dir;

  // Deactivate the runtime.
  SetCanPoisonMemory(false);
  SetMallocContextSize(1);
  ReInitializeCoverage(false, nullptr);

  AllocatorOptions disabled = asan_deactivated_flags.allocator_options;
  disabled.quarantine_size_mb = 0;
  disabled.min_redzone = 16;  // Redzone must be at least 16 bytes long.
  disabled.max_redzone = 16;
  disabled.alloc_dealloc_mismatch = false;
  disabled.may_return_null = true;
  ReInitializeAllocator(disabled);

  asan_is_deactivated = true;
}

void AsanActivate() {
  if (!asan_is_deactivated) return;
  VReport(1, "Activating ASan\n");

  asan_deactivated_flags.OverrideFromActivationFlags();

  SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
  SetMallocContextSize(asan_deactivated_flags.malloc_context_size);
  ReInitializeCoverage(asan_deactivated_flags.coverage,
                       asan_deactivated_flags.coverage_dir);
  ReInitializeAllocator(asan_deactivated_flags.allocator_options);

  asan_is_deactivated = false;
  if (common_flags()->verbosity) {
    Report("Activated with flags:\n");
    asan_deactivated_flags.Print();
  }
}

}  // namespace __asan
<commit_msg>[asan] Fix possibly uninitialized coverage flag.<commit_after>//===-- asan_activation.cc --------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// ASan activation/deactivation logic.
//===----------------------------------------------------------------------===//

#include "asan_activation.h"
#include "asan_allocator.h"
#include "asan_flags.h"
#include "asan_internal.h"
#include "asan_poisoning.h"
#include "asan_stack.h"
#include "sanitizer_common/sanitizer_flags.h"

namespace __asan {

static struct AsanDeactivatedFlags {
  AllocatorOptions allocator_options;
  int malloc_context_size;
  bool poison_heap;
  bool coverage;
  const char *coverage_dir;

  void OverrideFromActivationFlags() {
    Flags f;
    CommonFlags cf;

    // Copy the current activation flags.
    allocator_options.CopyTo(&f, &cf);
    cf.malloc_context_size = malloc_context_size;
    f.poison_heap = poison_heap;
    cf.coverage = coverage;
    cf.coverage_dir = coverage_dir;

    // Check if activation flags need to be overriden.
    // FIXME: Add diagnostic to check that activation flags string doesn't
    // contain any other flags.
    if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) {
      cf.ParseFromString(env);
      ParseFlagsFromString(&f, env);
    }

    // Override from getprop asan.options.
    char buf[100];
    GetExtraActivationFlags(buf, sizeof(buf));
    cf.ParseFromString(buf);
    ParseFlagsFromString(&f, buf);

    allocator_options.SetFrom(&f, &cf);
    malloc_context_size = cf.malloc_context_size;
    poison_heap = f.poison_heap;
    coverage = cf.coverage;
    coverage_dir = cf.coverage_dir;
  }

  void Print() {
    Report(
        "quarantine_size_mb %d, max_redzone %d, poison_heap %d, "
        "malloc_context_size %d, alloc_dealloc_mismatch %d, "
        "allocator_may_return_null %d, coverage %d, coverage_dir %s\n",
        allocator_options.quarantine_size_mb, allocator_options.max_redzone,
        poison_heap, malloc_context_size,
        allocator_options.alloc_dealloc_mismatch,
        allocator_options.may_return_null, coverage, coverage_dir);
  }
} asan_deactivated_flags;

static bool asan_is_deactivated;

void AsanDeactivate() {
  CHECK(!asan_is_deactivated);
  VReport(1, "Deactivating ASan\n");

  // Stash runtime state.
  GetAllocatorOptions(&asan_deactivated_flags.allocator_options);
  asan_deactivated_flags.malloc_context_size = GetMallocContextSize();
  asan_deactivated_flags.poison_heap = CanPoisonMemory();
  asan_deactivated_flags.coverage = common_flags()->coverage;
  asan_deactivated_flags.coverage_dir = common_flags()->coverage_dir;

  // Deactivate the runtime.
  SetCanPoisonMemory(false);
  SetMallocContextSize(1);
  ReInitializeCoverage(false, nullptr);

  AllocatorOptions disabled = asan_deactivated_flags.allocator_options;
  disabled.quarantine_size_mb = 0;
  disabled.min_redzone = 16;  // Redzone must be at least 16 bytes long.
  disabled.max_redzone = 16;
  disabled.alloc_dealloc_mismatch = false;
  disabled.may_return_null = true;
  ReInitializeAllocator(disabled);

  asan_is_deactivated = true;
}

void AsanActivate() {
  if (!asan_is_deactivated) return;
  VReport(1, "Activating ASan\n");

  asan_deactivated_flags.OverrideFromActivationFlags();

  SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
  SetMallocContextSize(asan_deactivated_flags.malloc_context_size);
  ReInitializeCoverage(asan_deactivated_flags.coverage,
                       asan_deactivated_flags.coverage_dir);
  ReInitializeAllocator(asan_deactivated_flags.allocator_options);

  asan_is_deactivated = false;
  if (common_flags()->verbosity) {
    Report("Activated with flags:\n");
    asan_deactivated_flags.Print();
  }
}

}  // namespace __asan
<|endoftext|>


<commit_before>#include "SDL.h"
#include <vector>
#include <cstdlib>
#include <cmath>
#include <thread>
#include <iostream>
#include <complex>

using namespace std;

int MAX_ITERATIONS = 50;

double MINX = -2;
double MAXX =  1;

double MINY = -1;
double MAXY =  1;

#define WIDTH 1200
#define HEIGHT 800

#define NUM_THREADS 8

double iters[WIDTH][HEIGHT];

vector<thread> threads(NUM_THREADS);

SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Event event;

void calcRange(int minX, int maxX)
{
	for(int x = minX; x<maxX; x++) {
		for(int y = 0; y<HEIGHT; y ++) {
			complex<double> c = {double(x) / WIDTH  * (MAXX-MINX) + MINX,
								 double(y) / HEIGHT * (MAXY-MINY) + MINY};
			complex<double> z = c;
                        iters[x][y] = 0;
			for(iters[x][y] = 0; iters[x][y] < MAX_ITERATIONS && abs(z) < 4; iters[x][y]++) {
				z = z*z + c;
			}
		}
	}

}

int main()
{
	SDL_Init(SDL_INIT_VIDEO);
	window = SDL_CreateWindow("Mandelbrot", SDL_WINDOWPOS_UNDEFINED,
		SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
	renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

	bool quit = false;
	bool invalid = true;

	while (!quit)
	{
		while (SDL_PollEvent(&event) > 0) {
			if (event.type == SDL_QUIT)
				quit = true;
			if (event.type == SDL_MOUSEBUTTONDOWN && event.button.button == 1) {
					float nWidthHalf = (MAXX - MINX) / 4;
					float nHeightHalf = (MAXY - MINY) / 4;
					float nCenterX = double(event.button.x) / WIDTH  * (MAXX-MINX) + MINX;
					float nCenterY = double(event.button.y) / HEIGHT * (MAXY-MINY) + MINY;
					MINX = nCenterX - nWidthHalf;
					MAXX = nCenterX + nWidthHalf;
					MINY = nCenterY - nHeightHalf;
					MAXY = nCenterY + nHeightHalf;

					MAX_ITERATIONS += 5;

					invalid = true;
				break;
			}
		}

		if(invalid)
		{
			SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
			SDL_RenderClear(renderer);

			for(int i = 0; i<NUM_THREADS; i++)
			{
				threads[i] = thread(calcRange,
				 	i   *  WIDTH / (NUM_THREADS),
					(i+1)* WIDTH / (NUM_THREADS));
			}
			for(int i = 0; i<NUM_THREADS; i++)
			{
				threads[i].join();
			}

			for(int x = 0; x < WIDTH; x++) {
				for(int y = 0; y < HEIGHT; y++) {
					SDL_SetRenderDrawColor(renderer,
						255 * iters[x][y] / MAX_ITERATIONS,
						0,
						255 - (255 / MAX_ITERATIONS)*iters[x][y],
						255);
					SDL_RenderDrawPoint(renderer, x, y);
				}
			}

			SDL_RenderPresent(renderer);

			invalid = false;
		}
	}
}
<commit_msg>Why would anyone ever indent with tabs? o.O<commit_after>#include "SDL.h"
#include <vector>
#include <cstdlib>
#include <cmath>
#include <thread>
#include <iostream>
#include <complex>

using namespace std;

int MAX_ITERATIONS = 50;

double MINX = -2;
double MAXX =  1;

double MINY = -1;
double MAXY =  1;

#define WIDTH 1200
#define HEIGHT 800

#define NUM_THREADS 8

double iters[WIDTH][HEIGHT];

vector<thread> threads(NUM_THREADS);

SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Event event;

void calcRange(int minX, int maxX)
{
  for(int x = minX; x<maxX; x++) {
    for(int y = 0; y<HEIGHT; y ++) {
      complex<double> c = {double(x) / WIDTH  * (MAXX-MINX) + MINX,
                 double(y) / HEIGHT * (MAXY-MINY) + MINY};
      complex<double> z = c;
                        iters[x][y] = 0;
      for(iters[x][y] = 0; iters[x][y] < MAX_ITERATIONS && abs(z) < 4; iters[x][y]++) {
        z = z*z + c;
      }
    }
  }

}

int main()
{
  SDL_Init(SDL_INIT_VIDEO);
  window = SDL_CreateWindow("Mandelbrot", SDL_WINDOWPOS_UNDEFINED,
    SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
  renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

  bool quit = false;
  bool invalid = true;

  while (!quit)
  {
    while (SDL_PollEvent(&event) > 0) {
      if (event.type == SDL_QUIT)
        quit = true;
      if (event.type == SDL_MOUSEBUTTONDOWN && event.button.button == 1) {
          float nWidthHalf = (MAXX - MINX) / 4;
          float nHeightHalf = (MAXY - MINY) / 4;
          float nCenterX = double(event.button.x) / WIDTH  * (MAXX-MINX) + MINX;
          float nCenterY = double(event.button.y) / HEIGHT * (MAXY-MINY) + MINY;
          MINX = nCenterX - nWidthHalf;
          MAXX = nCenterX + nWidthHalf;
          MINY = nCenterY - nHeightHalf;
          MAXY = nCenterY + nHeightHalf;

          MAX_ITERATIONS += 5;

          invalid = true;
        break;
      }
    }

    if(invalid)
    {
      SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
      SDL_RenderClear(renderer);

      for(int i = 0; i<NUM_THREADS; i++)
      {
        threads[i] = thread(calcRange,
           i   *  WIDTH / (NUM_THREADS),
          (i+1)* WIDTH / (NUM_THREADS));
      }
      for(int i = 0; i<NUM_THREADS; i++)
      {
        threads[i].join();
      }

      for(int x = 0; x < WIDTH; x++) {
        for(int y = 0; y < HEIGHT; y++) {
          SDL_SetRenderDrawColor(renderer,
            255 * iters[x][y] / MAX_ITERATIONS,
            0,
            255 - (255 / MAX_ITERATIONS)*iters[x][y],
            255);
          SDL_RenderDrawPoint(renderer, x, y);
        }
      }

      SDL_RenderPresent(renderer);

      invalid = false;
    }
  }
}
<|endoftext|>


<commit_before>/*
 *   Copyright 2012 Coherent Theory LLC
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "assethandler.h"

#include <QDebug>
#include <QDir>
#include <QLibraryInfo>
#include <QPluginLoader>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>

#include "installjob.h"
#include "assethandlerfactory.h"

namespace Bodega
{

class AssetHandler::Private
{
public:
    Private()
        : ops(0),
          ready(false)
    {
    }

    void initUpdateDb() {
        if (updateDb.isOpen()) {
            return;
        }

        updateDb = AssetHandler::updateDatabase();
    }

    AssetOperations *ops;
    bool ready;
    QSqlDatabase updateDb;
};

AssetHandler::AssetHandler(QObject *parent)
    : QObject(parent),
      d(new Private)
{
}

AssetHandler::~AssetHandler()
{
    if (d->updateDb.isOpen()) {
        d->updateDb.close();
    }

    delete d;
}

void AssetHandler::init()
{
    //Base implementation does nothing
}

AssetOperations *AssetHandler::operations() const
{
    return d->ops;
}

QString AssetHandler::launchText() const
{
    return QString();
}

bool AssetHandler::isInstalled() const
{
    return false;
}

Bodega::InstallJob *AssetHandler::install(QNetworkReply *reply, Session *session)
{
    return new InstallJob(reply, session);
}

Bodega::UninstallJob *AssetHandler::uninstall(Session *session)
{
    //return new UninstallJob();
    return 0;
}

AssetHandler *AssetHandler::create(const QString &type, AssetOperations *parent)
{
    QString plugin;
    //FIXME: a better registration system is badly needed
    if (type == QLatin1String("application/epub+zip") ||
        type == QLatin1String("application/pdf")) {
        plugin = QLatin1String("epub");
    } else if (type == QLatin1String("application/x-plasma")) {
        plugin = QLatin1String("plasmoid");
    } else if (type == QLatin1String("application/x-desktop-wallpaper")) {
        plugin = QLatin1String("wallpaper");
    } else if (type == QLatin1String("application/x-rpm")) {
        plugin = QLatin1String("rpm");
    }

    AssetHandler * handler = 0;

    if (!plugin.isEmpty()) {
        QList<QByteArray> paths = qgetenv("QT_PLUGIN_PATH").split(':');
        paths.removeAll(QByteArray());
        paths.append(QLibraryInfo::location(QLibraryInfo::PluginsPath).toLocal8Bit());

        foreach (const QByteArray& path, paths) {
            QDir pluginsDir(QString::fromLatin1(path + "/bodegaassethandlers/"));
            //FIXME: the .so is non-portable. need some ifdef's here if this is to work on non-UNIX.
            //remind me why QPluginLoader doesn't do this when QLibrary does?
            const QString candidatePath = pluginsDir.absoluteFilePath(QLatin1String("lib") + plugin + QLatin1String("handlerplugin.so"));
            if(QFile::exists(candidatePath)) {
                QPluginLoader pluginLoader(candidatePath);

                QObject *plugin = pluginLoader.instance();
                if (plugin) {
                    Bodega::AssetHandlerFactory *factory = dynamic_cast<Bodega::AssetHandlerFactory *>(plugin);
                    if (factory) {
                        handler = factory->createHandler();
                        Q_ASSERT(handler);
                    } else {
                        qWarning() << "Could not instanciate the handler using" << candidatePath;
                    }
                    break;
                } else {
                    qWarning() << "Plugin load failed" << pluginLoader.errorString() << candidatePath;
                }
            }
        }
    }

    if (!handler) {
        handler = new AssetHandler;
    }

    handler->setParent(parent);
    handler->d->ops = parent;
    handler->init();
    return handler;
}

void AssetHandler::launch()
{
}

void AssetHandler::registerForUpdates(Bodega::NetworkJob *job)
{
    if (!job || job->failed()) {
        return;
    }

    if (!d->ops) {
        return;
    }

    const QString id = d->ops->assetInfo().id;
    if (id.isEmpty()) {
        return;
    }

    d->initUpdateDb();

    QSqlQuery query(d->updateDb);
    query.prepare(QLatin1String("INSERT INTO assets (warehouse, store, asset, version) VALUES (:warehouse, :store, :asset, :version)"));
    query.bindValue(QLatin1String(":warehouse"), job->session()->baseUrl());
    query.bindValue(QLatin1String(":store"), job->session()->storeId());
    query.bindValue(QLatin1String(":asset"), id);
    query.bindValue(QLatin1String(":version"), d->ops->assetInfo().version);
    if (!query.exec()) {
        qDebug() << "Insertion of update failed:" << query.lastError();
    }
}

void AssetHandler::unregisterForUpdates(Bodega::NetworkJob *job)
{
    if (job && job->failed()) {
        return;
    }

    if (!d->ops) {
        return;
    }

    const QString id = d->ops->assetInfo().id;
    if (id.isEmpty()) {
        return;
    }

    d->initUpdateDb();

    QSqlQuery query(d->updateDb);
    query.prepare(QLatin1String("DELETE FROM assets WHERE warehouse = :warehouse AND store = :store AND asset = :asset"));
    query.bindValue(QLatin1String(":warehouse"), job->session()->baseUrl());
    query.bindValue(QLatin1String(":store"), job->session()->storeId());
    query.bindValue(QLatin1String(":asset"), id);
    if (!query.exec()) {
        qDebug() << "Insertion of update failed:" << query.lastError();
    }
}

void AssetHandler::setReady(bool isReady)
{
    d->ready = isReady;
    if (isReady) {
        emit ready();
    }
}

bool AssetHandler::isReady() const
{
    return d->ready;
}

QSqlDatabase AssetHandler::updateDatabase()
{
    const QString dbConnectionName = QLatin1String("BODEGA_UPDATES");
    bool initTables = false;

    QSqlDatabase updateDb = QSqlDatabase::database(dbConnectionName);

    if (!updateDb.isValid()) {
        //FIXME QT5: use QStandardDirs for this
        QString updateDbPath = QDir::homePath() + QLatin1String("/.local/share/bodega/");
        if (!QFile::exists(updateDbPath)) {
            QDir dir;
            dir.mkpath(updateDbPath);
        }

        updateDbPath.append(QLatin1String("assets.db"));
        initTables = !QFile::exists(updateDbPath);
        updateDb = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"));
        updateDb.setDatabaseName(updateDbPath);
    }

    if (!updateDb.isOpen()) {
        if (!updateDb.open()) {
            qDebug() << "failed to open update db" << updateDb.lastError();
        }

        if (initTables) {
            QSqlQuery query(updateDb);
            query.exec(QLatin1String("CREATE TABLE assets (store text, warehouse text, asset text, version text, checked bool default false)"));
        }
    }

    return updateDb;
}

} // namespace Bodega

#include "assethandler.moc"

<commit_msg>add a config table to store last check time, version of db and spiffy up assets table<commit_after>/*
 *   Copyright 2012 Coherent Theory LLC
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "assethandler.h"

#include <QDebug>
#include <QDir>
#include <QLibraryInfo>
#include <QPluginLoader>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>

#include "installjob.h"
#include "assethandlerfactory.h"

namespace Bodega
{

class AssetHandler::Private
{
public:
    Private()
        : ops(0),
          ready(false)
    {
    }

    void initUpdateDb() {
        if (updateDb.isOpen()) {
            return;
        }

        updateDb = AssetHandler::updateDatabase();
    }

    AssetOperations *ops;
    bool ready;
    QSqlDatabase updateDb;
};

AssetHandler::AssetHandler(QObject *parent)
    : QObject(parent),
      d(new Private)
{
}

AssetHandler::~AssetHandler()
{
    if (d->updateDb.isOpen()) {
        d->updateDb.close();
    }

    delete d;
}

void AssetHandler::init()
{
    //Base implementation does nothing
}

AssetOperations *AssetHandler::operations() const
{
    return d->ops;
}

QString AssetHandler::launchText() const
{
    return QString();
}

bool AssetHandler::isInstalled() const
{
    return false;
}

Bodega::InstallJob *AssetHandler::install(QNetworkReply *reply, Session *session)
{
    return new InstallJob(reply, session);
}

Bodega::UninstallJob *AssetHandler::uninstall(Session *session)
{
    //return new UninstallJob();
    return 0;
}

AssetHandler *AssetHandler::create(const QString &type, AssetOperations *parent)
{
    QString plugin;
    //FIXME: a better registration system is badly needed
    if (type == QLatin1String("application/epub+zip") ||
        type == QLatin1String("application/pdf")) {
        plugin = QLatin1String("epub");
    } else if (type == QLatin1String("application/x-plasma")) {
        plugin = QLatin1String("plasmoid");
    } else if (type == QLatin1String("application/x-desktop-wallpaper")) {
        plugin = QLatin1String("wallpaper");
    } else if (type == QLatin1String("application/x-rpm")) {
        plugin = QLatin1String("rpm");
    }

    AssetHandler * handler = 0;

    if (!plugin.isEmpty()) {
        QList<QByteArray> paths = qgetenv("QT_PLUGIN_PATH").split(':');
        paths.removeAll(QByteArray());
        paths.append(QLibraryInfo::location(QLibraryInfo::PluginsPath).toLocal8Bit());

        foreach (const QByteArray& path, paths) {
            QDir pluginsDir(QString::fromLatin1(path + "/bodegaassethandlers/"));
            //FIXME: the .so is non-portable. need some ifdef's here if this is to work on non-UNIX.
            //remind me why QPluginLoader doesn't do this when QLibrary does?
            const QString candidatePath = pluginsDir.absoluteFilePath(QLatin1String("lib") + plugin + QLatin1String("handlerplugin.so"));
            if(QFile::exists(candidatePath)) {
                QPluginLoader pluginLoader(candidatePath);

                QObject *plugin = pluginLoader.instance();
                if (plugin) {
                    Bodega::AssetHandlerFactory *factory = dynamic_cast<Bodega::AssetHandlerFactory *>(plugin);
                    if (factory) {
                        handler = factory->createHandler();
                        Q_ASSERT(handler);
                    } else {
                        qWarning() << "Could not instanciate the handler using" << candidatePath;
                    }
                    break;
                } else {
                    qWarning() << "Plugin load failed" << pluginLoader.errorString() << candidatePath;
                }
            }
        }
    }

    if (!handler) {
        handler = new AssetHandler;
    }

    handler->setParent(parent);
    handler->d->ops = parent;
    handler->init();
    return handler;
}

void AssetHandler::launch()
{
}

void AssetHandler::registerForUpdates(Bodega::NetworkJob *job)
{
    if (!job || job->failed()) {
        return;
    }

    if (!d->ops) {
        return;
    }

    const QString id = d->ops->assetInfo().id;
    if (id.isEmpty()) {
        return;
    }

    d->initUpdateDb();

    QSqlQuery query(d->updateDb);
    query.prepare(QLatin1String("INSERT INTO assets (warehouse, store, asset, created) VALUES (:warehouse, :store, :asset, :created)"));
    query.bindValue(QLatin1String(":warehouse"), job->session()->baseUrl());
    query.bindValue(QLatin1String(":store"), job->session()->storeId());
    query.bindValue(QLatin1String(":asset"), id);
    query.bindValue(QLatin1String(":created"), d->ops->assetInfo().created.toString(Qt::ISODate));
    if (!query.exec()) {
        qDebug() << "Insertion of update failed:" << query.lastError();
    }
}

void AssetHandler::unregisterForUpdates(Bodega::NetworkJob *job)
{
    if (job && job->failed()) {
        return;
    }

    if (!d->ops) {
        return;
    }

    const QString id = d->ops->assetInfo().id;
    if (id.isEmpty()) {
        return;
    }

    d->initUpdateDb();

    QSqlQuery query(d->updateDb);
    query.prepare(QLatin1String("DELETE FROM assets WHERE warehouse = :warehouse AND store = :store AND asset = :asset"));
    query.bindValue(QLatin1String(":warehouse"), job->session()->baseUrl());
    query.bindValue(QLatin1String(":store"), job->session()->storeId());
    query.bindValue(QLatin1String(":asset"), id);
    if (!query.exec()) {
        qDebug() << "Insertion of update failed:" << query.lastError();
    }
}

void AssetHandler::setReady(bool isReady)
{
    d->ready = isReady;
    if (isReady) {
        emit ready();
    }
}

bool AssetHandler::isReady() const
{
    return d->ready;
}

QSqlDatabase AssetHandler::updateDatabase()
{
    const QString dbConnectionName = QLatin1String("BODEGA_UPDATES");
    bool initTables = false;

    QSqlDatabase updateDb = QSqlDatabase::database(dbConnectionName);

    if (!updateDb.isValid()) {
        //FIXME QT5: use QStandardDirs for this
        QString updateDbPath = QDir::homePath() + QLatin1String("/.local/share/bodega/");
        if (!QFile::exists(updateDbPath)) {
            QDir dir;
            dir.mkpath(updateDbPath);
        }

        updateDbPath.append(QLatin1String("assets.db"));
        initTables = !QFile::exists(updateDbPath);
        updateDb = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"));
        updateDb.setDatabaseName(updateDbPath);
    }

    if (!updateDb.isOpen()) {
        if (!updateDb.open()) {
            qDebug() << "failed to open update db" << updateDb.lastError();
        }

        if (initTables) {
            QSqlQuery query(updateDb);
            query.exec(QLatin1String("CREATE TABLE assets (store text, warehouse text, asset text, created text, updated bool default false, checked bool default false)"));
            query.exec(QLatin1String("CREATE TABLE config (key text, val int)"));
            query.exec(QLatin1String("INSERT INTO config (key, val) VALUES('lastcheck', strftime('%s', 'now'))"));
            query.exec(QLatin1String("INSERT INTO config (key, val) VALUES('version', 1)"));
        }
    }

    return updateDb;
}

} // namespace Bodega

#include "assethandler.moc"

<|endoftext|>


<commit_before>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// Planet - An atmospheric code for planetary bodies, adapted to Titan
//
// Copyright (C) 2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License 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. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

//Antioch
#include "antioch/vector_utils_decl.h"
#include "antioch/cmath_shims.h"
#include "antioch/vector_utils.h"
//Planet
#include "planet/atmospheric_temperature.h"
//C++
#include <iostream>
#include <fstream>
#include <iomanip>
#include <limits>
#include <string>
#include <vector>

template<typename Scalar>
int check(const Scalar &test, const Scalar &ref, const Scalar &tol, const std::string &model)
{
  if(Antioch::ant_abs(test - ref)/ref > tol)
  {
     std::cout << std::scientific << std::setprecision(20)
               << "Error in binary diffusion calculations" << std::endl
               << "model is " << model << std::endl
               << "calculated coefficient = " << test << std::endl
               << "solution = " << ref << std::endl
               << "relative error = " << Antioch::ant_abs(test - ref)/ref << std::endl
               << "tolerance = " << tol << std::endl;
     return 1;
  }
  return 0;
}

template<typename Scalar>
Scalar electron_temperature(const Scalar &alt)
{
  if(alt < 900.L)
  {
     return 180.L;
  }else if(alt < 1400.L)
  {
     return 180.L + (alt - 900.L)/500.L * (1150.L - 180.L);
  }else
  {
     return 1150.L + (alt - 1400.L)/10.L;
  }

  return 0;
}

template<typename Scalar>
Scalar delectron_temperature(const Scalar &alt)
{
  if(alt < 900.L)
  {
     return 0.L;
  }else if(alt < 1400.L)
  {
     return 2e-3L;
  }else
  {
     return 0.1L;
  }

  return 0;
}

template<typename Scalar, typename VectorScalar = std::vector<Scalar> >
void read_temperature(VectorScalar &T0, VectorScalar &Tz, const std::string &file)
{
  T0.clear();
  Tz.clear();
  std::string line;
  std::ifstream temp(file);
  getline(temp,line);
  while(!temp.eof())
  {
     Scalar t(0.),tz(0.);
     temp >> t >> tz;
     if(temp.good())
     {
       T0.push_back(t);
       Tz.push_back(tz);
     }
  }
  temp.close();
  return;
}

template<typename Scalar>
int tester(const std::string & input_file)
{
//temperature
  std::vector<Scalar> T0,Tz;
  read_temperature<Scalar>(T0,Tz,input_file);

  gsl_interp_accel * acc = gsl_interp_accel_alloc();
  gsl_spline       * spline = gsl_spline_alloc(gsl_interp_cspline, T0.size());

  // GLS takes only double, raaaaahhhh
  std::vector<double> gsl_x_point(T0.size(),0);
  std::vector<double> gsl_y_point(T0.size(),0);
  for(unsigned int i = 0; i < T0.size(); i++)
  {
    gsl_x_point[i] = (const double)Tz[i];
    gsl_y_point[i] = (const double)T0[i];
  }

  const double * x = &gsl_x_point[0];
  const double * y = &gsl_y_point[0];

  gsl_spline_init(spline, x, y, T0.size());

  Planet::AtmosphericTemperature<Scalar,std::vector<Scalar> > temperature(Tz,T0); //neutral, ionic, altitude

  int return_flag(0);
  const Scalar tol = std::numeric_limits<Scalar>::epsilon() * 100.;

  for(unsigned int iz = 0; iz < T0.size() - 1; iz++)
  {
      Scalar z = (T0[iz] + T0[iz + 1]) / Scalar(2.L);
      Scalar neu_temp  = gsl_spline_eval(spline,z,acc);
      Scalar neu_dtemp = gsl_spline_eval_deriv(spline,z,acc);
      Scalar ion_temp  = gsl_spline_eval(spline,z,acc);
      Scalar ion_dtemp = gsl_spline_eval_deriv(spline,z,acc);
      Scalar e_temp    = electron_temperature(z);
      Scalar de_dtemp  = delectron_temperature(z);

      return_flag = check(temperature.neutral_temperature(z),        neu_temp,  tol, "neutral temperature")               ||
                    check(temperature.dneutral_temperature_dz(z),    neu_dtemp, tol, "neutral temperature differentiate") ||
                    check(temperature.ionic_temperature(z),          ion_temp,  tol, "ionic temperature")                 ||
                    check(temperature.dionic_temperature_dz(z),      ion_dtemp, tol, "ionic temperature differentiate")   ||
                    check(temperature.electronic_temperature(z),     e_temp,    tol, "electron temperature")              ||
                    check(temperature.delectronic_temperature_dz(z), de_dtemp,  tol, "electron temperature differentiate") ||
                    return_flag;
  }

  gsl_spline_free(spline);
  gsl_interp_accel_free(acc);

  return return_flag;
}

int main(int argc, char** argv)
{
  // Check command line count.
  if( argc < 2 )
    {
      // TODO: Need more consistent error handling.
      std::cerr << "Error: Must specify input file." << std::endl;
      antioch_error();
    }

  return (tester<float>(std::string(argv[1])) ||
          tester<double>(std::string(argv[1])) ||
          tester<long double>(std::string(argv[1])));
}
<commit_msg>range of altitude for temperature<commit_after>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// Planet - An atmospheric code for planetary bodies, adapted to Titan
//
// Copyright (C) 2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License 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. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

//Antioch
#include "antioch/vector_utils_decl.h"
#include "antioch/cmath_shims.h"
#include "antioch/vector_utils.h"
//Planet
#include "planet/atmospheric_temperature.h"
//C++
#include <iostream>
#include <fstream>
#include <iomanip>
#include <limits>
#include <string>
#include <vector>

template<typename Scalar>
int check(const Scalar &test, const Scalar &ref, const Scalar &tol, const std::string &model)
{
  if(Antioch::ant_abs(test - ref)/ref > tol)
  {
     std::cout << std::scientific << std::setprecision(20)
               << "Error in binary diffusion calculations" << std::endl
               << "model is " << model << std::endl
               << "calculated coefficient = " << test << std::endl
               << "solution = " << ref << std::endl
               << "relative error = " << Antioch::ant_abs(test - ref)/ref << std::endl
               << "tolerance = " << tol << std::endl;
     return 1;
  }
  return 0;
}

template<typename Scalar>
Scalar electron_temperature(const Scalar &alt)
{
  if(alt < 900.L)
  {
     return 180.L;
  }else if(alt < 1400.L)
  {
     return 180.L + (alt - 900.L)/500.L * (1150.L - 180.L);
  }else
  {
     return 1150.L + (alt - 1400.L)/10.L;
  }

  return 0;
}

template<typename Scalar>
Scalar delectron_temperature(const Scalar &alt)
{
  if(alt < 900.L)
  {
     return 0.L;
  }else if(alt < 1400.L)
  {
     return 2e-3L;
  }else
  {
     return 0.1L;
  }

  return 0;
}

template<typename Scalar, typename VectorScalar = std::vector<Scalar> >
void read_temperature(VectorScalar &T0, VectorScalar &Tz, const std::string &file)
{
  T0.clear();
  Tz.clear();
  std::string line;
  std::ifstream temp(file);
  getline(temp,line);
  while(!temp.eof())
  {
     Scalar t(0.),tz(0.);
     temp >> t >> tz;
     if(temp.good())
     {
       T0.push_back(t);
       Tz.push_back(tz);
     }
  }
  temp.close();
  return;
}

template<typename Scalar>
int tester(const std::string & input_file)
{
//temperature
  std::vector<Scalar> T0,Tz;
  read_temperature<Scalar>(T0,Tz,input_file);

  gsl_interp_accel * acc = gsl_interp_accel_alloc();
  gsl_spline       * spline = gsl_spline_alloc(gsl_interp_cspline, T0.size());

  // GLS takes only double, raaaaahhhh
  std::vector<double> gsl_x_point(T0.size(),0);
  std::vector<double> gsl_y_point(T0.size(),0);
  for(unsigned int i = 0; i < T0.size(); i++)
  {
    gsl_x_point[i] = (const double)Tz[i];
    gsl_y_point[i] = (const double)T0[i];
  }

  const double * x = &gsl_x_point[0];
  const double * y = &gsl_y_point[0];

  gsl_spline_init(spline, x, y, T0.size());

  Planet::AtmosphericTemperature<Scalar,std::vector<Scalar> > temperature(Tz,T0); //neutral, ionic, altitude

  int return_flag(0);
  const Scalar tol = (std::numeric_limits<Scalar>::epsilon() * 100. < 6e-17)?6e-17:
                      std::numeric_limits<Scalar>::epsilon() * 100.;

  for(Scalar z = 600.; z < 1401.; z += 10)
  {
      Scalar neu_temp  = gsl_spline_eval(spline,z,acc);
      Scalar neu_dtemp = gsl_spline_eval_deriv(spline,z,acc);
      Scalar ion_temp  = gsl_spline_eval(spline,z,acc);
      Scalar ion_dtemp = gsl_spline_eval_deriv(spline,z,acc);
      Scalar e_temp    = electron_temperature(z);
      Scalar de_dtemp  = delectron_temperature(z);

      return_flag = check(temperature.neutral_temperature(z),        neu_temp,  tol, "neutral temperature")               ||
                    check(temperature.dneutral_temperature_dz(z),    neu_dtemp, tol, "neutral temperature differentiate") ||
                    check(temperature.ionic_temperature(z),          ion_temp,  tol, "ionic temperature")                 ||
                    check(temperature.dionic_temperature_dz(z),      ion_dtemp, tol, "ionic temperature differentiate")   ||
                    check(temperature.electronic_temperature(z),     e_temp,    tol, "electron temperature")              ||
                    check(temperature.delectronic_temperature_dz(z), de_dtemp,  tol, "electron temperature differentiate") ||
                    return_flag;
  }

  gsl_spline_free(spline);
  gsl_interp_accel_free(acc);

  return return_flag;
}

int main(int argc, char** argv)
{
  // Check command line count.
  if( argc < 2 )
    {
      // TODO: Need more consistent error handling.
      std::cerr << "Error: Must specify input file." << std::endl;
      antioch_error();
    }

  return (tester<float>(std::string(argv[1])) ||
          tester<double>(std::string(argv[1])) ||
          tester<long double>(std::string(argv[1])));
}
<|endoftext|>


<commit_before>/*
 *   Copyright 2012 Coherent Theory LLC
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "historymodel.h"

#include "session.h"
#include "networkjob.h"

#include <QtCore/QVariant>
#include <QtCore/QDebug>
#include <QtCore/QMetaEnum>

namespace Bodega
{

static const int DEFAULT_PAGE_SIZE = 50;

class HistoryModel::Private {
public:
    Private(HistoryModel *parent);
    void historyJobFinished(Bodega::NetworkJob *job);
    void reloadFromNetwork();

    HistoryModel *q;
    Session *session;
    QList<QVariantMap> history;
    bool hasMore;
};

HistoryModel::Private::Private(HistoryModel *parent)
    : q(parent),
      session(0),
      hasMore(false)
{
}

void HistoryModel::Private::historyJobFinished(Bodega::NetworkJob *job)
{
    if (job->failed()) {
        return;
    }

    const QVariantMap json = job->parsedJson();
    if (json.isEmpty() || !json.contains(QLatin1String("history"))) {
        return;
    }

    hasMore = json[QLatin1String("hasMoreHistory")].toBool();
    const QVariantList historyData = json[QLatin1String("history")].toList();
    const int count = historyData.count();
    int offset = json[QLatin1String("offset")].toInt();
    const int end = qMax(offset, count + offset - 1);
    q->beginInsertRows(QModelIndex(), offset, end);

    // fill any blanks
    while (history.size() < offset) {
        history.append(QVariantMap());
    }

    // insert the actual values we retrieved with this job
    for (QVariantList::const_iterator itr = historyData.constBegin(); itr != historyData.constEnd(); ++itr) {
        history.insert(offset, itr->toMap());
        ++offset;
    }

    q->endInsertRows();
}

void HistoryModel::Private::reloadFromNetwork()
{
    if (!session || !session->isAuthenticated()) {
        return;
    }

    //reset topnode, remove all the contents of the model
    q->beginResetModel();
    hasMore = false;
    history.clear();
    q->endResetModel();

    NetworkJob *historyJob = session->history(0, DEFAULT_PAGE_SIZE);
    connect(historyJob, SIGNAL(jobFinished(Bodega::NetworkJob *)),
            q, SLOT(historyJobFinished(Bodega::NetworkJob *)));
}

HistoryModel::HistoryModel(QObject *parent)
    : QAbstractItemModel(parent),
      d(new Private(this))
{
    // set the role names based on the values of the DisplayRoles enum for
    //  the sake of QML
    QHash<int, QByteArray> roles;
    roles.insert(Qt::DisplayRole, "DisplayRole");
    QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("DisplayRoles"));
    for (int i = 0; i < e.keyCount(); ++i) {
        roles.insert(e.value(i), e.key(i));
    }
    setRoleNames(roles);
}

HistoryModel::~HistoryModel()
{
    delete d;
}

bool HistoryModel::canFetchMore(const QModelIndex &parent) const
{
    if (parent.isValid()) {
        return false;
    }

    return d->hasMore;
}

int HistoryModel::columnCount(const QModelIndex &parent) const
{
    return 1;
}

QVariant HistoryModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() >= d->history.count()) {
        return QVariant();
    }

    switch (role) {
        case Qt::DisplayRole: {
            const QString category = d->history[index.row()][QLatin1String("category")].toString();
            const QString what = d->history[index.row()][QLatin1String("what")].toString();
            if (category == QLatin1String("Download")) {
                return tr("Downloaded %1").arg(what);
            } else if (category == QLatin1String("Purchase")) {
                return tr("Purchased %1").arg(what);
            } else if (category == QLatin1String("Points")) {
                return tr("Added %1 points").arg(what);
            } else {
                return QString();
            }
        }
        case DateRole:
            return d->history[index.row()][QLatin1String("date")].toDateTime().toString(Qt::SystemLocaleShortDate);
        case DescriptionRole:
            return d->history[index.row()][QLatin1String("comment")];
        default:
            return QVariant();
    }
}

void HistoryModel::fetchMore(const QModelIndex &parent)
{
    if (!parent.isValid() || !d->session || !canFetchMore(parent) ||
        !d->session->isAuthenticated()) {
        return;
    }

    NetworkJob *job = d->session->history(d->history.count(), DEFAULT_PAGE_SIZE);
    connect(job, SIGNAL(jobFinished(Bodega::NetworkJob *)),
            this, SLOT(historyJobFinished(Bodega::NetworkJob *)));
}

Qt::ItemFlags HistoryModel::flags(const QModelIndex &index) const
{
    if (index.isValid()) {
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    } else {
        return Qt::NoItemFlags;
    }
}

bool HistoryModel::hasChildren(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return false;
}

QVariant HistoryModel::headerData(int section, Qt::Orientation orientation,
                           int role) const
{
    return QVariant();
}

QModelIndex HistoryModel::index(int row, int column, const QModelIndex &parent) const
{
    if (column > 0) {
        return QModelIndex();
    }

    if (row < 0 || row >= d->history.count()) {
        return QModelIndex();
    }

    return createIndex(row, column);
}

QMap<int, QVariant> HistoryModel::itemData(const QModelIndex &index) const
{
    return QMap<int, QVariant>();
}

QModelIndex HistoryModel::parent(const QModelIndex &index) const
{
    return QModelIndex();
}

int HistoryModel::rowCount(const QModelIndex &parent) const
{
    return d->history.size();
}

void HistoryModel::setSession(Session *session)
{
    if (session == d->session) {
        return;
    }

    if (d->session) {
        //not connected directly, so disconnect everything
        d->session->disconnect(this);
    }

    d->session = session;

    if (!d->session) {
        return;
    }

    connect(d->session, SIGNAL(authenticated(bool)),
            this, SLOT(reloadFromNetwork()));

    if (d->session->isAuthenticated()) {
        d->reloadFromNetwork();
    }
}

Session *HistoryModel::session() const
{
    return d->session;
}

}

#include "historymodel.moc"
<commit_msg>show a "no history" entry when there is no history. voila<commit_after>/*
 *   Copyright 2012 Coherent Theory LLC
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "historymodel.h"

#include "session.h"
#include "networkjob.h"

#include <QtCore/QVariant>
#include <QtCore/QDebug>
#include <QtCore/QMetaEnum>

namespace Bodega
{

static const int DEFAULT_PAGE_SIZE = 50;

class HistoryModel::Private {
public:
    Private(HistoryModel *parent);
    void historyJobFinished(Bodega::NetworkJob *job);
    void reloadFromNetwork();
    void insertNoHistoryEntry();

    HistoryModel *q;
    Session *session;
    QList<QVariantMap> history;
    bool hasMore;
};

HistoryModel::Private::Private(HistoryModel *parent)
    : q(parent),
      session(0),
      hasMore(false)
{
}

void HistoryModel::Private::insertNoHistoryEntry()
{
    q->beginInsertRows(QModelIndex(), 0, 0);
    QVariantMap noHistory;
    noHistory.insert(QLatin1String("category"), QString(QLatin1String("Information")));
    noHistory.insert(QLatin1String("what"), tr("No events for this account. Go download something interesting! :)"));
    noHistory.insert(QLatin1String("date"), QDateTime::currentDateTime());
    noHistory.insert(QLatin1String("comment"), QString());

    history.insert(0, noHistory);
    q->endInsertRows();
}

void HistoryModel::Private::historyJobFinished(Bodega::NetworkJob *job)
{
    if (job->failed()) {
        if (history.isEmpty()) {
            insertNoHistoryEntry();
        }
        return;
    }

    const QVariantMap json = job->parsedJson();
    if (json.isEmpty() || !json.contains(QLatin1String("history"))) {
        if (history.isEmpty()) {
            insertNoHistoryEntry();
        }
        return;
    }

    hasMore = json[QLatin1String("hasMoreHistory")].toBool();
    const QVariantList historyData = json[QLatin1String("history")].toList();
    const int count = historyData.count();
    if (count < 1 && !hasMore && history.isEmpty()) {
        insertNoHistoryEntry();
        return;
    }

    int offset = json[QLatin1String("offset")].toInt();
    const int end = qMax(offset, count + offset - 1);
    q->beginInsertRows(QModelIndex(), offset, end);

    // fill any blanks
    while (history.size() < offset) {
        history.append(QVariantMap());
    }

    // insert the actual values we retrieved with this job
    for (QVariantList::const_iterator itr = historyData.constBegin(); itr != historyData.constEnd(); ++itr) {
        history.insert(offset, itr->toMap());
        ++offset;
    }

    q->endInsertRows();
}

void HistoryModel::Private::reloadFromNetwork()
{
    if (!session || !session->isAuthenticated()) {
        return;
    }

    //reset topnode, remove all the contents of the model
    q->beginResetModel();
    hasMore = false;
    history.clear();
    q->endResetModel();

    NetworkJob *historyJob = session->history(0, DEFAULT_PAGE_SIZE);
    connect(historyJob, SIGNAL(jobFinished(Bodega::NetworkJob *)),
            q, SLOT(historyJobFinished(Bodega::NetworkJob *)));
}

HistoryModel::HistoryModel(QObject *parent)
    : QAbstractItemModel(parent),
      d(new Private(this))
{
    // set the role names based on the values of the DisplayRoles enum for
    //  the sake of QML
    QHash<int, QByteArray> roles;
    roles.insert(Qt::DisplayRole, "DisplayRole");
    QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("DisplayRoles"));
    for (int i = 0; i < e.keyCount(); ++i) {
        roles.insert(e.value(i), e.key(i));
    }
    setRoleNames(roles);
}

HistoryModel::~HistoryModel()
{
    delete d;
}

bool HistoryModel::canFetchMore(const QModelIndex &parent) const
{
    if (parent.isValid()) {
        return false;
    }

    return d->hasMore;
}

int HistoryModel::columnCount(const QModelIndex &parent) const
{
    return 1;
}

QVariant HistoryModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() >= d->history.count()) {
        return QVariant();
    }

    switch (role) {
        case Qt::DisplayRole: {
            const QString category = d->history[index.row()][QLatin1String("category")].toString();
            const QString what = d->history[index.row()][QLatin1String("what")].toString();
            if (category == QLatin1String("Information")) {
                return what;
            } else if (category == QLatin1String("Download")) {
                return tr("Downloaded %1").arg(what);
            } else if (category == QLatin1String("Purchase")) {
                return tr("Purchased %1").arg(what);
            } else if (category == QLatin1String("Points")) {
                return tr("Added %1 points").arg(what);
            } else {
                return QString();
            }
        }
        case DateRole:
            return d->history[index.row()][QLatin1String("date")].toDateTime().toString(Qt::SystemLocaleShortDate);
        case DescriptionRole:
            return d->history[index.row()][QLatin1String("comment")];
        default:
            return QVariant();
    }
}

void HistoryModel::fetchMore(const QModelIndex &parent)
{
    if (!parent.isValid() || !d->session || !canFetchMore(parent) ||
        !d->session->isAuthenticated()) {
        return;
    }

    NetworkJob *job = d->session->history(d->history.count(), DEFAULT_PAGE_SIZE);
    connect(job, SIGNAL(jobFinished(Bodega::NetworkJob *)),
            this, SLOT(historyJobFinished(Bodega::NetworkJob *)));
}

Qt::ItemFlags HistoryModel::flags(const QModelIndex &index) const
{
    if (index.isValid()) {
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    } else {
        return Qt::NoItemFlags;
    }
}

bool HistoryModel::hasChildren(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return false;
}

QVariant HistoryModel::headerData(int section, Qt::Orientation orientation,
                           int role) const
{
    return QVariant();
}

QModelIndex HistoryModel::index(int row, int column, const QModelIndex &parent) const
{
    if (column > 0) {
        return QModelIndex();
    }

    if (row < 0 || row >= d->history.count()) {
        return QModelIndex();
    }

    return createIndex(row, column);
}

QMap<int, QVariant> HistoryModel::itemData(const QModelIndex &index) const
{
    return QMap<int, QVariant>();
}

QModelIndex HistoryModel::parent(const QModelIndex &index) const
{
    return QModelIndex();
}

int HistoryModel::rowCount(const QModelIndex &parent) const
{
    return d->history.size();
}

void HistoryModel::setSession(Session *session)
{
    if (session == d->session) {
        return;
    }

    if (d->session) {
        //not connected directly, so disconnect everything
        d->session->disconnect(this);
    }

    d->session = session;

    if (!d->session) {
        return;
    }

    connect(d->session, SIGNAL(authenticated(bool)),
            this, SLOT(reloadFromNetwork()));

    if (d->session->isAuthenticated()) {
        d->reloadFromNetwork();
    }
}

Session *HistoryModel::session() const
{
    return d->session;
}

}

#include "historymodel.moc"
<|endoftext|>