<commit_before>//
//   Copyright 2013 Pixar
//
//   Licensed under the Apache License, Version 2.0 (the "Apache License")
//   with the following modification; you may not use this file except in
//   compliance with the Apache License and the following modification to it:
//   Section 6. Trademarks. is deleted and replaced with:
//
//   6. Trademarks. This License does not grant permission to use the trade
//      names, trademarks, service marks, or product names of the Licensor
//      and its affiliates, except as required to comply with Section 4(c) of
//      the License and to reproduce the content of the NOTICE file.
//
//   You may obtain a copy of the Apache License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the Apache License with the above modification is
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//   KIND, either express or implied. See the Apache License for the specific
//   language governing permissions and limitations under the Apache License.
//
#include "topology.h"

#include <fstream>
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {

OsdUtilSubdivTopology::OsdUtilSubdivTopology():
    name("noname"),
    numVertices(0),
    refinementLevel(2)  // arbitrary, start with a reasonable subdivision level
{
}

OsdUtilSubdivTopology::~OsdUtilSubdivTopology()
{
}

bool
OsdUtilSubdivTopology::Initialize(
    int numVerticesParam,
    const int *nvertsParam, int numFaces,
    const int *indicesParam, int indicesLen,
    int levels,
    string *errorMessage)
{

    numVertices = numVerticesParam;
    refinementLevel = levels;

    nverts.resize(numFaces);
    for (int i=0; i<numFaces; ++i) {
        nverts[i] = nvertsParam[i];
    }

    indices.resize(indicesLen);
    for (int i=0; i<indicesLen; ++i) {
        indices[i] = indicesParam[i];
    }

    return IsValid(errorMessage);
}

bool
OsdUtilSubdivTopology::IsValid(string *errorMessage) const
{
    if (numVertices == 0) {
        if (errorMessage) {
            stringstream ss;
            ss << "Topology " << name << " has no vertices";
            *errorMessage = ss.str();
        }
        return false;
    }

    for (int i=0; i<(int)indices.size(); ++i) {
        if ((indices[i] < 0) or
            (indices[i] >= numVertices)) {
            if (errorMessage) {
                stringstream ss;
                ss << "Topology " << name << " has bad index " << indices[i] << " at index " << i;
                *errorMessage = ss.str();
            }
            return false;
        }

    }

    int totalNumIndices = 0;
    for (int i=0; i< (int)nverts.size(); ++i) {
        if (nverts[i] < 1) {
            if (errorMessage) {
                stringstream ss;
                ss << "Topology " << name << " has bad nverts " << nverts[i] << " at index " << i;
                *errorMessage = ss.str();
            }
            return false;
        }
        totalNumIndices += nverts[i];
    }

    if (totalNumIndices != (int)indices.size()) {
        if (errorMessage) {
            *errorMessage = "Bad indexing for face topology";
        }

        return false;
    }

    return true;
}

void
OsdUtilSubdivTopology::Print() const
{
    std::cout << "Mesh " << name << "\n";
    std::cout << "\tnumVertices = " << numVertices << "\n";
    std::cout << "\trefinementLevel = " << refinementLevel << "\n";
    std::cout << "\tindices ( " << indices.size() << ") : ";
    for (int i=0; i<(int)indices.size(); ++i) {
        std::cout << indices[i] << ", ";
    }
    std::cout << "\n";

    std::cout << "\tnverts ( " << nverts.size() << ") : ";
    for (int i=0; i<(int)nverts.size(); ++i) {
        std::cout << nverts[i] << ", ";
    }
    std::cout << "\n";

}

bool
OsdUtilSubdivTopology::ReadFromObjFile( char const * fname,
                                          vector<float> *pointPositions,
                                          std::string *errorMessage ) {

    FILE * handle = fopen( fname, "rt" );
    if (not handle) {
        stringstream ss;
        ss << "Could not open .obj file " << fname ;
        *errorMessage = ss.str();
        return false;
    }

    fseek( handle, 0, SEEK_END );
    size_t size = ftell(handle);
    fseek( handle, 0, SEEK_SET );

    char * shapeStr = new char[size+1];

    if ( fread( shapeStr, size, 1, handle)!=1 ) {
        stringstream ss;
        ss << "Error reading .obj file " << fname ;
        *errorMessage = ss.str();
        return false;
    }

    fclose(handle);

    shapeStr[size]='\0';

    name = fname;

    return ParseFromObjString(shapeStr, 1, pointPositions );
}

static char const * sgets( char * s, int size, char ** stream ) {
    for (int i=0; i<size; ++i) {
        if ( (*stream)[i]=='\n' or (*stream)[i]=='\0') {

            memcpy(s, *stream, i);
            s[i]='\0';

            if ((*stream)[i]=='\0')
                return 0;
            else {
                (*stream) += i+1;
                return s;
            }
        }
    }
    return 0;
}

bool
OsdUtilSubdivTopology::ParseFromObjString(
    char const * shapestr, int axis,
    vector<float> *pointPositions,
    std::string * /* errorMessage */)
{
    char * str=const_cast<char *>(shapestr), line[256];
    bool done = false;

    while( not done ) {

        done = sgets(line, sizeof(line), &str)==0;
        char* end = &line[strlen(line)-1];
        if (*end == '\n')
            *end = '\0'; // strip trailing nl

        float x, y, z, u, v;
        switch (line[0]) {
        case 'v': switch (line[1]) {
            case ' ':
                if(sscanf(line, "v %f %f %f", &x, &y, &z) == 3) {
                    pointPositions->push_back(x);
                    switch( axis ) {
                    case 0 : pointPositions->push_back(-z);
                        pointPositions->push_back(y); break;
                    case 1 : pointPositions->push_back(y);
                        pointPositions->push_back(z); break;
                    }
                } break;
            case 't':
                if(sscanf(line, "vt %f %f", &u, &v) == 2) {
                    //XXX:gelder
                    // extract UVs
                    // s->uvs.push_back(u);
                    // s->uvs.push_back(v);
                } break;
            case 'n' :
                break; // skip normals for now
            }
            break;
        case 'f':
            if(line[1] == ' ')  {
                int vi, ti, ni;
                const char* cp = &line[2];
                while (*cp == ' ') cp++;
                int numVerts = 0, nitems=0;
                while( (nitems=sscanf(cp, "%d/%d/%d", &vi, &ti, &ni))>0) {
                    numVerts++;
                    indices.push_back(vi-1);
                    //XXX:gelder
                    // Extract face varying uvs
                    //if(nitems >= 1) s->faceuvs.push_back(ti-1);
                    //if(nitems >= 2) s->facenormals.push_back(ni-1);
                    while (*cp && *cp != ' ') cp++;
                    while (*cp == ' ') cp++;
                }
                nverts.push_back(numVerts);
            }
            break;
//        case 't' : if(line[1] == ' ') {
//                shape::tag * t = tag::parseTag( line );
//                if (t)
//                    s->tags.push_back(t);
//            } break;
        }
    }

    numVertices = (int)pointPositions->size()/3;

    return true;
}

bool OsdUtilTagData::TagTypeFromString(
    OsdUtilTagData::TagType *tagType,
    const std::string &str)
{
    if (str == "corner") {
        *tagType = OsdUtilTagData::CORNER;
    } else if  (str == "crease") {
        *tagType = OsdUtilTagData::CREASE;
    } else if  (str == "creasemethod") {
        *tagType = OsdUtilTagData::CREASE_METHOD;
    } else if  (str == "facevaryinginterpolateboundary") {
        *tagType = OsdUtilTagData::FACE_VARYING_INTERPOLATE_BOUNDARY;
    } else if  (str == "facevaryingpropagatecorners") {
        *tagType = OsdUtilTagData::FACE_VARYING_PROPOGATE_CORNERS;
    } else if  (str == "hole") {
        *tagType = OsdUtilTagData::HOLE;
    } else if  (str == "interpolateboundary") {
        *tagType = OsdUtilTagData::INTERPOLATE_BOUNDARY;
    } else if  (str == "smoothtriangles") {
        *tagType = OsdUtilTagData::SMOOTH_TRIANGLES;
    } else if  (str == "vertexedit") {
        *tagType = OsdUtilTagData::VERTEX_EDIT;
    } else if  (str == "edgeedit") {
        *tagType = OsdUtilTagData::EDGE_EDIT;
    } else {
        return false;
    }

    return true;
}

// If numSharpness == 1, the single sharpness value applies for all vertices
// If numSharpness == numIndices, there is a per-vertex sharpness
bool
OsdUtilTagData::AddCorner(int *indices, int numIndices,
                            float *sharpness, int numSharpness)
{
    tags.push_back(CORNER);
    numArgs.push_back(numIndices);
    numArgs.push_back(numSharpness);
    numArgs.push_back(0);
    for (int i=0; i<numIndices; ++i) {
        intArgs.push_back(indices[i]);
    }
    for (int i=0; i<numSharpness; ++i) {
        floatArgs.push_back(sharpness[i]);
    }

    return true;
}

// Indices is a sequential series of mesh vertex indices that bound
// the edges to be tagged with sharpness.
//
// If numSharpness == 1, the single sharpness value applies for all edges
// If numSharpness == numIndices, there is a per-edge sharpness that
// will be interpolated along the crease
bool
OsdUtilTagData::AddCrease(int *indices, int numIndices,
                            float *sharpness, int numSharpness)
{
    tags.push_back(CREASE);
    numArgs.push_back(numIndices);
    numArgs.push_back(numSharpness);
    numArgs.push_back(0);
    for (int i=0; i<numIndices; ++i) {
        intArgs.push_back(indices[i]);
    }
    for (int i=0; i<numSharpness; ++i) {
        floatArgs.push_back(sharpness[i]);
    }

    return true;
}

// Either "normal" or "chaikin"
bool
OsdUtilTagData::AddCreaseMethod(const std::string & /* value */)
{
    return true;
}

// 0 == OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryNone
// 1 == OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryEdgeAndCorner
// 2 == OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryEdgeOnly
bool
OsdUtilTagData::AddInterpolateBoundary(int value )
{
    tags.push_back(INTERPOLATE_BOUNDARY);
    numArgs.push_back(1);
    numArgs.push_back(0);
    numArgs.push_back(0);
    intArgs.push_back(value);
}

bool
OsdUtilTagData::AddHole(int *indices, int numIndices)
{
    tags.push_back(HOLE);
    numArgs.push_back(numIndices);
    numArgs.push_back(0);
    numArgs.push_back(0);
    for (int i=0; i<numIndices; ++i) {
        intArgs.push_back(indices[i]);
    }

    return true;
}

bool
OsdUtilSubdivTopology::WriteObjFile(
    const char *filename,
    const float *positions,
    std::string *errorMessage)
{

    ofstream file;

    file.open (filename);

    if (not file.is_open()) {
        stringstream ss;
        ss << "Could not open .obj file " << filename ;
        *errorMessage = ss.str();
        return false;
    }

    for (int i=0; i<numVertices*3; i+=3) {
        file << "v " << positions[i] << " " << positions[i+1]
             << " " << positions[i+2] <<"\n";
    }

    file << "\n";

    int idx = 0;
    for (int i=0; i<(int)nverts.size(); ++i) {
        file << "f";
        for (int j=0; j<nverts[i]; ++j) {
            file << " " << indices[idx+j]+1;
        }
        idx += nverts[i];
        file << "\n";
    }

    file << "\n";

    file.close();

    return true;
}

}  // end namespace OPENSUBDIV_VERSION
}  // end namespace OpenSubdiv
<commit_msg>Fixed build errors.<commit_after>//
//   Copyright 2013 Pixar
//
//   Licensed under the Apache License, Version 2.0 (the "Apache License")
//   with the following modification; you may not use this file except in
//   compliance with the Apache License and the following modification to it:
//   Section 6. Trademarks. is deleted and replaced with:
//
//   6. Trademarks. This License does not grant permission to use the trade
//      names, trademarks, service marks, or product names of the Licensor
//      and its affiliates, except as required to comply with Section 4(c) of
//      the License and to reproduce the content of the NOTICE file.
//
//   You may obtain a copy of the Apache License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the Apache License with the above modification is
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//   KIND, either express or implied. See the Apache License for the specific
//   language governing permissions and limitations under the Apache License.
//
#include "topology.h"

#include <fstream>
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {

OsdUtilSubdivTopology::OsdUtilSubdivTopology():
    name("noname"),
    numVertices(0),
    refinementLevel(2)  // arbitrary, start with a reasonable subdivision level
{
}

OsdUtilSubdivTopology::~OsdUtilSubdivTopology()
{
}

bool
OsdUtilSubdivTopology::Initialize(
    int numVerticesParam,
    const int *nvertsParam, int numFaces,
    const int *indicesParam, int indicesLen,
    int levels,
    string *errorMessage)
{

    numVertices = numVerticesParam;
    refinementLevel = levels;

    nverts.resize(numFaces);
    for (int i=0; i<numFaces; ++i) {
        nverts[i] = nvertsParam[i];
    }

    indices.resize(indicesLen);
    for (int i=0; i<indicesLen; ++i) {
        indices[i] = indicesParam[i];
    }

    return IsValid(errorMessage);
}

bool
OsdUtilSubdivTopology::IsValid(string *errorMessage) const
{
    if (numVertices == 0) {
        if (errorMessage) {
            stringstream ss;
            ss << "Topology " << name << " has no vertices";
            *errorMessage = ss.str();
        }
        return false;
    }

    for (int i=0; i<(int)indices.size(); ++i) {
        if ((indices[i] < 0) or
            (indices[i] >= numVertices)) {
            if (errorMessage) {
                stringstream ss;
                ss << "Topology " << name << " has bad index " << indices[i] << " at index " << i;
                *errorMessage = ss.str();
            }
            return false;
        }

    }

    int totalNumIndices = 0;
    for (int i=0; i< (int)nverts.size(); ++i) {
        if (nverts[i] < 1) {
            if (errorMessage) {
                stringstream ss;
                ss << "Topology " << name << " has bad nverts " << nverts[i] << " at index " << i;
                *errorMessage = ss.str();
            }
            return false;
        }
        totalNumIndices += nverts[i];
    }

    if (totalNumIndices != (int)indices.size()) {
        if (errorMessage) {
            *errorMessage = "Bad indexing for face topology";
        }

        return false;
    }

    return true;
}

void
OsdUtilSubdivTopology::Print() const
{
    std::cout << "Mesh " << name << "\n";
    std::cout << "\tnumVertices = " << numVertices << "\n";
    std::cout << "\trefinementLevel = " << refinementLevel << "\n";
    std::cout << "\tindices ( " << indices.size() << ") : ";
    for (int i=0; i<(int)indices.size(); ++i) {
        std::cout << indices[i] << ", ";
    }
    std::cout << "\n";

    std::cout << "\tnverts ( " << nverts.size() << ") : ";
    for (int i=0; i<(int)nverts.size(); ++i) {
        std::cout << nverts[i] << ", ";
    }
    std::cout << "\n";

}

bool
OsdUtilSubdivTopology::ReadFromObjFile( char const * fname,
                                          vector<float> *pointPositions,
                                          std::string *errorMessage ) {

    FILE * handle = fopen( fname, "rt" );
    if (not handle) {
        stringstream ss;
        ss << "Could not open .obj file " << fname ;
        *errorMessage = ss.str();
        return false;
    }

    fseek( handle, 0, SEEK_END );
    size_t size = ftell(handle);
    fseek( handle, 0, SEEK_SET );

    char * shapeStr = new char[size+1];

    if ( fread( shapeStr, size, 1, handle)!=1 ) {
        stringstream ss;
        ss << "Error reading .obj file " << fname ;
        *errorMessage = ss.str();
        return false;
    }

    fclose(handle);

    shapeStr[size]='\0';

    name = fname;

    return ParseFromObjString(shapeStr, 1, pointPositions );
}

static char const * sgets( char * s, int size, char ** stream ) {
    for (int i=0; i<size; ++i) {
        if ( (*stream)[i]=='\n' or (*stream)[i]=='\0') {

            memcpy(s, *stream, i);
            s[i]='\0';

            if ((*stream)[i]=='\0')
                return 0;
            else {
                (*stream) += i+1;
                return s;
            }
        }
    }
    return 0;
}

bool
OsdUtilSubdivTopology::ParseFromObjString(
    char const * shapestr, int axis,
    vector<float> *pointPositions,
    std::string * /* errorMessage */)
{
    char * str=const_cast<char *>(shapestr), line[256];
    bool done = false;

    while( not done ) {

        done = sgets(line, sizeof(line), &str)==0;
        char* end = &line[strlen(line)-1];
        if (*end == '\n')
            *end = '\0'; // strip trailing nl

        float x, y, z, u, v;
        switch (line[0]) {
        case 'v': switch (line[1]) {
            case ' ':
                if(sscanf(line, "v %f %f %f", &x, &y, &z) == 3) {
                    pointPositions->push_back(x);
                    switch( axis ) {
                    case 0 : pointPositions->push_back(-z);
                        pointPositions->push_back(y); break;
                    case 1 : pointPositions->push_back(y);
                        pointPositions->push_back(z); break;
                    }
                } break;
            case 't':
                if(sscanf(line, "vt %f %f", &u, &v) == 2) {
                    //XXX:gelder
                    // extract UVs
                    // s->uvs.push_back(u);
                    // s->uvs.push_back(v);
                } break;
            case 'n' :
                break; // skip normals for now
            }
            break;
        case 'f':
            if(line[1] == ' ')  {
                int vi, ti, ni;
                const char* cp = &line[2];
                while (*cp == ' ') cp++;
                int numVerts = 0, nitems=0;
                while( (nitems=sscanf(cp, "%d/%d/%d", &vi, &ti, &ni))>0) {
                    numVerts++;
                    indices.push_back(vi-1);
                    //XXX:gelder
                    // Extract face varying uvs
                    //if(nitems >= 1) s->faceuvs.push_back(ti-1);
                    //if(nitems >= 2) s->facenormals.push_back(ni-1);
                    while (*cp && *cp != ' ') cp++;
                    while (*cp == ' ') cp++;
                }
                nverts.push_back(numVerts);
            }
            break;
//        case 't' : if(line[1] == ' ') {
//                shape::tag * t = tag::parseTag( line );
//                if (t)
//                    s->tags.push_back(t);
//            } break;
        }
    }

    numVertices = (int)pointPositions->size()/3;

    return true;
}

bool OsdUtilTagData::TagTypeFromString(
    OsdUtilTagData::TagType *tagType,
    const std::string &str)
{
    if (str == "corner") {
        *tagType = OsdUtilTagData::CORNER;
    } else if  (str == "crease") {
        *tagType = OsdUtilTagData::CREASE;
    } else if  (str == "creasemethod") {
        *tagType = OsdUtilTagData::CREASE_METHOD;
    } else if  (str == "facevaryinginterpolateboundary") {
        *tagType = OsdUtilTagData::FACE_VARYING_INTERPOLATE_BOUNDARY;
    } else if  (str == "facevaryingpropagatecorners") {
        *tagType = OsdUtilTagData::FACE_VARYING_PROPOGATE_CORNERS;
    } else if  (str == "hole") {
        *tagType = OsdUtilTagData::HOLE;
    } else if  (str == "interpolateboundary") {
        *tagType = OsdUtilTagData::INTERPOLATE_BOUNDARY;
    } else if  (str == "smoothtriangles") {
        *tagType = OsdUtilTagData::SMOOTH_TRIANGLES;
    } else if  (str == "vertexedit") {
        *tagType = OsdUtilTagData::VERTEX_EDIT;
    } else if  (str == "edgeedit") {
        *tagType = OsdUtilTagData::EDGE_EDIT;
    } else {
        return false;
    }

    return true;
}

// If numSharpness == 1, the single sharpness value applies for all vertices
// If numSharpness == numIndices, there is a per-vertex sharpness
bool
OsdUtilTagData::AddCorner(int *indices, int numIndices,
                            float *sharpness, int numSharpness)
{
    tags.push_back(CORNER);
    numArgs.push_back(numIndices);
    numArgs.push_back(numSharpness);
    numArgs.push_back(0);
    for (int i=0; i<numIndices; ++i) {
        intArgs.push_back(indices[i]);
    }
    for (int i=0; i<numSharpness; ++i) {
        floatArgs.push_back(sharpness[i]);
    }

    return true;
}

// Indices is a sequential series of mesh vertex indices that bound
// the edges to be tagged with sharpness.
//
// If numSharpness == 1, the single sharpness value applies for all edges
// If numSharpness == numIndices, there is a per-edge sharpness that
// will be interpolated along the crease
bool
OsdUtilTagData::AddCrease(int *indices, int numIndices,
                            float *sharpness, int numSharpness)
{
    tags.push_back(CREASE);
    numArgs.push_back(numIndices);
    numArgs.push_back(numSharpness);
    numArgs.push_back(0);
    for (int i=0; i<numIndices; ++i) {
        intArgs.push_back(indices[i]);
    }
    for (int i=0; i<numSharpness; ++i) {
        floatArgs.push_back(sharpness[i]);
    }

    return true;
}

// Either "normal" or "chaikin"
bool
OsdUtilTagData::AddCreaseMethod(const std::string & /* value */)
{
    return true;
}

// 0 == OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryNone
// 1 == OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryEdgeAndCorner
// 2 == OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryEdgeOnly
bool
OsdUtilTagData::AddInterpolateBoundary(int value )
{
    tags.push_back(INTERPOLATE_BOUNDARY);
    numArgs.push_back(1);
    numArgs.push_back(0);
    numArgs.push_back(0);
    intArgs.push_back(value);

    return true;
}

bool
OsdUtilTagData::AddHole(int *indices, int numIndices)
{
    tags.push_back(HOLE);
    numArgs.push_back(numIndices);
    numArgs.push_back(0);
    numArgs.push_back(0);
    for (int i=0; i<numIndices; ++i) {
        intArgs.push_back(indices[i]);
    }

    return true;
}

bool
OsdUtilSubdivTopology::WriteObjFile(
    const char *filename,
    const float *positions,
    std::string *errorMessage)
{

    ofstream file;

    file.open (filename);

    if (not file.is_open()) {
        stringstream ss;
        ss << "Could not open .obj file " << filename ;
        *errorMessage = ss.str();
        return false;
    }

    for (int i=0; i<numVertices*3; i+=3) {
        file << "v " << positions[i] << " " << positions[i+1]
             << " " << positions[i+2] <<"\n";
    }

    file << "\n";

    int idx = 0;
    for (int i=0; i<(int)nverts.size(); ++i) {
        file << "f";
        for (int j=0; j<nverts[i]; ++j) {
            file << " " << indices[idx+j]+1;
        }
        idx += nverts[i];
        file << "\n";
    }

    file << "\n";

    file.close();

    return true;
}

}  // end namespace OPENSUBDIV_VERSION
}  // end namespace OpenSubdiv
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*
	File is modified to include Ring Keywords and Ignore the Case
	Updated by : Mahmoud Fayed <msfclipper@yahoo.com>
	Date	    : 2016.09.14
*/

#include "highlighter.h"

Highlighter::Highlighter(QTextDocument *parent)
    : QSyntaxHighlighter(parent)
{
    setColors(Qt::darkBlue,Qt::darkMagenta,Qt::red,Qt::darkGreen,Qt::blue);
}

void Highlighter::highlightBlock(const QString &text)
{
    foreach (const HighlightingRule &rule, highlightingRules) {
        QRegExp expression(rule.pattern);
        int index = expression.indexIn(text);
        while (index >= 0) {
            int length = expression.matchedLength();
            setFormat(index, length, rule.format);
            index = expression.indexIn(text, index + length);
        }
    }

    setCurrentBlockState(0);
    int startIndex = 0;
    if (previousBlockState() != 1)
        startIndex = commentStartExpression.indexIn(text);

    while (startIndex >= 0) {
        int endIndex = commentEndExpression.indexIn(text, startIndex);
        int commentLength;
        if (endIndex == -1) {
            setCurrentBlockState(1);
            commentLength = text.length() - startIndex;
        } else {
            commentLength = endIndex - startIndex
                            + commentEndExpression.matchedLength();
        }
        setFormat(startIndex, commentLength, multiLineCommentFormat);
        startIndex = commentStartExpression.indexIn(text, startIndex + commentLength);
    }
}

void Highlighter::setColors(QColor c1,QColor c2,QColor c3,QColor c4,QColor c5) {

    HighlightingRule rule;
    highlightingRules.remove(0,highlightingRules.count());
    keywordFormat.setForeground(c1);
    if (this->nKeywordsBold)
	    keywordFormat.setFontWeight(QFont::Bold);
    QStringList keywordPatterns;
    keywordPatterns << "\\bagain\\b" << "\\band\\b" << "\\bbut\\b"
                    << "\\bbye\\b" << "\\bcall\\b" << "\\bcase\\b"
                    << "\\bcatch\\b" << "\\bclass\\b" << "\\bdef\\b"
                    << "\\bdo\\b" << "\\bdone\\b" << "\\belse\\b"
                    << "\\belseif\\b" << "\\bend\\b" << "\\bexit\\b"
                    << "\\bfor\\b" << "\\bfrom\\b" << "\\bfunc\\b"
                    << "\\bget\\b" << "\\bgive\\b" << "\\bif\\b"
                    << "\\bimport\\b" << "\\bin\\b" << "\\bload\\b"
                    << "\\bloop\\b" << "\\bnew\\b" << "\\bnext\\b"
					<< "\\bnot\\b" << "\\boff\\b" << "\\bok\\b"
					<< "\\bon\\b" << "\\bor\\b" << "\\bother\\b"
					<< "\\bpackage\\b" << "\\bprivate\\b" << "\\bput\\b"
					<< "\\breturn\\b" << "\\bsee\\b" << "\\bstep\\b"
					<< "\\bswitch\\b" << "\\bto\\b" << "\\btry\\b"
					<< "\\bendfunc\\b" << "\\bendclass\\b" << "\\bendpackage\\b"
					<< "\\bwhile\\b" << "\\bchangeringkeyword\\b"
					<< "\\bchangeringoperator\\b" << "\\bloadsyntax\\b";

    foreach (const QString &pattern, keywordPatterns) {
        rule.pattern = QRegExp(pattern,Qt::CaseInsensitive);
        rule.format = keywordFormat;
        highlightingRules.append(rule);
    }

    if (this->nKeywordsBold)
    	classFormat.setFontWeight(QFont::Bold);
    classFormat.setForeground(c2);
    rule.pattern = QRegExp("\\bQ[A-Za-z]+\\b");
    rule.format = classFormat;
    highlightingRules.append(rule);

    singleLineCommentFormat.setForeground(c3);
    rule.pattern = QRegExp("//[^\n]*");
    rule.format = singleLineCommentFormat;
    highlightingRules.append(rule);

    singleLineCommentFormat.setForeground(c3);
    rule.pattern = QRegExp("#[^\n]*");
    rule.format = singleLineCommentFormat;
    highlightingRules.append(rule);

    multiLineCommentFormat.setForeground(c3);

    quotationFormat.setForeground(c4);
    rule.pattern = QRegExp("\"(?:(?!\\/\\/).)+\"");			//QRegExp("\".*\"");
    rule.pattern.setMinimal(true);
    rule.format = quotationFormat;
    highlightingRules.append(rule);

    quotationFormat2.setForeground(c4);
    rule.pattern = QRegExp("\'(?:(?!\\/\\/).)+\'");			// QRegExp("\'.*\'");
    rule.pattern.setMinimal(true);
    rule.format = quotationFormat2;
    highlightingRules.append(rule);

    quotationFormat3.setForeground(c4);
    rule.pattern = QRegExp("\`(?:(?!\\/\\/).)+\`");			// QRegExp("\`.*\`");
    rule.pattern.setMinimal(true);
    rule.format = quotationFormat3;
    highlightingRules.append(rule);

    functionFormat.setFontItalic(true);
    functionFormat.setForeground(c5);
    rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()");
    rule.format = functionFormat;
    highlightingRules.append(rule);

    commentStartExpression = QRegExp("/\\*");
    commentEndExpression = QRegExp("\\*/");

}

void Highlighter::setKeywordsBold(int nStatus) {
	this->nKeywordsBold = nStatus;
}
<commit_msg>Update RingQt - highlighter.cpp - Better highlighter rules.<commit_after>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*
	File is modified to include Ring Keywords and Ignore the Case
	Updated by : Mahmoud Fayed <msfclipper@yahoo.com>
	Date	    : 2016.09.14
*/

#include "highlighter.h"

Highlighter::Highlighter(QTextDocument *parent)
    : QSyntaxHighlighter(parent)
{
    setColors(Qt::darkBlue,Qt::darkMagenta,Qt::red,Qt::darkGreen,Qt::blue);
}

void Highlighter::highlightBlock(const QString &text)
{
    foreach (const HighlightingRule &rule, highlightingRules) {
        QRegExp expression(rule.pattern);
        int index = expression.indexIn(text);
        while (index >= 0) {
            int length = expression.matchedLength();
            setFormat(index, length, rule.format);
            index = expression.indexIn(text, index + length);
        }
    }

    setCurrentBlockState(0);
    int startIndex = 0;
    if (previousBlockState() != 1)
        startIndex = commentStartExpression.indexIn(text);

    while (startIndex >= 0) {
        int endIndex = commentEndExpression.indexIn(text, startIndex);
        int commentLength;
        if (endIndex == -1) {
            setCurrentBlockState(1);
            commentLength = text.length() - startIndex;
        } else {
            commentLength = endIndex - startIndex
                            + commentEndExpression.matchedLength();
        }
        setFormat(startIndex, commentLength, multiLineCommentFormat);
        startIndex = commentStartExpression.indexIn(text, startIndex + commentLength);
    }
}

void Highlighter::setColors(QColor c1,QColor c2,QColor c3,QColor c4,QColor c5) {

    HighlightingRule rule;
    highlightingRules.remove(0,highlightingRules.count());
    keywordFormat.setForeground(c1);
    if (this->nKeywordsBold)
	    keywordFormat.setFontWeight(QFont::Bold);
    QStringList keywordPatterns;
    keywordPatterns << "\\bagain\\b" << "\\band\\b" << "\\bbut\\b"
                    << "\\bbye\\b" << "\\bcall\\b" << "\\bcase\\b"
                    << "\\bcatch\\b" << "\\bclass\\b" << "\\bdef\\b"
                    << "\\bdo\\b" << "\\bdone\\b" << "\\belse\\b"
                    << "\\belseif\\b" << "\\bend\\b" << "\\bexit\\b"
                    << "\\bfor\\b" << "\\bfrom\\b" << "\\bfunc\\b"
                    << "\\bget\\b" << "\\bgive\\b" << "\\bif\\b"
                    << "\\bimport\\b" << "\\bin\\b" << "\\bload\\b"
                    << "\\bloop\\b" << "\\bnew\\b" << "\\bnext\\b"
					<< "\\bnot\\b" << "\\boff\\b" << "\\bok\\b"
					<< "\\bon\\b" << "\\bor\\b" << "\\bother\\b"
					<< "\\bpackage\\b" << "\\bprivate\\b" << "\\bput\\b"
					<< "\\breturn\\b" << "\\bsee\\b" << "\\bstep\\b"
					<< "\\bswitch\\b" << "\\bto\\b" << "\\btry\\b"
					<< "\\bendfunc\\b" << "\\bendclass\\b" << "\\bendpackage\\b"
					<< "\\bwhile\\b" << "\\bchangeringkeyword\\b"
					<< "\\bchangeringoperator\\b" << "\\bloadsyntax\\b";

    foreach (const QString &pattern, keywordPatterns) {
        rule.pattern = QRegExp(pattern,Qt::CaseInsensitive);
        rule.format = keywordFormat;
        highlightingRules.append(rule);
    }

    if (this->nKeywordsBold)
    	classFormat.setFontWeight(QFont::Bold);
    classFormat.setForeground(c2);
    rule.pattern = QRegExp("\\bQ[A-Za-z]+\\b");
    rule.format = classFormat;
    highlightingRules.append(rule);

    functionFormat.setFontItalic(true);
    functionFormat.setForeground(c5);
    rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()");
    rule.format = functionFormat;
    highlightingRules.append(rule);

    singleLineCommentFormat.setForeground(c3);
    rule.pattern = QRegExp("//[^\n]*");
    rule.format = singleLineCommentFormat;
    highlightingRules.append(rule);

    rule.pattern = QRegExp("^#+[^\n]*");
    highlightingRules.append(rule);

    rule.pattern = QRegExp("#+( |-|=)[^\n]*");
    highlightingRules.append(rule);

    multiLineCommentFormat.setForeground(c3);

    quotationFormat.setForeground(c4);
    rule.pattern = QRegExp("\"(?:(?!\\/\\/).)+\"");
    rule.pattern.setMinimal(true);
    rule.format = quotationFormat;
    highlightingRules.append(rule);

    quotationFormat2.setForeground(c4);
    rule.pattern = QRegExp("\'(?:(?!\\/\\/).)+\'");
    rule.pattern.setMinimal(true);
    rule.format = quotationFormat2;
    highlightingRules.append(rule);

    quotationFormat3.setForeground(c4);
    rule.pattern = QRegExp("\`(?:(?!\\/\\/).)+\`");
    rule.pattern.setMinimal(true);
    rule.format = quotationFormat3;
    highlightingRules.append(rule);

    commentStartExpression = QRegExp("^/\\*");
    commentEndExpression = QRegExp("\\*/");

}

void Highlighter::setKeywordsBold(int nStatus) {
	this->nKeywordsBold = nStatus;
}
<|endoftext|>


<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/profiler.h>
#include <iostream>
#include <map>
#include <string>
#include <utility>

using namespace std;

namespace geos {
namespace util { // geos.util

Profile::Profile(string newname)
{
	name = newname;
	totaltime = 0;
	min = max = avg = 0;
}

Profile::~Profile()
{
}

#if 0
void
Profile::start()
{
	gettimeofday(&starttime, NULL);
}

void
Profile::stop()
{
	gettimeofday(&stoptime, NULL);
	double elapsed = 1000000*(stoptime.tv_sec-starttime.tv_sec)+
		(stoptime.tv_usec-starttime.tv_usec);

	timings.push_back(elapsed);
	totaltime += elapsed;
	if ( timings.size() == 1 ) max = min = elapsed;
	else
	{
		if ( elapsed > max ) max = elapsed;
		if ( elapsed < min ) min = elapsed;
	}
	avg = totaltime / timings.size();
}
#endif

double
Profile::getMax() const
{
	return max;
}

double
Profile::getMin() const
{
	return min;
}

double
Profile::getAvg() const
{
	return avg;
}

double
Profile::getTot() const
{
	return totaltime;
}

size_t
Profile::getNumTimings() const
{
	return timings.size();
}

Profiler::Profiler()
{
}

Profiler::~Profiler()
{
	map<string, Profile *>::const_iterator it;
	for ( it=profs.begin(); it != profs.end(); ++it )
	{
		delete it->second;
	}
}

void
Profiler::start(string name)
{
	Profile *prof = get(name);
	prof->start();
}

void
Profiler::stop(string name)
{
	map<string, Profile *>::iterator iter = profs.find(name);
	if ( iter == profs.end() )
		cerr<<name<<": no such Profile started";
	iter->second->stop();
}

Profile *
Profiler::get(string name)
{
	Profile *prof;
	map<string, Profile *>::iterator iter = profs.find(name);
	if ( iter == profs.end() ) {
		prof = new Profile(name);
		profs.insert(pair<string, Profile *>(name, prof));
	} else {
		prof = iter->second;
	}
	return prof;
}

Profiler *
Profiler::instance()
{
	static Profiler internal_profiler;
	return &internal_profiler;
}

ostream&
operator<< (ostream &os, const Profile &prof)
{
	os << " num:"<<prof.getNumTimings()<<" min:"<<
		prof.getMin()<<" max:"<<prof.getMax()<<
		" avg:"<<prof.getAvg()<<" tot:"<<prof.getTot()<<
		" ["<<prof.name<<"]";
	return os;
}

ostream&
operator<< (ostream &os, const Profiler &prof)
{
	map<string, Profile *>::const_iterator it;
	for ( it=prof.profs.begin(); it != prof.profs.end(); ++it )
	{
		os<<*(it->second)<<endl;
	}
	return os;
}

} // namespace geos.util
} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.10  2006/06/12 11:29:24  strk
 * unsigned int => size_t
 *
 * Revision 1.9  2006/03/07 14:18:34  strk
 * Profiler singleton implemented with a function-static Profiler instance
 *
 * Revision 1.8  2006/03/06 19:40:48  strk
 * geos::util namespace. New GeometryCollection::iterator interface, many cleanups.
 *
 * Revision 1.7  2006/03/03 10:46:22  strk
 * Removed 'using namespace' from headers, added missing headers in .cpp files, removed useless includes in headers (bug#46)
 *
 * Revision 1.6  2005/02/01 14:18:04  strk
 * Made profiler start/stop inline
 *
 * Revision 1.5  2005/02/01 13:44:59  strk
 * More profiling labels.
 *
 * Revision 1.4  2004/12/03 22:52:56  strk
 * enforced const return of CoordinateSequence::toVector() method to derivate classes.
 *
 * Revision 1.3  2004/11/08 12:15:35  strk
 * Added number of gathered timings in output.
 *
 * Revision 1.2  2004/11/08 11:19:39  strk
 * Profiler::get() always return a Profile (new if not existant).
 *
 * Revision 1.1  2004/11/01 16:43:04  strk
 * Added Profiler code.
 * Temporarly patched a bug in DoubleBits (must check drawbacks).
 * Various cleanups and speedups.
 *
 **********************************************************************/
<commit_msg>Do not dereference past-the-end iterator on invalid call<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/profiler.h>
#include <iostream>
#include <map>
#include <string>
#include <utility>

using namespace std;

namespace geos {
namespace util { // geos.util

Profile::Profile(string newname)
{
	name = newname;
	totaltime = 0;
	min = max = avg = 0;
}

Profile::~Profile()
{
}

#if 0
void
Profile::start()
{
	gettimeofday(&starttime, NULL);
}

void
Profile::stop()
{
	gettimeofday(&stoptime, NULL);
	double elapsed = 1000000*(stoptime.tv_sec-starttime.tv_sec)+
		(stoptime.tv_usec-starttime.tv_usec);

	timings.push_back(elapsed);
	totaltime += elapsed;
	if ( timings.size() == 1 ) max = min = elapsed;
	else
	{
		if ( elapsed > max ) max = elapsed;
		if ( elapsed < min ) min = elapsed;
	}
	avg = totaltime / timings.size();
}
#endif

double
Profile::getMax() const
{
	return max;
}

double
Profile::getMin() const
{
	return min;
}

double
Profile::getAvg() const
{
	return avg;
}

double
Profile::getTot() const
{
	return totaltime;
}

size_t
Profile::getNumTimings() const
{
	return timings.size();
}

Profiler::Profiler()
{
}

Profiler::~Profiler()
{
	map<string, Profile *>::const_iterator it;
	for ( it=profs.begin(); it != profs.end(); ++it )
	{
		delete it->second;
	}
}

void
Profiler::start(string name)
{
	Profile *prof = get(name);
	prof->start();
}

void
Profiler::stop(string name)
{
	map<string, Profile *>::iterator iter = profs.find(name);
	if ( iter == profs.end() ) {
		cerr<<name<<": no such Profile started";
		return;
	}
	iter->second->stop();
}

Profile *
Profiler::get(string name)
{
	Profile *prof;
	map<string, Profile *>::iterator iter = profs.find(name);
	if ( iter == profs.end() ) {
		prof = new Profile(name);
		profs.insert(pair<string, Profile *>(name, prof));
	} else {
		prof = iter->second;
	}
	return prof;
}

Profiler *
Profiler::instance()
{
	static Profiler internal_profiler;
	return &internal_profiler;
}

ostream&
operator<< (ostream &os, const Profile &prof)
{
	os << " num:"<<prof.getNumTimings()<<" min:"<<
		prof.getMin()<<" max:"<<prof.getMax()<<
		" avg:"<<prof.getAvg()<<" tot:"<<prof.getTot()<<
		" ["<<prof.name<<"]";
	return os;
}

ostream&
operator<< (ostream &os, const Profiler &prof)
{
	map<string, Profile *>::const_iterator it;
	for ( it=prof.profs.begin(); it != prof.profs.end(); ++it )
	{
		os<<*(it->second)<<endl;
	}
	return os;
}

} // namespace geos.util
} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.10  2006/06/12 11:29:24  strk
 * unsigned int => size_t
 *
 * Revision 1.9  2006/03/07 14:18:34  strk
 * Profiler singleton implemented with a function-static Profiler instance
 *
 * Revision 1.8  2006/03/06 19:40:48  strk
 * geos::util namespace. New GeometryCollection::iterator interface, many cleanups.
 *
 * Revision 1.7  2006/03/03 10:46:22  strk
 * Removed 'using namespace' from headers, added missing headers in .cpp files, removed useless includes in headers (bug#46)
 *
 * Revision 1.6  2005/02/01 14:18:04  strk
 * Made profiler start/stop inline
 *
 * Revision 1.5  2005/02/01 13:44:59  strk
 * More profiling labels.
 *
 * Revision 1.4  2004/12/03 22:52:56  strk
 * enforced const return of CoordinateSequence::toVector() method to derivate classes.
 *
 * Revision 1.3  2004/11/08 12:15:35  strk
 * Added number of gathered timings in output.
 *
 * Revision 1.2  2004/11/08 11:19:39  strk
 * Profiler::get() always return a Profile (new if not existant).
 *
 * Revision 1.1  2004/11/01 16:43:04  strk
 * Added Profiler code.
 * Temporarly patched a bug in DoubleBits (must check drawbacks).
 * Various cleanups and speedups.
 *
 **********************************************************************/
<|endoftext|>


<commit_before>/*
Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Gabriel Ebner
*/
#include "util/log_tree.h"
#include "util/task_builder.h"
#include <vector>
#include <string>

namespace lean {

void log_tree::notify_core(std::vector<log_tree::event> const & events) {
    if (events.empty()) return;
    for (auto & l : m_listeners)
        l(events);
}

void log_tree::add_listener(log_tree::listener const & l) {
    unique_lock<mutex> lock(m_mutex);
    m_listeners.push_back(l);
}

log_tree::log_tree() {
    auto cell = new node_cell;
    cell->m_tree = this;
    m_root = node(cell);
}

log_tree::~log_tree() {
    std::vector<event> evs;
    m_root.detach_core(evs);
    m_root = node();
}

void log_tree::print_to(std::ostream & out) const {
    get_root().print_to(out, 0);
}

void log_tree::print() const {
    print_to(std::cerr);
}

void log_tree::node::for_each(std::function<bool(log_tree::node const &)> const & fn) const { // NOLINT
    if (fn(*this)) {
        get_children().for_each([&] (name const &, log_tree::node const & c) {
            c.for_each(fn);
        });
    }
};

void log_tree::for_each(std::function<bool(log_tree::node const &)> const & fn) const { // NOLINT
    m_root.for_each(fn);
};

void log_tree::node::detach_core(std::vector<log_tree::event> & events) const {
    if (m_ptr->m_detached) return;
    m_ptr->m_detached = true;
    m_ptr->m_children.for_each([&] (name const &, node const & c) { c.detach_core(events); });
    for (auto & e : m_ptr->m_entries) events.push_back({ event::EntryRemoved, m_ptr, e });
    if (m_ptr->m_producer) events.push_back({event::Finished, m_ptr, {}});
}

void log_tree::node::notify(std::vector<log_tree::event> const & events, unique_lock<mutex> & l) const {
    if (!m_ptr->m_detached) {
        l.unlock();
        m_ptr->m_tree->notify_core(events);
    }
}

log_tree::node log_tree::node::clone_core() const {
    auto copy = node(new node_cell);
    copy.m_ptr->m_children = m_ptr->m_children;
    m_ptr->m_children.clear();
    copy.m_ptr->m_tree = m_ptr->m_tree;
    copy.m_ptr->m_detached = m_ptr->m_detached;
    copy.m_ptr->m_entries = m_ptr->m_entries;
    m_ptr->m_detached = true;
    return copy;
}

void log_tree::node::clear_entries() const {
    auto l = lock();

    std::vector<event> events;
    for (auto & e : m_ptr->m_entries) {
        events.push_back({event::EntryRemoved, *this, std::move(e)});
    }
    m_ptr->m_entries.clear();

    notify(events, l);
}

void log_tree::node::add(log_entry const & entry) const {
    auto l = lock();
    m_ptr->m_entries.push_back(entry);
    notify({{event::EntryAdded, *this, entry}}, l);
}

log_tree::node log_tree::node::mk_child(name n, std::string const & description, location const & loc,
                                        bool overwrite) {
    auto l = lock();
    std::vector<event> events;

    if (!overwrite && (n.is_anonymous() || m_ptr->m_used_names.contains(n))) {
        for (unsigned i = 0;; i++) {
            name n_(n, i);
            if (!m_ptr->m_used_names.contains(n_)) {
                n = n_;
                break;
            }
        }
    }
    m_ptr->m_used_names.insert(n);

    node child;
    if (auto existing = m_ptr->m_children.find(n)) {
        child = existing->clone_core();
        existing->detach_core(events);
    } else {
        child = node(new node_cell);
        child.m_ptr->m_tree = m_ptr->m_tree;
        child.m_ptr->m_detached = m_ptr->m_detached;
    }
    child.m_ptr->m_description = description;
    child.m_ptr->m_location = loc;
    m_ptr->m_children.insert(n, child);

    notify(events, l);
    return child;
}

void log_tree::node::set_producer(gtask const & prod) {
    auto l = lock();
    m_ptr->m_producer = prod;
    notify({{event::ProducerSet, *this, {}}}, l);
}

void log_tree::node::finish() const {
    auto l = lock();
    std::vector<event> events;
    m_ptr->m_producer.reset();

    buffer<pair<name, node>> to_delete;
    m_ptr->m_children.for_each([&] (name const & n, node const & c) {
        if (!m_ptr->m_used_names.contains(n))
            to_delete.emplace_back(n, c);
    });

    for (auto & c : to_delete) {
        m_ptr->m_children.erase(c.first);
        c.second.detach_core(events);
    }

    events.push_back({event::Finished, *this, {}});
    notify(events, l);
}

std::vector<log_entry> log_tree::node::get_entries() const {
    auto l = lock();
    return m_ptr->m_entries;
}

name_map<lean::log_tree::node> log_tree::node::get_children() const {
    auto l = lock();
    return m_ptr->m_children;
}

void log_tree::node::remove_child(name const & n) const {
    auto l = lock();
    if (auto c = m_ptr->m_children.find(n)) {
        m_ptr->m_children.erase(n);
        std::vector<event> events;
        c->detach_core(events);
        notify(events, l);
    }
}

name_map<log_tree::node> log_tree::node::get_used_children() const {
    auto l = lock();
    name_map<node> used_children;
    m_ptr->m_used_names.for_each([&] (name const & n) {
        if (auto c = m_ptr->m_children.find(n)) {
            used_children.insert(n, *c);
        }
    });
    return used_children;
}

void log_tree::node::reuse(name const & n) const {
    auto l = lock();
    m_ptr->m_used_names.insert(n);
}

name_set log_tree::node::get_used_names() const {
    auto l = lock();
    return m_ptr->m_used_names;
}

gtask log_tree::node::get_producer() const {
    auto l = lock();
    return m_ptr->m_producer;
}

void log_tree::node::print() const {
    print_to(std::cerr, 0);
}

void log_tree::node::print_to(std::ostream & out, unsigned indent) const {
    indent += 2;

    auto l = lock();
    auto begin = m_ptr->m_location.m_range.m_begin, end = m_ptr->m_location.m_range.m_end;
    out << m_ptr->m_location.m_file_name
        << ": " << begin.first << ":" << begin.second << " -- " << end.first << ":" << end.second << ": "
        << m_ptr->m_description << " ("
        << m_ptr->m_entries.size()
        << " entries, producer = "
        << std::hex << reinterpret_cast<uintptr_t>(m_ptr->m_producer.get()) << std::dec
        << ")" << std::endl;

    if (auto prod = m_ptr->m_producer) {
        if (auto ex = prod->peek_exception()) {
            for (unsigned i = 0; i < indent; i++) out << ' ';
            out << "producer threw exception: ";
            try {
                std::rethrow_exception(ex);
            } catch (std::exception & ex) {
                out << ex.what();
            } catch (cancellation_exception) {
                out << "<cancelled>";
            } catch (...) {
                out << "<unknown exception>";
            }
            out << "\n";
        }
    }

    auto children = m_ptr->m_children;
    auto used_names = m_ptr->m_used_names;
    l.unlock();

    children.for_each([&] (name const & n, log_tree::node const & c) {
        for (unsigned i = 0; i < indent; i++) out << ' ';
        out << n;
        if (!used_names.contains(n))
            out << " (unused)";
        out << ": ";
        c.print_to(out, indent);
    });
}

static void gather_producers(buffer<gtask> & deps, log_tree::node const & n) {
    if (auto prod = n.get_producer()) deps.push_back(prod);
    n.get_children().for_each([&] (name const &, log_tree::node const & c) {
       gather_producers(deps, c);
    });
}

gtask log_tree::node::wait_for_finish() const {
    auto t = *this;
    return mk_dependency_task([t] (buffer<gtask> & deps) { gather_producers(deps, t); });
}

bool log_tree::node::has_entry_now(std::function<bool(log_entry const &)> const & fn) const { // NOLINT
    for (auto & e : get_entries()) {
        if (fn(e)) return true;
    }
    bool res = false;
    get_children().for_each([&] (name const &, node const & c) {
        res = res || c.has_entry_now(fn);
    });
    return res;
}

task<bool> log_tree::node::has_entry(std::function<bool(log_entry const &)> const & fn) const { // NOLINT
    auto t = *this;
    return task_builder<bool>([t, fn] { return t.has_entry_now(fn); }).depends_on(wait_for_finish()).build();
}

LEAN_THREAD_PTR(log_tree::node, g_log_tree);
scope_log_tree_core::scope_log_tree_core(log_tree::node * lt) : flet<log_tree::node *>(g_log_tree, lt) {}

log_tree::node & logtree() {
    if (g_log_tree) {
        return *g_log_tree;
    } else {
        throw exception("no log tree in scope");
    }
}

scope_log_tree::scope_log_tree(log_tree::node const & lt) : m_node(lt), m_scope(&m_node) {
    m_node.clear_entries();
}

scope_log_tree::~scope_log_tree() {
    logtree().finish();
}

scope_log_tree::scope_log_tree(std::string const & desc, pos_range const & pos) :
        scope_log_tree(logtree().mk_child({}, desc, {logtree().get_location().m_file_name, pos})) {}

scope_log_tree::scope_log_tree(std::string const & desc) :
        scope_log_tree(logtree().mk_child({}, desc, logtree().get_location())) {}

scope_log_tree::scope_log_tree() : scope_log_tree(std::string()) {}

}
<commit_msg>refactor(util/log_tree): use for_each<commit_after>/*
Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Gabriel Ebner
*/
#include "util/log_tree.h"
#include "util/task_builder.h"
#include <vector>
#include <string>

namespace lean {

void log_tree::notify_core(std::vector<log_tree::event> const & events) {
    if (events.empty()) return;
    for (auto & l : m_listeners)
        l(events);
}

void log_tree::add_listener(log_tree::listener const & l) {
    unique_lock<mutex> lock(m_mutex);
    m_listeners.push_back(l);
}

log_tree::log_tree() {
    auto cell = new node_cell;
    cell->m_tree = this;
    m_root = node(cell);
}

log_tree::~log_tree() {
    std::vector<event> evs;
    m_root.detach_core(evs);
    m_root = node();
}

void log_tree::print_to(std::ostream & out) const {
    get_root().print_to(out, 0);
}

void log_tree::print() const {
    print_to(std::cerr);
}

void log_tree::node::for_each(std::function<bool(log_tree::node const &)> const & fn) const { // NOLINT
    if (fn(*this)) {
        get_children().for_each([&] (name const &, log_tree::node const & c) {
            c.for_each(fn);
        });
    }
};

void log_tree::for_each(std::function<bool(log_tree::node const &)> const & fn) const { // NOLINT
    m_root.for_each(fn);
};

void log_tree::node::detach_core(std::vector<log_tree::event> & events) const {
    if (m_ptr->m_detached) return;
    m_ptr->m_detached = true;
    m_ptr->m_children.for_each([&] (name const &, node const & c) { c.detach_core(events); });
    for (auto & e : m_ptr->m_entries) events.push_back({ event::EntryRemoved, m_ptr, e });
    if (m_ptr->m_producer) events.push_back({event::Finished, m_ptr, {}});
}

void log_tree::node::notify(std::vector<log_tree::event> const & events, unique_lock<mutex> & l) const {
    if (!m_ptr->m_detached) {
        l.unlock();
        m_ptr->m_tree->notify_core(events);
    }
}

log_tree::node log_tree::node::clone_core() const {
    auto copy = node(new node_cell);
    copy.m_ptr->m_children = m_ptr->m_children;
    m_ptr->m_children.clear();
    copy.m_ptr->m_tree = m_ptr->m_tree;
    copy.m_ptr->m_detached = m_ptr->m_detached;
    copy.m_ptr->m_entries = m_ptr->m_entries;
    m_ptr->m_detached = true;
    return copy;
}

void log_tree::node::clear_entries() const {
    auto l = lock();

    std::vector<event> events;
    for (auto & e : m_ptr->m_entries) {
        events.push_back({event::EntryRemoved, *this, std::move(e)});
    }
    m_ptr->m_entries.clear();

    notify(events, l);
}

void log_tree::node::add(log_entry const & entry) const {
    auto l = lock();
    m_ptr->m_entries.push_back(entry);
    notify({{event::EntryAdded, *this, entry}}, l);
}

log_tree::node log_tree::node::mk_child(name n, std::string const & description, location const & loc,
                                        bool overwrite) {
    auto l = lock();
    std::vector<event> events;

    if (!overwrite && (n.is_anonymous() || m_ptr->m_used_names.contains(n))) {
        for (unsigned i = 0;; i++) {
            name n_(n, i);
            if (!m_ptr->m_used_names.contains(n_)) {
                n = n_;
                break;
            }
        }
    }
    m_ptr->m_used_names.insert(n);

    node child;
    if (auto existing = m_ptr->m_children.find(n)) {
        child = existing->clone_core();
        existing->detach_core(events);
    } else {
        child = node(new node_cell);
        child.m_ptr->m_tree = m_ptr->m_tree;
        child.m_ptr->m_detached = m_ptr->m_detached;
    }
    child.m_ptr->m_description = description;
    child.m_ptr->m_location = loc;
    m_ptr->m_children.insert(n, child);

    notify(events, l);
    return child;
}

void log_tree::node::set_producer(gtask const & prod) {
    auto l = lock();
    m_ptr->m_producer = prod;
    notify({{event::ProducerSet, *this, {}}}, l);
}

void log_tree::node::finish() const {
    auto l = lock();
    std::vector<event> events;
    m_ptr->m_producer.reset();

    buffer<pair<name, node>> to_delete;
    m_ptr->m_children.for_each([&] (name const & n, node const & c) {
        if (!m_ptr->m_used_names.contains(n))
            to_delete.emplace_back(n, c);
    });

    for (auto & c : to_delete) {
        m_ptr->m_children.erase(c.first);
        c.second.detach_core(events);
    }

    events.push_back({event::Finished, *this, {}});
    notify(events, l);
}

std::vector<log_entry> log_tree::node::get_entries() const {
    auto l = lock();
    return m_ptr->m_entries;
}

name_map<lean::log_tree::node> log_tree::node::get_children() const {
    auto l = lock();
    return m_ptr->m_children;
}

void log_tree::node::remove_child(name const & n) const {
    auto l = lock();
    if (auto c = m_ptr->m_children.find(n)) {
        m_ptr->m_children.erase(n);
        std::vector<event> events;
        c->detach_core(events);
        notify(events, l);
    }
}

name_map<log_tree::node> log_tree::node::get_used_children() const {
    auto l = lock();
    name_map<node> used_children;
    m_ptr->m_used_names.for_each([&] (name const & n) {
        if (auto c = m_ptr->m_children.find(n)) {
            used_children.insert(n, *c);
        }
    });
    return used_children;
}

void log_tree::node::reuse(name const & n) const {
    auto l = lock();
    m_ptr->m_used_names.insert(n);
}

name_set log_tree::node::get_used_names() const {
    auto l = lock();
    return m_ptr->m_used_names;
}

gtask log_tree::node::get_producer() const {
    auto l = lock();
    return m_ptr->m_producer;
}

void log_tree::node::print() const {
    print_to(std::cerr, 0);
}

void log_tree::node::print_to(std::ostream & out, unsigned indent) const {
    indent += 2;

    auto l = lock();
    auto begin = m_ptr->m_location.m_range.m_begin, end = m_ptr->m_location.m_range.m_end;
    out << m_ptr->m_location.m_file_name
        << ": " << begin.first << ":" << begin.second << " -- " << end.first << ":" << end.second << ": "
        << m_ptr->m_description << " ("
        << m_ptr->m_entries.size()
        << " entries, producer = "
        << std::hex << reinterpret_cast<uintptr_t>(m_ptr->m_producer.get()) << std::dec
        << ")" << std::endl;

    if (auto prod = m_ptr->m_producer) {
        if (auto ex = prod->peek_exception()) {
            for (unsigned i = 0; i < indent; i++) out << ' ';
            out << "producer threw exception: ";
            try {
                std::rethrow_exception(ex);
            } catch (std::exception & ex) {
                out << ex.what();
            } catch (cancellation_exception) {
                out << "<cancelled>";
            } catch (...) {
                out << "<unknown exception>";
            }
            out << "\n";
        }
    }

    auto children = m_ptr->m_children;
    auto used_names = m_ptr->m_used_names;
    l.unlock();

    children.for_each([&] (name const & n, log_tree::node const & c) {
        for (unsigned i = 0; i < indent; i++) out << ' ';
        out << n;
        if (!used_names.contains(n))
            out << " (unused)";
        out << ": ";
        c.print_to(out, indent);
    });
}

gtask log_tree::node::wait_for_finish() const {
    auto t = *this;
    return mk_dependency_task([t] (buffer<gtask> & deps) {
        t.for_each([&] (node const & n) {
            if (auto prod = n.get_producer())
                deps.push_back(prod);
            return true;
        });
    });
}

bool log_tree::node::has_entry_now(std::function<bool(log_entry const &)> const & fn) const { // NOLINT
    bool res = false;
    for_each([&] (node const & n) {
        if (res) return false;
        for (auto & e : n.get_entries()) {
            if (fn(e)) {
                res = true;
                break;
            }
        }
        return !res;
    });
    return res;
}

task<bool> log_tree::node::has_entry(std::function<bool(log_entry const &)> const & fn) const { // NOLINT
    auto t = *this;
    return task_builder<bool>([t, fn] { return t.has_entry_now(fn); }).depends_on(wait_for_finish()).build();
}

LEAN_THREAD_PTR(log_tree::node, g_log_tree);
scope_log_tree_core::scope_log_tree_core(log_tree::node * lt) : flet<log_tree::node *>(g_log_tree, lt) {}

log_tree::node & logtree() {
    if (g_log_tree) {
        return *g_log_tree;
    } else {
        throw exception("no log tree in scope");
    }
}

scope_log_tree::scope_log_tree(log_tree::node const & lt) : m_node(lt), m_scope(&m_node) {
    m_node.clear_entries();
}

scope_log_tree::~scope_log_tree() {
    logtree().finish();
}

scope_log_tree::scope_log_tree(std::string const & desc, pos_range const & pos) :
        scope_log_tree(logtree().mk_child({}, desc, {logtree().get_location().m_file_name, pos})) {}

scope_log_tree::scope_log_tree(std::string const & desc) :
        scope_log_tree(logtree().mk_child({}, desc, logtree().get_location())) {}

scope_log_tree::scope_log_tree() : scope_log_tree(std::string()) {}

}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: cat %s | %cling 2>&1 | FileCheck %s

// This file should be used as regression test for the value printing subsystem
// Reproducers of fixed bugs should be put here

extern "C" int mustPrintFirst() { return 6; }
mustPrintFirst
// CHECK: (int (*)()) Function

// PR #93006
.rawInput 1
extern "C" int printf(const char* fmt, ...);
class A {
public:
  int Var;
  A(int arg) { Var = arg; }
  int someFunc(float) { return 42; }
  ~A() { printf("A d'tor\n"); }
};

const A& foo(const A& arg) { return arg; }
A foo2(const A& arg) { return A(42); }
.rawInput 0

foo(A(12)).Var
// CHECK: (const int) 12
// CHECK: A d'tor
// End PR #93006

// myvector.end() failed to print (roottest/cling/stl/default/VectorSort.C)
foo2(A(42))
// CHECK: (A) @0x{{[0-9a-f]+}}
// CHECK: A d'tor

 // Savannah #96523
int *p = (int*)0x123;
p // CHECK: (int *) 0x123
const int *q = (int*)0x123;
q // CHECK: (const int *) 0x123 <invalid memory address>

0.00001234L // CHECK-NEXT: (long double) 1.2340000e-05L

// PR ROOT-5467
&A::someFunc // CHECK: (int (A::*)(float)) Function @0x{{[0-9a-f]+}}

nullptr // CHECK: (nullptr_t) nullptr

true // CHECK: (bool) true
false // CHECK: (bool) false

unordered_multiset<float> {1} // ROOT-7310
// expected-error@2 {{use of undeclared identifier 'unordered_multiset'}}
// expected-error@2 {{expected '(' for function-style cast or type construction}}
// expected-error@2 {{initializer list cannot be used on the right hand side of operator '>'}}

#include <unordered_set>
std::unordered_multiset<float> {1}
// FIXME: BROKEN_ON_LINUX-CHECK: (std::unordered_multiset<float>) { 1.00000f }

// ROOT-7426
#include <string>
#include <vector>
std::vector<std::string> a = { "a", "b", "c" } // CHECK: (std::vector<std::string> &) { "a", "b", "c" }
a // CHECK: (std::vector<std::string> &) { "a", "b", "c" }
a[0] // CHECK: ({{.*}} &) "a"

// ROOT-7918
struct Enumer {
#ifndef _WIN32
  // This variant fails on Windows, and seems conforming behaviour to do so
  enum H {  h = (unsigned long long )-1 };
#else
  enum H : unsigned long long { h = (unsigned long long )-1 };
#endif
};
Enumer::h
// CHECK: (Enumer::H) (Enumer::H::h) : (unsigned long{{( long)?}}) 18446744073709551615

// ROOT-7837
auto bla=[](double *x, double *par, int blub){return x[0]*blub;} // CHECK: ((lambda) &) @0x{{[0-9a-f]+}}

#include <functional>
using namespace std::placeholders;
auto fn_moo = std::bind (bla, _1,_2,10) // CHECK: ({{.*\(lambda\).*}}> &) @0x{{[0-9a-f]+}}

// Make sure cling survives
12 // CHECK: (int) 12

// ROOT-8077
.rawInput 1
#include <string>
void f(std::string) {}
.rawInput 0
f // CHECK: (void (*)(std::string)) Function @0x{{[0-9a-f]+}}
// CHECK: at input_line_{{[0-9].*}}:1:
// CHECK: void f(std::string) {}

class notapointer {};
struct OverloadedAddrOf {
  notapointer operator&() {
    return notapointer();
  }
};
OverloadedAddrOf overloadedAddrOf
// CHECK: (OverloadedAddrOf &) @0x{{[0-9a-f]+}}

namespace PR180 {
  class base {};

  template <class B>
  class Derived : public B {};
  using Foo = Derived<base>;
}
auto bar = PR180::Foo()
// CHECK: (PR180::Derived<PR180::base> &) @0x{{[0-9a-f]+}}
<commit_msg>Test printValue on unutterable types.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: cat %s | %cling 2>&1 | FileCheck %s

// This file should be used as regression test for the value printing subsystem
// Reproducers of fixed bugs should be put here

extern "C" int mustPrintFirst() { return 6; }
mustPrintFirst
// CHECK: (int (*)()) Function

// PR #93006
.rawInput 1
extern "C" int printf(const char* fmt, ...);
class A {
public:
  int Var;
  A(int arg) { Var = arg; }
  int someFunc(float) { return 42; }
  ~A() { printf("A d'tor\n"); }
};

const A& foo(const A& arg) { return arg; }
A foo2(const A& arg) { return A(42); }
.rawInput 0

foo(A(12)).Var
// CHECK: (const int) 12
// CHECK: A d'tor
// End PR #93006

// myvector.end() failed to print (roottest/cling/stl/default/VectorSort.C)
foo2(A(42))
// CHECK: (A) @0x{{[0-9a-f]+}}
// CHECK: A d'tor

 // Savannah #96523
int *p = (int*)0x123;
p // CHECK: (int *) 0x123
const int *q = (int*)0x123;
q // CHECK: (const int *) 0x123 <invalid memory address>

0.00001234L // CHECK-NEXT: (long double) 1.2340000e-05L

// PR ROOT-5467
&A::someFunc // CHECK: (int (A::*)(float)) Function @0x{{[0-9a-f]+}}

nullptr // CHECK: (nullptr_t) nullptr

true // CHECK: (bool) true
false // CHECK: (bool) false

unordered_multiset<float> {1} // ROOT-7310
// expected-error@2 {{use of undeclared identifier 'unordered_multiset'}}
// expected-error@2 {{expected '(' for function-style cast or type construction}}
// expected-error@2 {{initializer list cannot be used on the right hand side of operator '>'}}

#include <unordered_set>
std::unordered_multiset<float> {1}
// FIXME: BROKEN_ON_LINUX-CHECK: (std::unordered_multiset<float>) { 1.00000f }

// ROOT-7426
#include <string>
#include <vector>
std::vector<std::string> a = { "a", "b", "c" } // CHECK: (std::vector<std::string> &) { "a", "b", "c" }
a // CHECK: (std::vector<std::string> &) { "a", "b", "c" }
a[0] // CHECK: ({{.*}} &) "a"

// ROOT-7918
struct Enumer {
#ifndef _WIN32
  // This variant fails on Windows, and seems conforming behaviour to do so
  enum H {  h = (unsigned long long )-1 };
#else
  enum H : unsigned long long { h = (unsigned long long )-1 };
#endif
};
Enumer::h
// CHECK: (Enumer::H) (Enumer::H::h) : (unsigned long{{( long)?}}) 18446744073709551615

// ROOT-7837
auto bla=[](double *x, double *par, int blub){return x[0]*blub;} // CHECK: ((lambda) &) @0x{{[0-9a-f]+}}

#include <functional>
using namespace std::placeholders;
auto fn_moo = std::bind (bla, _1,_2,10) // CHECK: ({{.*\(lambda\).*}}> &) @0x{{[0-9a-f]+}}

// Make sure cling survives
12 // CHECK: (int) 12

// ROOT-8077
.rawInput 1
#include <string>
void f(std::string) {}
.rawInput 0
f // CHECK: (void (*)(std::string)) Function @0x{{[0-9a-f]+}}
// CHECK: at input_line_{{[0-9].*}}:1:
// CHECK: void f(std::string) {}

class notapointer {};
struct OverloadedAddrOf {
  notapointer operator&() {
    return notapointer();
  }
};
OverloadedAddrOf overloadedAddrOf
// CHECK: (OverloadedAddrOf &) @0x{{[0-9a-f]+}}

// Much more important than what cling prints: cling survives this!
.rawInput
auto func() { class X {} x; return x; };
namespace WithUnnamed { namespace { struct Y {} y; } Y z; }
.rawInput
//func
func()
WithUnnamed::y
WithUnnamed::z // CHECK: (WithUnnamed::

namespace PR180 {
  class base {};

  template <class B>
  class Derived : public B {};
  using Foo = Derived<base>;
}
auto bar = PR180::Foo()
// CHECK: (PR180::Derived<PR180::base> &) @0x{{[0-9a-f]+}}
<|endoftext|>


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

// int _tmain(int argc, _TCHAR* argv[])
// {
//	return 0;
// }

#include <tbb/task_group.h>
#include <tbb/tbb_thread.h> // for sleep functionality
// An alternative can be taken from
// https://repo.anl-external.org/repos/BlueTBB/tbb30_104oss/src/rml/perfor/tbb_simple.cpp
//void MilliSleep(unsigned milliseconds) {
//#if ( _WIN32 || _WIN64 )
//    Sleep(milliseconds); // accepts DWORD: 32-bit unsigned integer
//#else
//    usleep(milliseconds * 1000); // accepts mysterious useconds_t
//#endif
//}

#include <iostream>
#include <stdio.h> //// MOVE TO iostreams TODO
#include <stdlib.h>

using namespace tbb;

// No matter which main function we use,
// we want to disable buffering on stdout before we do anything
// TODO this is nasty
struct Dummy { Dummy() { setbuf(stdout, NULL); } };
static Dummy d;

#if 0 // just spin up and run four simple tasks, using lambdas
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds

int main(int argc, char *argv[]) {
    puts("Starting...");

    task_group g;

    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 1] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 2] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 3] started"); } );

    g.run_and_wait( [&]{ this_tbb_thread::sleep(oneSecond); puts("A message from the main thread"); } );

    return EXIT_SUCCESS;
}
#endif

#if 0 // fun with the idea of futures

// #include "tbb/atomic.h"

// Faking/implementing futures with TBB tasks

// Note that mutable state is held in its own struct,
// as TBB's run(1) function accepts its arg by const reference,
// forcing us to handle mutation via a pointer to a mutable value
// and not within the MyFuture class itself.

// We use TBB's sleep functionality, to avoid C++14 dependency
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds
const tbb::tick_count::interval_t threeSeconds(3.0);
const tbb::tick_count::interval_t tenSeconds(10.0);

int main(int argc, char *argv[]) {
    puts("Starting...");

    class MyFuture {
      struct MutableState {
        MutableState() : result(0) { }
        int result;
      };

      class Executor {
        /*not const*/ MutableState * const msPtr;
      public:
        Executor(MutableState *m) : msPtr(m) { };

        void operator()() const {
          puts("[from task] Task is running. Now for the pause...");
//        this_tbb_thread::sleep( threeSeconds );
          this_tbb_thread::sleep( tenSeconds );
          puts("[from task] Task pause complete, assigning output...");
          msPtr->result = 3;
          return;
        }
      };

      task_group   tg;
      MutableState ms;
      const Executor e; // must be const in order to call run(1)

    public:
      MyFuture() : e(&ms) // just invoke default constructor of tg and ms
      { }

      void begin() {
        tg.run( this->e );
      }

      int force() /*const*/ {
        tg.wait();
        return ms.result;
      }
    };

    MyFuture f; // not const: we mutate internally

    puts("Now to run");
    f.begin();
    puts("Running. Now to do a couple of prints with a pause between each.");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after a second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    puts("And now to wait...");

    printf( "%d\n", f.force() );

    return EXIT_SUCCESS;
}
#endif

#if 1
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds

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

  puts("Here we go");

  int myInt = 0;

  tg.run( [&](){
    myInt = 3;
    puts("[from task] Now to sleep");
    this_tbb_thread::sleep( oneSecond );
    puts("[from task] Done sleeping");
  } );

  puts("Now to wait");
  tg.wait();
  puts("Done waiting");
  printf("Value is now %d\n",myInt);

  return EXIT_SUCCESS;
}

#endif

<commit_msg>Another lambda-based example, showing const issues<commit_after>// #include "stdafx.h"

// int _tmain(int argc, _TCHAR* argv[])
// {
//	return 0;
// }

#include <tbb/task_group.h>
#include <tbb/tbb_thread.h> // for sleep functionality
// An alternative can be taken from
// https://repo.anl-external.org/repos/BlueTBB/tbb30_104oss/src/rml/perfor/tbb_simple.cpp
//void MilliSleep(unsigned milliseconds) {
//#if ( _WIN32 || _WIN64 )
//    Sleep(milliseconds); // accepts DWORD: 32-bit unsigned integer
//#else
//    usleep(milliseconds * 1000); // accepts mysterious useconds_t
//#endif
//}

#include <iostream>
#include <stdio.h> //// MOVE TO iostreams TODO
#include <stdlib.h>

using namespace tbb;

// No matter which main function we use,
// we want to disable buffering on stdout before we do anything
// TODO this is nasty
struct Dummy { Dummy() { setbuf(stdout, NULL); } };
static Dummy d;

#if 0 // just spin up and run four simple tasks, using lambdas
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds

int main(int argc, char *argv[]) {
    puts("Starting...");

    task_group g;

    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 1] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 2] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 3] started"); } );

    g.run_and_wait( [&]{ this_tbb_thread::sleep(oneSecond); puts("A message from the main thread"); } );

    return EXIT_SUCCESS;
}
#endif

#if 0 // fun with the idea of futures

// #include "tbb/atomic.h"

// Faking/implementing futures with TBB tasks

// Note that mutable state is held in its own struct,
// as TBB's run(1) function accepts its arg by const reference,
// forcing us to handle mutation via a pointer to a mutable value
// and not within the MyFuture class itself.

// We use TBB's sleep functionality, to avoid C++14 dependency
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds
const tbb::tick_count::interval_t threeSeconds(3.0);
const tbb::tick_count::interval_t tenSeconds(10.0);

int main(int argc, char *argv[]) {
    puts("Starting...");

    class MyFuture {
      struct MutableState {
        MutableState() : result(0) { }
        int result;
      };

      class Executor {
        /*not const*/ MutableState * const msPtr;
      public:
        Executor(MutableState *m) : msPtr(m) { };

        void operator()() const {
          puts("[from task] Task is running. Now for the pause...");
//        this_tbb_thread::sleep( threeSeconds );
          this_tbb_thread::sleep( tenSeconds );
          puts("[from task] Task pause complete, assigning output...");
          msPtr->result = 3;
          return;
        }
      };

      task_group   tg;
      MutableState ms;
      const Executor e; // must be const in order to call run(1)

    public:
      MyFuture() : e(&ms) // just invoke default constructor of tg and ms
      { }

      void begin() {
        tg.run( this->e );
      }

      int force() /*const*/ {
        tg.wait();
        return ms.result;
      }
    };

    MyFuture f; // not const: we mutate internally

    puts("Now to run");
    f.begin();
    puts("Running. Now to do a couple of prints with a pause between each.");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after a second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    puts("And now to wait...");

    printf( "%d\n", f.force() );

    return EXIT_SUCCESS;
}
#endif

#if 0
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds

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

  puts("Here we go");

  int myInt = 0;

  tg.run( [&](){
    myInt = 3;
    puts("[from task] Now to sleep");
    this_tbb_thread::sleep( oneSecond );
    puts("[from task] Done sleeping");
  } );

  puts("Now to wait");
  tg.wait();
  puts("Done waiting");
  printf("Value is now %d\n",myInt);

  return EXIT_SUCCESS;
}

#endif

#if 1
struct SelfMutatingFuture {
  int myInt;
  SelfMutatingFuture() : myInt(0) { }

  void operator()() {
    this->myInt = 3;
  }
};

int main(int argc, char *argv[]) {
  task_group tg;
  SelfMutatingFuture s;

  puts("Here we go");

// We could use run_and_wait, but to be more illustrative, we don't

// tg.run(s); // forbidden: operator()() is not const

// lambda itself is const, doesn't matter that 's' (captured by ref) is mutated
  tg.run( [&](){
    s();
  } );

  puts("Now to wait");
  tg.wait();
  puts("Done waiting");
  printf("Value is now %d\n",s.myInt);

  return EXIT_SUCCESS;
}
#endif

<|endoftext|>


<commit_before>// Loosely based on https://repo.anl-external.org/repos/BlueTBB/tbb30_104oss/src/rml/perfor/tbb_simple.cpp

// #include "stdafx.h"

// int _tmain(int argc, _TCHAR* argv[])
// {
//	return 0;
// }

#include "tbb/task_group.h"

#include <iostream>
#include <stdio.h> //// MOVE TO iostreams TODO
#include <stdlib.h>

//#include <chrono> // for 2s to mean 2 seconds
//using namespace std::literals::chrono_literals; // as above
//#include <thread> // for std::this_thread::sleep_for(1);

#include <tbb/mutex.h>
#include <tbb/tbb_thread.h>

// tbb::mutex my_mutex;

#if _WIN32||_WIN64
//#include <Windows.h> /* Sleep */
#else
//// #error Only tested on Windows! TODO
// #include <unistd.h>  /* usleep */
#endif

using namespace tbb;

#if 0 // totally inappropriate and broken use of subclassing of tbb::task, just for giggles
// see https://www.threadingbuildingblocks.org/docs/help/reference/task_scheduler/task_cls.htm
#include "tbb/task.h"

class TrivialTask : public tbb::task {
public:

    TrivialTask() {	}

    task* parent() const { // the "parent" member-function is confusingly referred to as "the successor attribute"
        return NULL;
    }

    task* execute() override {
        puts("Hello from my task!");
        return NULL;
    }

    ~TrivialTask() {
        puts("Destroying my task");
    }
};

// allocate_continuation
// #include <stdio.h>
// #include <stdlib.h>
int main(int argc, char *argv[]) {
    // use TBB's custom allocator, along the lines shown in
    // https://www.threadingbuildingblocks.org/docs/help/tbb_userguide/Simple_Example_Fibonacci_Numbers.htm#tutorial_Simple_Example_Fibonacci_Numbers

    // see also https://www.threadingbuildingblocks.org/docs/help/reference/task_scheduler/task_allocation.htm

    {
        // looking at task_allocation.htm this should use:
        // "cancellation group is the current innermost cancellation group. "
        ////// WHICH WE DON'T HAVE!?!?! shouldn't this cause an assert failure?
        task& t = *new(task::allocate_root()) TrivialTask; // following http://fulla.fnal.gov/intel/tbb/html/a00249.html

        auto count1 = t.ref_count();

        t.execute(); // No concurrency! Hence 'totally inappropriate'
                     // t.decrement_ref_count(); causes underflow!
                     //if ( NULL != t.parent ) {
                     //}

                     // "Because there is no placement delete expression[...]" https://en.wikipedia.org/w/index.php?title=Placement_syntax&oldid=674756226#Custom_allocators

                     // not using standard 'new' so can't use standard 'delete'
                     //delete (task::allocate_root()) &t; // kaboom! VS2010 picks up a double-free problem. Looks like we're missing something important....????

        auto count2 = t.ref_count();

        t.decrement_ref_count(); // same as   t.set_ref_count(0);

    }

    return EXIT_SUCCESS;
}
#endif

#if 0 // just spin up and run four simple tasks, using lambdas
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds

int main(int argc, char *argv[]) {
    puts("Starting...");

    task_group g;

    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 1] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 2] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 3] started"); } );

    g.run_and_wait( [&]{ this_tbb_thread::sleep(oneSecond); puts("A message from the main thread"); } );

    return EXIT_SUCCESS;
}
#endif

#if 1 // fun with the idea of futures

// #include "tbb/atomic.h"

// Faking/implementing futures with TBB tasks

// Note that mutable state is held in its own struct,
// as TBB's run(1) function accepts its arg by const reference,
// forcing us to handle mutation via a pointer to a mutable value
// and not within the MyFuture class itself.

// we use TBB's sleep functionality, to avoid C++14 dependency
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds
const tbb::tick_count::interval_t threeSeconds(3.0);
const tbb::tick_count::interval_t tenSeconds(10.0);

int main(int argc, char *argv[]) {
    puts("Starting...");

    class MyFuture {
      struct MutableState {
        MutableState() : result(0) { }
        int result;
      };

      class Executor {
        /*not const*/ MutableState * const msPtr;
      public:
        Executor(MutableState *m) : msPtr(m) { };

        void operator()() const {
          puts("[from task] Task is running. Now for the pause...");
//        this_tbb_thread::sleep( threeSeconds );
          this_tbb_thread::sleep( tenSeconds );
          puts("[from task] Task pause complete, assigning output...");
          msPtr->result = 3;
          return;
        }
      };

      task_group   tg;
      MutableState ms;
      const Executor e; // must be const in order to call run(1)

    public:
      MyFuture() : e(&ms) // just invoke default constructor of tg and ms
      { }

      void begin() {
        tg.run( this->e );
      }

      int force() /*const*/ {
        tg.wait();
        return ms.result;
      }
    };

    MyFuture f; // not const: we mutate internally

    puts("Now to run");
    f.begin();
    puts("Running. Now to do a couple of prints with a pause between each.");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after a second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    puts("And now to wait...");

    printf( "%d\n", f.force() );

    return EXIT_SUCCESS;
}
#endif

#if 0 // the fib example from the web
int fib(int n) {
    int ret;
    if (n < 2) {
        ret = n;
    }
    else {
        int x, y;
        task_group g;

        x = y = 9;

        // g.run( [&]{my_mutex.lock();/* x=fib(n-1); */ puts("Now:\n"); getchar(); my_mutex.unlock();} ); // spawn a task

        g.run([&] {
            tbb::mutex::scoped_lock lock(my_mutex);
            /* x=fib(n-1); */ puts("Now:\n"); getchar();
        }); // spawn a task

            // g.run( [&]{my_mutex.lock();/* y=fib(n-2); */ puts("Now:\n"); getchar(); my_mutex.unlock();} ); // spawn another task
        g.run([&] {
            tbb::mutex::scoped_lock lock(my_mutex);/* y=fib(n-2); */ puts("Now:\n"); getchar();
        }); // spawn another task

        g.wait();                // wait for both tasks to complete

        ret = x + y;
    }

    return ret;
} // - See more at: https://www.threadingbuildingblocks.org/tutorial-intel-tbb-task-based-programming#sthash.EzgRXzaB.dpuf

int main(int argc, char *argv[]) {
    std::cout << fib(33);

    // getchar();
    return EXIT_SUCCESS;
}

#endif
<commit_msg>Take another look at our whacky first demo<commit_after>// Loosely based on https://repo.anl-external.org/repos/BlueTBB/tbb30_104oss/src/rml/perfor/tbb_simple.cpp

// #include "stdafx.h"

// int _tmain(int argc, _TCHAR* argv[])
// {
//	return 0;
// }

#include "tbb/task_group.h"

#include <iostream>
#include <stdio.h> //// MOVE TO iostreams TODO
#include <stdlib.h>

//#include <chrono> // for 2s to mean 2 seconds
//using namespace std::literals::chrono_literals; // as above
//#include <thread> // for std::this_thread::sleep_for(1);

#include <tbb/mutex.h>
#include <tbb/tbb_thread.h>

// tbb::mutex my_mutex;

#if _WIN32||_WIN64
//#include <Windows.h> /* Sleep */
#else
//// #error Only tested on Windows! TODO
// #include <unistd.h>  /* usleep */
#endif

using namespace tbb;

#if 1 // totally inappropriate and broken use of subclassing of tbb::task, just for giggles
// see https://www.threadingbuildingblocks.org/docs/help/reference/task_scheduler/task_cls.htm
#include "tbb/task.h"

class TrivialTask : public tbb::task {
public:

    TrivialTask() { }

    task* parent() const { // the "parent" member-function is confusingly referred to as "the successor attribute"
        return NULL;
    }

    task* execute() override {
        puts("Hello from my task!");
        return NULL;
    }

    ~TrivialTask() {
        puts("Destroying my task");
    }
};

// allocate_continuation
// #include <stdio.h>
// #include <stdlib.h>
int main(int argc, char *argv[]) {
  // use TBB's custom allocator, along the lines shown in
  // https://www.threadingbuildingblocks.org/docs/help/tbb_userguide/Simple_Example_Fibonacci_Numbers.htm#tutorial_Simple_Example_Fibonacci_Numbers

  // see also https://www.threadingbuildingblocks.org/docs/help/reference/task_scheduler/task_allocation.htm

  // looking at task_allocation.htm this should use:
  // "cancellation group is the current innermost cancellation group. "
  ////// which we don't have!? shouldn't this cause an assert failure?
  task& t = *new(task::allocate_root()) TrivialTask; // following http://fulla.fnal.gov/intel/tbb/html/a00249.html

  auto count1 = t.ref_count();

  t.execute(); // No concurrency! Hence 'totally inappropriate'
 // t.decrement_ref_count(); causes underflow!
 // if ( NULL != t.parent ) {
 // }

 // "Because there is no placement delete expression[...]" https://en.wikipedia.org/w/index.php?title=Placement_syntax&oldid=674756226#Custom_allocators

 // not using standard 'new' so can't use standard 'delete'
 // delete (task::allocate_root()) &t; // kaboom! VS2010 picks up a double-free problem. Looks like we're missing something important....????

  auto count2 = t.ref_count();
  t.decrement_ref_count(); // same as   t.set_ref_count(0);
  return EXIT_SUCCESS;
}
#endif

#if 0 // just spin up and run four simple tasks, using lambdas
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds

int main(int argc, char *argv[]) {
    puts("Starting...");

    task_group g;

    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 1] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 2] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 3] started"); } );

    g.run_and_wait( [&]{ this_tbb_thread::sleep(oneSecond); puts("A message from the main thread"); } );

    return EXIT_SUCCESS;
}
#endif

#if 0 // fun with the idea of futures

// #include "tbb/atomic.h"

// Faking/implementing futures with TBB tasks

// Note that mutable state is held in its own struct,
// as TBB's run(1) function accepts its arg by const reference,
// forcing us to handle mutation via a pointer to a mutable value
// and not within the MyFuture class itself.

// we use TBB's sleep functionality, to avoid C++14 dependency
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds
const tbb::tick_count::interval_t threeSeconds(3.0);
const tbb::tick_count::interval_t tenSeconds(10.0);

int main(int argc, char *argv[]) {
    puts("Starting...");

    class MyFuture {
      struct MutableState {
        MutableState() : result(0) { }
        int result;
      };

      class Executor {
        /*not const*/ MutableState * const msPtr;
      public:
        Executor(MutableState *m) : msPtr(m) { };

        void operator()() const {
          puts("[from task] Task is running. Now for the pause...");
//        this_tbb_thread::sleep( threeSeconds );
          this_tbb_thread::sleep( tenSeconds );
          puts("[from task] Task pause complete, assigning output...");
          msPtr->result = 3;
          return;
        }
      };

      task_group   tg;
      MutableState ms;
      const Executor e; // must be const in order to call run(1)

    public:
      MyFuture() : e(&ms) // just invoke default constructor of tg and ms
      { }

      void begin() {
        tg.run( this->e );
      }

      int force() /*const*/ {
        tg.wait();
        return ms.result;
      }
    };

    MyFuture f; // not const: we mutate internally

    puts("Now to run");
    f.begin();
    puts("Running. Now to do a couple of prints with a pause between each.");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after a second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    puts("And now to wait...");

    printf( "%d\n", f.force() );

    return EXIT_SUCCESS;
}
#endif

#if 0 // the fib example from the web
int fib(int n) {
    int ret;
    if (n < 2) {
        ret = n;
    }
    else {
        int x, y;
        task_group g;

        x = y = 9;

        // g.run( [&]{my_mutex.lock();/* x=fib(n-1); */ puts("Now:\n"); getchar(); my_mutex.unlock();} ); // spawn a task

        g.run([&] {
            tbb::mutex::scoped_lock lock(my_mutex);
            /* x=fib(n-1); */ puts("Now:\n"); getchar();
        }); // spawn a task

            // g.run( [&]{my_mutex.lock();/* y=fib(n-2); */ puts("Now:\n"); getchar(); my_mutex.unlock();} ); // spawn another task
        g.run([&] {
            tbb::mutex::scoped_lock lock(my_mutex);/* y=fib(n-2); */ puts("Now:\n"); getchar();
        }); // spawn another task

        g.wait();                // wait for both tasks to complete

        ret = x + y;
    }

    return ret;
} // - See more at: https://www.threadingbuildingblocks.org/tutorial-intel-tbb-task-based-programming#sthash.EzgRXzaB.dpuf

int main(int argc, char *argv[]) {
    std::cout << fib(33);

    // getchar();
    return EXIT_SUCCESS;
}

#endif
<|endoftext|>


<commit_before>#include <boost/algorithm/string.hpp>
#include <iostream>
using namespace std;

const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const int alphabet_length = alphabet.length();

string get_keyphrase(const string& text, const string& keyword)
{
  /* Returns the Vigenere keyword of appropriate length (in all caps) for a
   * given text (either plaintext or ciphertext) and keyword.
   */
  string keyphrase = "";
  string caps_keyword = boost::algorithm::to_upper_copy<string>(keyword);

  size_t keyword_length = keyword.length();
  size_t text_length = text.length();

  for (int i = 0; i < text_length; i++)
  {
    keyphrase += caps_keyword[i % keyword_length];
  }

  return keyphrase;
}

string encrypt(const string& plaintext, const string& keyword)
{
  /* Returns the ciphertext produced by encrypting the plaintext using the
   * given keyword and the Vigenere Cipher
   * (http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher).
   */

  string ciphertext = "";
  string caps_plaintext = boost::algorithm::to_upper_copy<string>(plaintext);
  string keyphrase = get_keyphrase(plaintext, keyword);

  for (int i = 0; i < plaintext.length(); i++)
  {
    int plaintext_index = alphabet.find(caps_plaintext[i]);
    int advance_by = alphabet.find(keyphrase[i]);
    int ciphertext_index = (plaintext_index + advance_by) % alphabet_length;

    ciphertext += alphabet[ciphertext_index];
  }

  return ciphertext;
}

string decrypt(const string& ciphertext, const string& keyword)
{
  /* Returns the plaintext produced by decrypting the ciphertext using the
   * given keyword and the Vigenere Cipher
   * (http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher).
   */
  string plaintext = "";
  string caps_ciphertext = boost::algorithm::to_upper_copy<string>(ciphertext);
  string keyphrase = get_keyphrase(ciphertext, keyword);

  for (int i = 0; i < ciphertext.length(); i++)
  {
    int ciphertext_index = alphabet.find(caps_ciphertext[i]);
    int reverse_by = alphabet.find(keyphrase[i]);
    int plaintext_index = (ciphertext_index - reverse_by) % alphabet_length;

    plaintext += alphabet[plaintext_index];
  }

  return plaintext;
}
<commit_msg>Fix of typing problems with some interesting discoveries about modulus.<commit_after>#include <boost/algorithm/string.hpp>
#include <iostream>
using namespace std;

const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const int alphabet_length = (int) alphabet.length();

string get_keyphrase(const string& text, const string& keyword)
{
  /* Returns the Vigenere keyword of appropriate length (in all caps) for a
   * given text (either plaintext or ciphertext) and keyword.
   */
  string keyphrase = "";
  string caps_keyword = boost::algorithm::to_upper_copy<string>(keyword);

  size_t keyword_length = keyword.length();
  size_t text_length = text.length();

  for (int i = 0; i < text_length; i++)
  {
    keyphrase += caps_keyword[i % keyword_length];
  }

  return keyphrase;
}

string encrypt(const string& plaintext, const string& keyword)
{
  /* Returns the ciphertext produced by encrypting the plaintext using the
   * given keyword and the Vigenere Cipher
   * (http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher).
   */

  string ciphertext = "";
  string caps_plaintext = boost::algorithm::to_upper_copy<string>(plaintext);
  string keyphrase = get_keyphrase(plaintext, keyword);

  for (int i = 0; i < plaintext.length(); i++)
  {
    int plaintext_index = (int) alphabet.find(caps_plaintext[i]);
    int advance_by = (int) alphabet.find(keyphrase[i]);
    int ciphertext_index = (plaintext_index + advance_by) % alphabet_length;

    ciphertext += alphabet[ciphertext_index];
  }

  return ciphertext;
}

string decrypt(const string& ciphertext, const string& keyword)
{
  /* Returns the plaintext produced by decrypting the ciphertext using the
   * given keyword and the Vigenere Cipher
   * (http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher).
   */
  string plaintext = "";
  string caps_ciphertext = boost::algorithm::to_upper_copy<string>(ciphertext);
  string keyphrase = get_keyphrase(ciphertext, keyword);

  for (int i = 0; i < ciphertext.length(); i++)
  {
    int ciphertext_index = (int) alphabet.find(caps_ciphertext[i]);
    int reverse_by = (int) alphabet.find(keyphrase[i]);
    int plaintext_index = (ciphertext_index - reverse_by) % alphabet_length;

    cout << ciphertext_index << endl;
    cout << reverse_by << endl;
    cout << plaintext_index << endl;
    cout << endl;

    plaintext += alphabet[plaintext_index];
  }

  return plaintext;
}
<|endoftext|>