<commit_before>// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "key.h"

#include "crypto/sha2.h"
#include "eccryptoverify.h"
#include "pubkey.h"
#include "random.h"

#include <secp256k1.h>
#include "ecwrapper.h"

//! anonymous namespace
namespace {

class CSecp256k1Init {
public:
    CSecp256k1Init() {
        secp256k1_start(SECP256K1_START_SIGN);
    }
    ~CSecp256k1Init() {
        secp256k1_stop();
    }
};
static CSecp256k1Init instance_of_csecp256k1;

} // anon namespace

bool CKey::Check(const unsigned char *vch) {
    return eccrypto::Check(vch);
}

void CKey::MakeNewKey(bool fCompressedIn) {
    do {
        GetRandBytes(vch, sizeof(vch));
    } while (!Check(vch));
    fValid = true;
    fCompressed = fCompressedIn;
}

bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) {
    if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
        return false;
    fCompressed = fCompressedIn;
    fValid = true;
    return true;
}

CPrivKey CKey::GetPrivKey() const {
    assert(fValid);
    CPrivKey privkey;
    int privkeylen, ret;
    privkey.resize(279);
    privkeylen = 279;
    ret = secp256k1_ec_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed);
    assert(ret);
    privkey.resize(privkeylen);
    return privkey;
}

CPubKey CKey::GetPubKey() const {
    assert(fValid);
    CPubKey result;
    int clen = 65;
    int ret = secp256k1_ec_pubkey_create((unsigned char*)result.begin(), &clen, begin(), fCompressed);
    assert((int)result.size() == clen);
    assert(ret);
    assert(result.IsValid());
    return result;
}

bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
    if (!fValid)
        return false;
    vchSig.resize(72);
    int nSigLen = 72;
    CKey nonce;
    do {
        nonce.MakeNewKey(true);
        if (secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), nonce.begin()))
            break;
    } while(true);
    vchSig.resize(nSigLen);
    return true;
}

bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
    if (pubkey.IsCompressed() != fCompressed) {
        return false;
    }
    unsigned char rnd[8];
    std::string str = "Bitcoin key verification\n";
    GetRandBytes(rnd, sizeof(rnd));
    uint256 hash;
    CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize((unsigned char*)&hash);
    std::vector<unsigned char> vchSig;
    Sign(hash, vchSig);
    return pubkey.Verify(hash, vchSig);
}

bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
    if (!fValid)
        return false;
    vchSig.resize(65);
    int rec = -1;
    CKey nonce;
    do {
        nonce.MakeNewKey(true);
        if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec))
            break;
    } while(true);
    assert(rec != -1);
    vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
    return true;
}

bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
    if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
        return false;
    fCompressed = vchPubKey.IsCompressed();
    fValid = true;

    if (fSkipCheck)
        return true;

    return VerifyPubKey(vchPubKey);
}

bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
    assert(IsValid());
    assert(IsCompressed());
    unsigned char out[64];
    LockObject(out);
    if ((nChild >> 31) == 0) {
        CPubKey pubkey = GetPubKey();
        assert(pubkey.begin() + 33 == pubkey.end());
        BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, out);
    } else {
        assert(begin() + 32 == end());
        BIP32Hash(cc, nChild, 0, begin(), out);
    }
    memcpy(ccChild, out+32, 32);
    memcpy((unsigned char*)keyChild.begin(), begin(), 32);
    bool ret = secp256k1_ec_privkey_tweak_add((unsigned char*)keyChild.begin(), out);
    UnlockObject(out);
    keyChild.fCompressed = true;
    keyChild.fValid = ret;
    return ret;
}

bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const {
    out.nDepth = nDepth + 1;
    CKeyID id = key.GetPubKey().GetID();
    memcpy(&out.vchFingerprint[0], &id, 4);
    out.nChild = nChild;
    return key.Derive(out.key, out.vchChainCode, nChild, vchChainCode);
}

void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
    static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
    unsigned char out[64];
    LockObject(out);
    CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(out);
    key.Set(&out[0], &out[32], true);
    memcpy(vchChainCode, &out[32], 32);
    UnlockObject(out);
    nDepth = 0;
    nChild = 0;
    memset(vchFingerprint, 0, sizeof(vchFingerprint));
}

CExtPubKey CExtKey::Neuter() const {
    CExtPubKey ret;
    ret.nDepth = nDepth;
    memcpy(&ret.vchFingerprint[0], &vchFingerprint[0], 4);
    ret.nChild = nChild;
    ret.pubkey = key.GetPubKey();
    memcpy(&ret.vchChainCode[0], &vchChainCode[0], 32);
    return ret;
}

void CExtKey::Encode(unsigned char code[74]) const {
    code[0] = nDepth;
    memcpy(code+1, vchFingerprint, 4);
    code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
    code[7] = (nChild >>  8) & 0xFF; code[8] = (nChild >>  0) & 0xFF;
    memcpy(code+9, vchChainCode, 32);
    code[41] = 0;
    assert(key.size() == 32);
    memcpy(code+42, key.begin(), 32);
}

void CExtKey::Decode(const unsigned char code[74]) {
    nDepth = code[0];
    memcpy(vchFingerprint, code+1, 4);
    nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
    memcpy(vchChainCode, code+9, 32);
    key.Set(code+42, code+74, true);
}

bool ECC_InitSanityCheck() {
    return CECKey::SanityCheck();
}
<commit_msg>Add key generation/verification to ECC sanity check<commit_after>// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "key.h"

#include "crypto/sha2.h"
#include "eccryptoverify.h"
#include "pubkey.h"
#include "random.h"

#include <secp256k1.h>
#include "ecwrapper.h"

//! anonymous namespace
namespace {

class CSecp256k1Init {
public:
    CSecp256k1Init() {
        secp256k1_start(SECP256K1_START_SIGN);
    }
    ~CSecp256k1Init() {
        secp256k1_stop();
    }
};
static CSecp256k1Init instance_of_csecp256k1;

} // anon namespace

bool CKey::Check(const unsigned char *vch) {
    return eccrypto::Check(vch);
}

void CKey::MakeNewKey(bool fCompressedIn) {
    do {
        GetRandBytes(vch, sizeof(vch));
    } while (!Check(vch));
    fValid = true;
    fCompressed = fCompressedIn;
}

bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) {
    if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
        return false;
    fCompressed = fCompressedIn;
    fValid = true;
    return true;
}

CPrivKey CKey::GetPrivKey() const {
    assert(fValid);
    CPrivKey privkey;
    int privkeylen, ret;
    privkey.resize(279);
    privkeylen = 279;
    ret = secp256k1_ec_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed);
    assert(ret);
    privkey.resize(privkeylen);
    return privkey;
}

CPubKey CKey::GetPubKey() const {
    assert(fValid);
    CPubKey result;
    int clen = 65;
    int ret = secp256k1_ec_pubkey_create((unsigned char*)result.begin(), &clen, begin(), fCompressed);
    assert((int)result.size() == clen);
    assert(ret);
    assert(result.IsValid());
    return result;
}

bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
    if (!fValid)
        return false;
    vchSig.resize(72);
    int nSigLen = 72;
    CKey nonce;
    do {
        nonce.MakeNewKey(true);
        if (secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), nonce.begin()))
            break;
    } while(true);
    vchSig.resize(nSigLen);
    return true;
}

bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
    if (pubkey.IsCompressed() != fCompressed) {
        return false;
    }
    unsigned char rnd[8];
    std::string str = "Bitcoin key verification\n";
    GetRandBytes(rnd, sizeof(rnd));
    uint256 hash;
    CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize((unsigned char*)&hash);
    std::vector<unsigned char> vchSig;
    Sign(hash, vchSig);
    return pubkey.Verify(hash, vchSig);
}

bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
    if (!fValid)
        return false;
    vchSig.resize(65);
    int rec = -1;
    CKey nonce;
    do {
        nonce.MakeNewKey(true);
        if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec))
            break;
    } while(true);
    assert(rec != -1);
    vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
    return true;
}

bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
    if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
        return false;
    fCompressed = vchPubKey.IsCompressed();
    fValid = true;

    if (fSkipCheck)
        return true;

    return VerifyPubKey(vchPubKey);
}

bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
    assert(IsValid());
    assert(IsCompressed());
    unsigned char out[64];
    LockObject(out);
    if ((nChild >> 31) == 0) {
        CPubKey pubkey = GetPubKey();
        assert(pubkey.begin() + 33 == pubkey.end());
        BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, out);
    } else {
        assert(begin() + 32 == end());
        BIP32Hash(cc, nChild, 0, begin(), out);
    }
    memcpy(ccChild, out+32, 32);
    memcpy((unsigned char*)keyChild.begin(), begin(), 32);
    bool ret = secp256k1_ec_privkey_tweak_add((unsigned char*)keyChild.begin(), out);
    UnlockObject(out);
    keyChild.fCompressed = true;
    keyChild.fValid = ret;
    return ret;
}

bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const {
    out.nDepth = nDepth + 1;
    CKeyID id = key.GetPubKey().GetID();
    memcpy(&out.vchFingerprint[0], &id, 4);
    out.nChild = nChild;
    return key.Derive(out.key, out.vchChainCode, nChild, vchChainCode);
}

void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
    static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
    unsigned char out[64];
    LockObject(out);
    CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(out);
    key.Set(&out[0], &out[32], true);
    memcpy(vchChainCode, &out[32], 32);
    UnlockObject(out);
    nDepth = 0;
    nChild = 0;
    memset(vchFingerprint, 0, sizeof(vchFingerprint));
}

CExtPubKey CExtKey::Neuter() const {
    CExtPubKey ret;
    ret.nDepth = nDepth;
    memcpy(&ret.vchFingerprint[0], &vchFingerprint[0], 4);
    ret.nChild = nChild;
    ret.pubkey = key.GetPubKey();
    memcpy(&ret.vchChainCode[0], &vchChainCode[0], 32);
    return ret;
}

void CExtKey::Encode(unsigned char code[74]) const {
    code[0] = nDepth;
    memcpy(code+1, vchFingerprint, 4);
    code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
    code[7] = (nChild >>  8) & 0xFF; code[8] = (nChild >>  0) & 0xFF;
    memcpy(code+9, vchChainCode, 32);
    code[41] = 0;
    assert(key.size() == 32);
    memcpy(code+42, key.begin(), 32);
}

void CExtKey::Decode(const unsigned char code[74]) {
    nDepth = code[0];
    memcpy(vchFingerprint, code+1, 4);
    nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
    memcpy(vchChainCode, code+9, 32);
    key.Set(code+42, code+74, true);
}

bool ECC_InitSanityCheck() {
#if !defined(USE_SECP256K1)
    if (!CECKey::SanityCheck()) {
        return false;
    }
#endif
    CKey key;
    key.MakeNewKey(true);
    CPubKey pubkey = key.GetPubKey();
    return key.VerifyPubKey(pubkey);
}
<|endoftext|>


<commit_before>
#ifndef V4R_OCTREE_VOXELCENTROID_CONTAINER_HPP
#define V4R_OCTREE_VOXELCENTROID_CONTAINER_HPP

#include <pcl/common/point_operators.h>
#include <pcl/point_types.h>
#include <pcl/register_point_struct.h>
#include <pcl/octree/octree_pointcloud_voxelcentroid.h>
#include <pcl/octree/octree.h>
#include <pcl/octree/octree_impl.h>
#include <pcl/octree/octree_pointcloud.h>

namespace pcl
{
  namespace octree
  {
    /** \brief @b Octree pointcloud voxel centroid leaf node class
      * \note This class implements a leaf node that calculates the mean centroid of PointXYZRGB points added this octree container.
      */
    template<typename PointT=pcl::PointXYZRGB>
    class OctreeVoxelCentroidContainerXYZRGB : public OctreeContainerBase
    {
      public:
        /** \brief Class initialization. */
        OctreeVoxelCentroidContainerXYZRGB ()
        {
          this->reset();
        }

        /** \brief Empty class deconstructor. */
        virtual ~OctreeVoxelCentroidContainerXYZRGB ()
        {
        }

        /** \brief deep copy function */
        virtual OctreeVoxelCentroidContainerXYZRGB *
        deepCopy () const
        {
          return (new OctreeVoxelCentroidContainerXYZRGB (*this));
        }

        /** \brief Equal comparison operator - set to false
         */
         // param[in] OctreeVoxelCentroidContainerXYZRGB to compare with
        virtual bool operator==(const OctreeContainerBase&) const
        {
          return ( false );
        }

        /** \brief Add new point to voxel.
          * \param[in] new_point the new point to add
          */
        void
        addPoint (const PointT& new_point)
        {
          using namespace pcl::common;

          ++point_counter_;

          pt_[0] += double(new_point.x);
          pt_[1] += double(new_point.y);
          pt_[2] += double(new_point.z);
          r_ += unsigned(new_point.r);
          g_ += unsigned(new_point.g);
          b_ += unsigned(new_point.b);
        }

        /** \brief Calculate centroid of voxel.
          * \param[out] centroid_arg the resultant centroid of the voxel
          */
        void
        getCentroid (PointT& centroid_arg) const
        {
          using namespace pcl::common;

          if (point_counter_)
          {
            centroid_arg.getVector3fMap() = (pt_ / static_cast<double> (point_counter_)).cast<float>();
            centroid_arg.r = static_cast<unsigned char>(r_ / point_counter_);
            centroid_arg.g = static_cast<unsigned char>(g_ / point_counter_);
            centroid_arg.b = static_cast<unsigned char>(b_ / point_counter_);
          }
          else
          {
            centroid_arg.x = std::numeric_limits<float>::quiet_NaN();
            centroid_arg.y = std::numeric_limits<float>::quiet_NaN();
            centroid_arg.z = std::numeric_limits<float>::quiet_NaN();
            centroid_arg.r = 0;
            centroid_arg.g = 0;
            centroid_arg.b = 0;
          }
        }

        /** \brief Reset leaf container. */
        virtual void
        reset ()
        {
          using namespace pcl::common;

          point_counter_ = 0;
          pt_ = Eigen::Vector3d(0.,0.,0.);
          r_ = g_ = b_ = 0;
        }

      private:
        unsigned int point_counter_;
        Eigen::Vector3d pt_;
        unsigned r_, g_, b_;
    };

  }
}

#endif

<commit_msg>Add missing 'template' keyword (causes clang compilation error)<commit_after>
#ifndef V4R_OCTREE_VOXELCENTROID_CONTAINER_HPP
#define V4R_OCTREE_VOXELCENTROID_CONTAINER_HPP

#include <pcl/common/point_operators.h>
#include <pcl/point_types.h>
#include <pcl/register_point_struct.h>
#include <pcl/octree/octree_pointcloud_voxelcentroid.h>
#include <pcl/octree/octree.h>
#include <pcl/octree/octree_impl.h>
#include <pcl/octree/octree_pointcloud.h>

namespace pcl
{
  namespace octree
  {
    /** \brief @b Octree pointcloud voxel centroid leaf node class
      * \note This class implements a leaf node that calculates the mean centroid of PointXYZRGB points added this octree container.
      */
    template<typename PointT=pcl::PointXYZRGB>
    class OctreeVoxelCentroidContainerXYZRGB : public OctreeContainerBase
    {
      public:
        /** \brief Class initialization. */
        OctreeVoxelCentroidContainerXYZRGB ()
        {
          this->reset();
        }

        /** \brief Empty class deconstructor. */
        virtual ~OctreeVoxelCentroidContainerXYZRGB ()
        {
        }

        /** \brief deep copy function */
        virtual OctreeVoxelCentroidContainerXYZRGB *
        deepCopy () const
        {
          return (new OctreeVoxelCentroidContainerXYZRGB (*this));
        }

        /** \brief Equal comparison operator - set to false
         */
         // param[in] OctreeVoxelCentroidContainerXYZRGB to compare with
        virtual bool operator==(const OctreeContainerBase&) const
        {
          return ( false );
        }

        /** \brief Add new point to voxel.
          * \param[in] new_point the new point to add
          */
        void
        addPoint (const PointT& new_point)
        {
          using namespace pcl::common;

          ++point_counter_;

          pt_[0] += double(new_point.x);
          pt_[1] += double(new_point.y);
          pt_[2] += double(new_point.z);
          r_ += unsigned(new_point.r);
          g_ += unsigned(new_point.g);
          b_ += unsigned(new_point.b);
        }

        /** \brief Calculate centroid of voxel.
          * \param[out] centroid_arg the resultant centroid of the voxel
          */
        void
        getCentroid (PointT& centroid_arg) const
        {
          using namespace pcl::common;

          if (point_counter_)
          {
            centroid_arg.getVector3fMap() = (pt_ / static_cast<double> (point_counter_)).template cast<float>();
            centroid_arg.r = static_cast<unsigned char>(r_ / point_counter_);
            centroid_arg.g = static_cast<unsigned char>(g_ / point_counter_);
            centroid_arg.b = static_cast<unsigned char>(b_ / point_counter_);
          }
          else
          {
            centroid_arg.x = std::numeric_limits<float>::quiet_NaN();
            centroid_arg.y = std::numeric_limits<float>::quiet_NaN();
            centroid_arg.z = std::numeric_limits<float>::quiet_NaN();
            centroid_arg.r = 0;
            centroid_arg.g = 0;
            centroid_arg.b = 0;
          }
        }

        /** \brief Reset leaf container. */
        virtual void
        reset ()
        {
          using namespace pcl::common;

          point_counter_ = 0;
          pt_ = Eigen::Vector3d(0.,0.,0.);
          r_ = g_ = b_ = 0;
        }

      private:
        unsigned int point_counter_;
        Eigen::Vector3d pt_;
        unsigned r_, g_, b_;
    };

  }
}

#endif

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#include <qi/log.hpp>
#include "log_p.hpp"
#include <qi/os.hpp>
#include <list>
#include <map>
#include <cstring>
#include <iomanip>

#include <qi/application.hpp>
#include <qi/log/consoleloghandler.hpp>

#include <boost/thread/thread.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/program_options.hpp>

#ifdef QI_USE_BOOST_LOCK_FREE
# include <boost/lockfree/fifo.hpp>
#else
# include <queue>
#endif
#include <boost/function.hpp>

#define RTLOG_BUFFERS (128)

#define CAT_SIZE 64
#define FILE_SIZE 128
#define FUNC_SIZE 64
#define LOG_SIZE 2048

namespace qi {
  namespace detail {
    void cutCat(const char* category, char* res)
    {
      int categorySize = strlen(category);
      if (categorySize < CATSIZEMAX)
      {
        memset(res, ' ', CATSIZEMAX);
        memcpy(res, category, strlen(category));
      }
      else
      {
        memset(res, '.', CATSIZEMAX);
        memcpy(res + 3, category + categorySize - CATSIZEMAX + 3, CATSIZEMAX - 3);
      }
      res[CATSIZEMAX] = '\0';
    }

    std::string logline(const              os::timeval date,
                        const char        *category,
                        const char        *msg,
                        const char        *file,
                        const char        *fct,
                        const int          line)
    {
      char fixedCategory[CATSIZEMAX + 1];
      fixedCategory[CATSIZEMAX] = '\0';
      cutCat(category, fixedCategory);

      int tid = qi::os::gettid();
      std::stringstream logline;

      std::stringstream ss;
      ss << date.tv_sec << "."
         << std::setw(7) << std::setfill('0')  << date.tv_usec;

      switch (qi::log::context())
      {
      case 1:
        logline << fixedCategory << ": ";
        break;
      case 2:
        logline << ss.str() << " ";
        break;
      case 3:
        if (line != 0)
          logline << file << "(" << line << ") ";
        break;
      case 4:
        logline << ss.str() << " " << fixedCategory << ": ";
        break;
      case 5:
        if (line == 0)
          logline << ss.str() << " ";
        else
          logline << ss.str() << " " << file << "(" << line << ") ";
        break;
      case 6:
        if (line == 0)
          logline << fixedCategory << ": ";
        else
          logline << fixedCategory << ": " << file << "(" << line << ")";
        break;
      case 7:
        if (line == 0)
          logline << ss.str() << " " << tid << " " << fixedCategory << ": " << fct << " ";
        else
          logline << ss.str() << " " << tid << " " << fixedCategory << ": " << file << "(" << line << ") " << fct << " ";
        break;
      default:
        break;
      }
      logline << msg;

      return logline.str();
    }
  }

  namespace log {

    typedef struct sPrivateLog
    {
      LogLevel        _logLevel;
      char            _category[CAT_SIZE];
      char            _file[FILE_SIZE];
      char            _function[FUNC_SIZE];
      int             _line;
      char            _log[LOG_SIZE];
      qi::os::timeval _date;
    } privateLog;

    class Log
    {
    public:
      inline Log();
      inline ~Log();

      void run();
      void printLog();

    public:
      bool                       LogInit;
      boost::thread              LogThread;
      boost::mutex               LogWriteLock;
      boost::mutex               LogHandlerLock;
      boost::condition_variable  LogReadyCond;

#ifdef QI_USE_BOOST_LOCK_FREE
      boost::lockfree::fifo<privateLog*>     logs;
#else
      std::queue<privateLog*>     logs;
#endif
      std::map<std::string, logFuncHandler > logHandlers;
    };

    static LogLevel               _glVerbosity = qi::log::info;
    static int                    _glContext = false;
    static bool                   _glSyncLog = false;
    static bool                   _glInit    = false;
    static ConsoleLogHandler      *_glConsoleLogHandler;

    static Log                    *LogInstance;
    static privateLog             LogBuffer[RTLOG_BUFFERS];
    static volatile unsigned long LogPush = 0;

    static class DefaultLogInit
    {
    public:
      DefaultLogInit()
      {
        _glInit = false;
        qi::log::init();
      }

      ~DefaultLogInit()
      {
        qi::log::destroy();
      };
    } synchLog;

    void Log::printLog()
    {
      privateLog* pl;
      boost::mutex::scoped_lock lock(LogHandlerLock);
#ifdef QI_USE_BOOST_LOCK_FREE
      while (logs.dequeue(&pl))
      {

#else
      while ((pl = logs.front()) != 0)
      {
        logs.pop();
#endif
        if (!logHandlers.empty())
        {
          std::map<std::string, logFuncHandler >::iterator it;
          for (it = logHandlers.begin();
               it != logHandlers.end(); ++it)
          {
            (*it).second(pl->_logLevel,
                         pl->_date,
                         pl->_category,
                         pl->_log,
                         pl->_file,
                         pl->_function,
                         pl->_line);
          }
        }
      }
    }

    void Log::run()
    {
      while (LogInit)
      {
        {
          boost::mutex::scoped_lock lock(LogWriteLock);
          LogReadyCond.wait(lock);
        }

        printLog();
      }
    }

    inline Log::Log()
    {
      LogInit = true;
      if (!_glSyncLog)
        LogThread = boost::thread(&Log::run, this);
    };

    inline Log::~Log()
    {
      if (!LogInit)
        return;

      LogInit = false;

      if (!_glSyncLog)
      {
        LogThread.interrupt();
        LogThread.join();

        printLog();
      }
    }

    static void my_strcpy_log(char *dst, const char *src, int len) {
      if (!src)
        src = "(null)";

      int messSize = strlen(src);
      // check if the last char is a \n
      if (src[messSize - 1] == '\n')
      {
        // Get the size to memcpy (don't forget we need 1 space more for \0)
        int strSize = messSize < len  ? messSize : len - 1;
       #ifndef _WIN32
        memcpy(dst, src, strSize);
       #else
        memcpy_s(dst, len,  src, strSize);
       #endif
        dst[strSize] = 0;
        return;
      }

     #ifndef _WIN32
      // Get the size to memcpy (we need 2 spaces more for \n\0)
      int strSize = messSize < len - 1  ? messSize : len - 2;
      memcpy(dst, src, strSize);
      dst[strSize] = '\n';
      dst[strSize + 1] = '\0';
     #else
      // Get the size to memcpy (we need 3 spaces more for \r\n\0)
      int strSize = messSize < len - 2  ? messSize : len - 3;
      memcpy_s(dst, len,  src, strSize);
      dst[strSize] = '\r';
      dst[strSize + 1] = '\n';
      dst[strSize + 2] = '\0';
     #endif
    }

    static void my_strcpy(char *dst, const char *src, int len) {
      if (!src)
        src = "(null)";
     #ifdef _MSV_VER
      strncpy_s(dst, len, src, _TRUNCATE);
     #else
      strncpy(dst, src, len);
      dst[len - 1] = 0;
     #endif
    }

    void init(qi::log::LogLevel verb,
              int ctx,
              bool synchronous)
    {
      setVerbosity(verb);
      setContext(ctx);
      setSynchronousLog(synchronous);

      if (_glInit)
        destroy();

      _glConsoleLogHandler = new ConsoleLogHandler;
      LogInstance          = new Log;
      addLogHandler("consoleloghandler",
                    boost::bind(&ConsoleLogHandler::log,
                                _glConsoleLogHandler,
                                _1, _2, _3, _4, _5, _6, _7));
      _glInit = true;
    }

    void destroy()
    {
      if (!_glInit)
        return;
      _glInit = false;
      LogInstance->printLog();
      delete _glConsoleLogHandler;
      _glConsoleLogHandler = 0;
      delete LogInstance;
      LogInstance = 0;
    }

    void flush()
    {
      if (_glInit)
        LogInstance->printLog();
    }

    void log(const LogLevel        verb,
             const char           *category,
             const char           *msg,
             const char           *file,
             const char           *fct,
             const int             line)
    {
      if (!LogInstance)
        return;
      if (!LogInstance->LogInit)
        return;

      int tmpRtLogPush = ++LogPush % RTLOG_BUFFERS;
      privateLog* pl = &(LogBuffer[tmpRtLogPush]);

      qi::os::timeval tv;
      qi::os::gettimeofday(&tv);

      pl->_logLevel = verb;
      pl->_line = line;
      pl->_date.tv_sec = tv.tv_sec;
      pl->_date.tv_usec = tv.tv_usec;

      my_strcpy(pl->_category, category, CAT_SIZE);
      my_strcpy(pl->_file, file, FILE_SIZE);
      my_strcpy(pl->_function, fct, FUNC_SIZE);
      my_strcpy_log(pl->_log, msg, LOG_SIZE);

      if (_glSyncLog)
      {
        if (!LogInstance->logHandlers.empty())
        {
          std::map<std::string, logFuncHandler >::iterator it;
          for (it = LogInstance->logHandlers.begin();
               it != LogInstance->logHandlers.end(); ++it)
          {
            (*it).second(pl->_logLevel,
                         pl->_date,
                         pl->_category,
                         pl->_log,
                         pl->_file,
                         pl->_function,
                         pl->_line);
          }
        }
      }
      else
      {
#ifdef QI_USE_BOOST_LOCK_FREE
        LogInstance->logs.enqueue(pl);
#else
        LogInstance->logs.push(pl);
#endif
        LogInstance->LogReadyCond.notify_one();
      }
    }

    void addLogHandler(const std::string& name, logFuncHandler fct)
    {
      if (!LogInstance)
        return;
      boost::mutex::scoped_lock l(LogInstance->LogHandlerLock);
      LogInstance->logHandlers[name] = fct;
    }

    void removeLogHandler(const std::string& name)
    {
      if (!LogInstance)
        return;
      boost::mutex::scoped_lock l(LogInstance->LogHandlerLock);
      LogInstance->logHandlers.erase(name);
    }

    LogLevel stringToLogLevel(const char* verb)
    {
      std::string v(verb);
      if (v == "silent")
        return qi::log::silent;
      if (v == "fatal")
        return qi::log::fatal;
      if (v == "error")
        return qi::log::error;
      if (v == "warning")
        return qi::log::warning;
      if (v == "info")
        return qi::log::info;
      if (v == "verbose")
        return qi::log::verbose;
      if (v == "debug")
        return qi::log::debug;
      return qi::log::info;
    }

    const char *logLevelToString(const LogLevel verb)
    {
      static const char *sverb[] = {
        "[SILENT]", // never shown
        "[FATAL]",
        "[ERROR]",
        "[WARN ]",
        "[INFO ]",
        "[VERB ]",
        "[DEBUG]"
      };
      return sverb[verb];
    }

    void setVerbosity(const LogLevel lv)
    {
      const char *verbose = std::getenv("VERBOSE");

      if (verbose)
        _glVerbosity = (LogLevel)atoi(verbose);
      else
        _glVerbosity = lv;

      qiLogVerbose("qi.log") << "Verbosity set to " << _glVerbosity;
    };

    LogLevel verbosity()
    {
      return _glVerbosity;
    };

    void setContext(int ctx)
    {
      const char *context = std::getenv("CONTEXT");

      if (context)
        _glContext = (atoi(context));
      else
        _glContext = ctx;

      qiLogVerbose("qi.log") << "Context set to " << _glContext;
    };

    int context()
    {
      return _glContext;
    };

    void setSynchronousLog(bool sync)
    {
      _glSyncLog = sync;
    };

    static void _setVerbosityInt(int v)
    {
      setVerbosity((LogLevel)v);
    }

    static void _setVerbose(bool on)
    {
      if (on)
        setVerbosity(verbose);
    }
    static void _setDebug(bool on)
    {
      if (on)
        setVerbosity(debug);
    }
    static void _quiet(bool on)
    {
      if (on)
        removeLogHandler("consoleloghandler");
    }

    _QI_COMMAND_LINE_OPTIONS(
      "Logging options",
      ("verbose,v", bool_switch()->notifier(&_setVerbose), "Set verbose verbosity.")
      ("debug,d", bool_switch()->notifier(&_setDebug), "Set debug verbosity.")
      ("quiet,q",  bool_switch()->notifier(&_quiet), "Do not show logs on console.")
      ("context,c", value<int>()->notifier(&setContext), "Show context logs: [0-7] (0: none, 1: categories, 2: date, 3: file+line, 4: date+categories, 5: date+line+file, 6: categories+line+file, 7: all (date+categories+line+file+function)).")
      ("synchronous-log", bool_switch()->notifier(boost::bind(&setSynchronousLog, true)),  "Activate synchronous logs.")
      ("log-level,L", value<int>()->notifier(&_setVerbosityInt), "Change the log minimum level: [0-6] (0: silent, 1: fatal, 2: error, 3: warning, 4: info, 5: verbose, 6: debug). Default: 4 (info)")
      )

  } // namespace log
} // namespace qi

<commit_msg>Add logging on Android<commit_after>/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#include <qi/log.hpp>
#include "log_p.hpp"
#include <qi/os.hpp>
#include <list>
#include <map>
#include <cstring>
#include <iomanip>

#include <qi/application.hpp>
#include <qi/log/consoleloghandler.hpp>

#include <boost/thread/thread.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/program_options.hpp>

#ifdef QI_USE_BOOST_LOCK_FREE
# include <boost/lockfree/fifo.hpp>
#else
# include <queue>
#endif
#include <boost/function.hpp>

#ifdef ANDROID
# include <android/log.h>
#endif

#define RTLOG_BUFFERS (128)

#define CAT_SIZE 64
#define FILE_SIZE 128
#define FUNC_SIZE 64
#define LOG_SIZE 2048

namespace qi {
  namespace detail {
    void cutCat(const char* category, char* res)
    {
      int categorySize = strlen(category);
      if (categorySize < CATSIZEMAX)
      {
        memset(res, ' ', CATSIZEMAX);
        memcpy(res, category, strlen(category));
      }
      else
      {
        memset(res, '.', CATSIZEMAX);
        memcpy(res + 3, category + categorySize - CATSIZEMAX + 3, CATSIZEMAX - 3);
      }
      res[CATSIZEMAX] = '\0';
    }

    std::string logline(const              os::timeval date,
                        const char        *category,
                        const char        *msg,
                        const char        *file,
                        const char        *fct,
                        const int          line)
    {
      char fixedCategory[CATSIZEMAX + 1];
      fixedCategory[CATSIZEMAX] = '\0';
      cutCat(category, fixedCategory);

      int tid = qi::os::gettid();
      std::stringstream logline;

      std::stringstream ss;
      ss << date.tv_sec << "."
         << std::setw(7) << std::setfill('0')  << date.tv_usec;

      switch (qi::log::context())
      {
      case 1:
        logline << fixedCategory << ": ";
        break;
      case 2:
        logline << ss.str() << " ";
        break;
      case 3:
        if (line != 0)
          logline << file << "(" << line << ") ";
        break;
      case 4:
        logline << ss.str() << " " << fixedCategory << ": ";
        break;
      case 5:
        if (line == 0)
          logline << ss.str() << " ";
        else
          logline << ss.str() << " " << file << "(" << line << ") ";
        break;
      case 6:
        if (line == 0)
          logline << fixedCategory << ": ";
        else
          logline << fixedCategory << ": " << file << "(" << line << ")";
        break;
      case 7:
        if (line == 0)
          logline << ss.str() << " " << tid << " " << fixedCategory << ": " << fct << " ";
        else
          logline << ss.str() << " " << tid << " " << fixedCategory << ": " << file << "(" << line << ") " << fct << " ";
        break;
      default:
        break;
      }
      logline << msg;

      return logline.str();
    }
  }

  namespace log {

    typedef struct sPrivateLog
    {
      LogLevel        _logLevel;
      char            _category[CAT_SIZE];
      char            _file[FILE_SIZE];
      char            _function[FUNC_SIZE];
      int             _line;
      char            _log[LOG_SIZE];
      qi::os::timeval _date;
    } privateLog;

    class Log
    {
    public:
      inline Log();
      inline ~Log();

      void run();
      void printLog();

    public:
      bool                       LogInit;
      boost::thread              LogThread;
      boost::mutex               LogWriteLock;
      boost::mutex               LogHandlerLock;
      boost::condition_variable  LogReadyCond;

#ifdef QI_USE_BOOST_LOCK_FREE
      boost::lockfree::fifo<privateLog*>     logs;
#else
      std::queue<privateLog*>     logs;
#endif
      std::map<std::string, logFuncHandler > logHandlers;
    };

    static LogLevel               _glVerbosity = qi::log::info;
    static int                    _glContext = false;
    static bool                   _glSyncLog = false;
    static bool                   _glInit    = false;
    static ConsoleLogHandler      *_glConsoleLogHandler;

    static Log                    *LogInstance;
    static privateLog             LogBuffer[RTLOG_BUFFERS];
    static volatile unsigned long LogPush = 0;

    static class DefaultLogInit
    {
    public:
      DefaultLogInit()
      {
        _glInit = false;
        qi::log::init();
      }

      ~DefaultLogInit()
      {
        qi::log::destroy();
      };
    } synchLog;

    void Log::printLog()
    {
      privateLog* pl;
      boost::mutex::scoped_lock lock(LogHandlerLock);
#ifdef QI_USE_BOOST_LOCK_FREE
      while (logs.dequeue(&pl))
      {

#else
      while ((pl = logs.front()) != 0)
      {
        logs.pop();
#endif
        if (!logHandlers.empty())
        {
          std::map<std::string, logFuncHandler >::iterator it;
          for (it = logHandlers.begin();
               it != logHandlers.end(); ++it)
          {
            (*it).second(pl->_logLevel,
                         pl->_date,
                         pl->_category,
                         pl->_log,
                         pl->_file,
                         pl->_function,
                         pl->_line);
          }
        }
      }
    }

    void Log::run()
    {
      while (LogInit)
      {
        {
          boost::mutex::scoped_lock lock(LogWriteLock);
          LogReadyCond.wait(lock);
        }

        printLog();
      }
    }

    inline Log::Log()
    {
      LogInit = true;
      if (!_glSyncLog)
        LogThread = boost::thread(&Log::run, this);
    };

    inline Log::~Log()
    {
      if (!LogInit)
        return;

      LogInit = false;

      if (!_glSyncLog)
      {
        LogThread.interrupt();
        LogThread.join();

        printLog();
      }
    }

    static void my_strcpy_log(char *dst, const char *src, int len) {
      if (!src)
        src = "(null)";

      int messSize = strlen(src);
      // check if the last char is a \n
      if (src[messSize - 1] == '\n')
      {
        // Get the size to memcpy (don't forget we need 1 space more for \0)
        int strSize = messSize < len  ? messSize : len - 1;
       #ifndef _WIN32
        memcpy(dst, src, strSize);
       #else
        memcpy_s(dst, len,  src, strSize);
       #endif
        dst[strSize] = 0;
        return;
      }

     #ifndef _WIN32
      // Get the size to memcpy (we need 2 spaces more for \n\0)
      int strSize = messSize < len - 1  ? messSize : len - 2;
      memcpy(dst, src, strSize);
      dst[strSize] = '\n';
      dst[strSize + 1] = '\0';
     #else
      // Get the size to memcpy (we need 3 spaces more for \r\n\0)
      int strSize = messSize < len - 2  ? messSize : len - 3;
      memcpy_s(dst, len,  src, strSize);
      dst[strSize] = '\r';
      dst[strSize + 1] = '\n';
      dst[strSize + 2] = '\0';
     #endif
    }

    static void my_strcpy(char *dst, const char *src, int len) {
      if (!src)
        src = "(null)";
     #ifdef _MSV_VER
      strncpy_s(dst, len, src, _TRUNCATE);
     #else
      strncpy(dst, src, len);
      dst[len - 1] = 0;
     #endif
    }

    void init(qi::log::LogLevel verb,
              int ctx,
              bool synchronous)
    {
      setVerbosity(verb);
      setContext(ctx);
      setSynchronousLog(synchronous);

      if (_glInit)
        destroy();

      _glConsoleLogHandler = new ConsoleLogHandler;
      LogInstance          = new Log;
      addLogHandler("consoleloghandler",
                    boost::bind(&ConsoleLogHandler::log,
                                _glConsoleLogHandler,
                                _1, _2, _3, _4, _5, _6, _7));
      _glInit = true;
    }

    void destroy()
    {
      if (!_glInit)
        return;
      _glInit = false;
      LogInstance->printLog();
      delete _glConsoleLogHandler;
      _glConsoleLogHandler = 0;
      delete LogInstance;
      LogInstance = 0;
    }

    void flush()
    {
      if (_glInit)
        LogInstance->printLog();
    }

    void log(const LogLevel        verb,
             const char           *category,
             const char           *msg,
             const char           *file,
             const char           *fct,
             const int             line)
    {
      #ifdef ANDROID
        std::map<LogLevel, android_LogPriority> _conv;

        _conv[silent]  = ANDROID_LOG_SILENT;
        _conv[fatal]   = ANDROID_LOG_FATAL;
        _conv[error]   = ANDROID_LOG_ERROR;
        _conv[warning] = ANDROID_LOG_WARN;
        _conv[info]    = ANDROID_LOG_INFO;
        _conv[verbose] = ANDROID_LOG_VERBOSE;
        _conv[debug]   = ANDROID_LOG_DEBUG;

        __android_log_print(_conv[verb], category, msg);
        return;
      #endif

      if (!LogInstance)
        return;
      if (!LogInstance->LogInit)
        return;

      int tmpRtLogPush = ++LogPush % RTLOG_BUFFERS;
      privateLog* pl = &(LogBuffer[tmpRtLogPush]);

      qi::os::timeval tv;
      qi::os::gettimeofday(&tv);

      pl->_logLevel = verb;
      pl->_line = line;
      pl->_date.tv_sec = tv.tv_sec;
      pl->_date.tv_usec = tv.tv_usec;

      my_strcpy(pl->_category, category, CAT_SIZE);
      my_strcpy(pl->_file, file, FILE_SIZE);
      my_strcpy(pl->_function, fct, FUNC_SIZE);
      my_strcpy_log(pl->_log, msg, LOG_SIZE);

      if (_glSyncLog)
      {
        if (!LogInstance->logHandlers.empty())
        {
          std::map<std::string, logFuncHandler >::iterator it;
          for (it = LogInstance->logHandlers.begin();
               it != LogInstance->logHandlers.end(); ++it)
          {
            (*it).second(pl->_logLevel,
                         pl->_date,
                         pl->_category,
                         pl->_log,
                         pl->_file,
                         pl->_function,
                         pl->_line);
          }
        }
      }
      else
      {
#ifdef QI_USE_BOOST_LOCK_FREE
        LogInstance->logs.enqueue(pl);
#else
        LogInstance->logs.push(pl);
#endif
        LogInstance->LogReadyCond.notify_one();
      }
    }

    void addLogHandler(const std::string& name, logFuncHandler fct)
    {
      if (!LogInstance)
        return;
      boost::mutex::scoped_lock l(LogInstance->LogHandlerLock);
      LogInstance->logHandlers[name] = fct;
    }

    void removeLogHandler(const std::string& name)
    {
      if (!LogInstance)
        return;
      boost::mutex::scoped_lock l(LogInstance->LogHandlerLock);
      LogInstance->logHandlers.erase(name);
    }

    LogLevel stringToLogLevel(const char* verb)
    {
      std::string v(verb);
      if (v == "silent")
        return qi::log::silent;
      if (v == "fatal")
        return qi::log::fatal;
      if (v == "error")
        return qi::log::error;
      if (v == "warning")
        return qi::log::warning;
      if (v == "info")
        return qi::log::info;
      if (v == "verbose")
        return qi::log::verbose;
      if (v == "debug")
        return qi::log::debug;
      return qi::log::info;
    }

    const char *logLevelToString(const LogLevel verb)
    {
      static const char *sverb[] = {
        "[SILENT]", // never shown
        "[FATAL]",
        "[ERROR]",
        "[WARN ]",
        "[INFO ]",
        "[VERB ]",
        "[DEBUG]"
      };
      return sverb[verb];
    }

    void setVerbosity(const LogLevel lv)
    {
      const char *verbose = std::getenv("VERBOSE");

      if (verbose)
        _glVerbosity = (LogLevel)atoi(verbose);
      else
        _glVerbosity = lv;

      qiLogVerbose("qi.log") << "Verbosity set to " << _glVerbosity;
    };

    LogLevel verbosity()
    {
      return _glVerbosity;
    };

    void setContext(int ctx)
    {
      const char *context = std::getenv("CONTEXT");

      if (context)
        _glContext = (atoi(context));
      else
        _glContext = ctx;

      qiLogVerbose("qi.log") << "Context set to " << _glContext;
    };

    int context()
    {
      return _glContext;
    };

    void setSynchronousLog(bool sync)
    {
      _glSyncLog = sync;
    };

    static void _setVerbosityInt(int v)
    {
      setVerbosity((LogLevel)v);
    }

    static void _setVerbose(bool on)
    {
      if (on)
        setVerbosity(verbose);
    }
    static void _setDebug(bool on)
    {
      if (on)
        setVerbosity(debug);
    }
    static void _quiet(bool on)
    {
      if (on)
        removeLogHandler("consoleloghandler");
    }

    _QI_COMMAND_LINE_OPTIONS(
      "Logging options",
      ("verbose,v", bool_switch()->notifier(&_setVerbose), "Set verbose verbosity.")
      ("debug,d", bool_switch()->notifier(&_setDebug), "Set debug verbosity.")
      ("quiet,q",  bool_switch()->notifier(&_quiet), "Do not show logs on console.")
      ("context,c", value<int>()->notifier(&setContext), "Show context logs: [0-7] (0: none, 1: categories, 2: date, 3: file+line, 4: date+categories, 5: date+line+file, 6: categories+line+file, 7: all (date+categories+line+file+function)).")
      ("synchronous-log", bool_switch()->notifier(boost::bind(&setSynchronousLog, true)),  "Activate synchronous logs.")
      ("log-level,L", value<int>()->notifier(&_setVerbosityInt), "Change the log minimum level: [0-6] (0: silent, 1: fatal, 2: error, 3: warning, 4: info, 5: verbose, 6: debug). Default: 4 (info)")
      )

  } // namespace log
} // namespace qi

<|endoftext|>


<commit_before>#include "myclass.hpp"

#include "extern_templates.hpp"

template <typename T, typename D>
class TemplateClass {
public:
  TemplateClass () : value_(0.0) {}
  TemplateClass (const T& v) : value_(v) {}
  const T& GetValue (void) { return value_; }
  T value_;
};

template class TemplateClass<int, class jim::MyClass<float>>;

int main(int argc, char **argv) {
  // DELETE THESE.  Used to suppress unused variable warnings.
  (void)argc;
  (void)argv;

  double d = 10;
  double c = add(d, d);
  d = c;

  TemplateClass<int, jim::MyClass<float>> ti;
  ti.GetValue();

  jim::MyClass<char> mc;

  jim::Baseclass *bc = new jim::Subclass1<float>();
  bc->value0_ = 40;

  if (argc > 2) {
    mc.value_ = 40;
  }

  return 0;
}
<commit_msg>breaks on vector<commit_after>#include <vector>

#include "myclass.hpp"

#include "extern_templates.hpp"

template <typename T, typename D>
class TemplateClass {
public:
  TemplateClass () : value_(0.0) {}
  TemplateClass (const T& v) : value_(v) {}
  const T& GetValue (void) { return value_; }
  T value_;
};

template class TemplateClass<int, class jim::MyClass<float>>;

int main(int argc, char **argv) {
  // DELETE THESE.  Used to suppress unused variable warnings.
  (void)argc;
  (void)argv;

  double d = 10;
  double c = add(d, d);
  d = c;

  TemplateClass<int, jim::MyClass<float>> ti;
  ti.GetValue();

  jim::MyClass<char> mc;

  jim::Baseclass *bc = new jim::Subclass1<float>();
  bc->value0_ = 40;

  if (argc > 2) {
    mc.value_ = 40;
  }

  std::vector<int> ivec;
  ivec.push_back(10);

  return 0;
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <time.h>
#include <cassert>
#include <functional>
#include <iostream>
#include <string>
#include <variant>
#include <vector>

#include <mpd/connection.h>

#include "args.h"
#include "ashuffle.h"
#include "getpass.h"
#include "load.h"
#include "mpd_client.h"
#include "shuffle.h"

using namespace ashuffle;

namespace {

std::unique_ptr<Loader> BuildLoader(mpd::MPD* mpd, const Options& opts) {
    if (opts.file_in != nullptr && opts.check_uris) {
        return std::make_unique<FileMPDLoader>(mpd, opts.ruleset, opts.group_by,
                                               opts.file_in);
    } else if (opts.file_in != nullptr) {
        return std::make_unique<FileLoader>(opts.file_in);
    }

    return std::make_unique<MPDLoader>(mpd, opts.ruleset, opts.group_by);
}

}  // namespace

int main(int argc, const char* argv[]) {
    std::variant<Options, ParseError> parse =
        Options::ParseFromC(*mpd::client::Parser(), argv, argc);
    if (ParseError* err = std::get_if<ParseError>(&parse); err != nullptr) {
        switch (err->type) {
            case ParseError::Type::kUnknown:
                std::cerr << "unknown option parsing error. Please file a bug "
                          << "at https://github.com/joshkunz/ashuffle"
                          << std::endl;
                break;
            case ParseError::Type::kHelp:
                // We always print the help, so just break here.
                break;
            case ParseError::Type::kGeneric:
                std::cerr << "error: " << err->msg << std::endl;
                break;
            default:
                assert(false && "unreachable");
        }
        std::cerr << DisplayHelp;
        exit(EXIT_FAILURE);
    }

    Options options = std::move(std::get<Options>(parse));

    if (!options.check_uris && !options.group_by.empty()) {
        std::cerr << "-g/--group-by not supported with no-check" << std::endl;
        exit(EXIT_FAILURE);
    }

    std::function<std::string()> pass_f = [] {
        return GetPass(stdin, stdout, "mpd password: ");
    };
    /* attempt to connect to MPD */
    std::unique_ptr<mpd::MPD> mpd =
        Connect(*mpd::client::Dialer(), options, pass_f);

    ShuffleChain songs((size_t)options.tweak.window_size);

    {
        // We construct the loader in a new scope, since loaders can
        // consume a lot of memory.
        std::unique_ptr<Loader> loader = BuildLoader(mpd.get(), options);
        loader->Load(&songs);
    }

    // For integration testing, we sometimes just want to have ashuffle
    // dump the list of songs in its shuffle chain.
    if (options.test.print_all_songs_and_exit) {
        bool first = true;
        for (auto&& group : songs.Items()) {
            if (!first) {
                std::cout << "---" << std::endl;
            }
            first = false;
            for (auto&& song : group) {
                std::cout << song << std::endl;
            }
        }
        exit(EXIT_SUCCESS);
    }

    if (songs.Len() == 0) {
        std::cerr << "Song pool is empty." << std::endl;
        exit(EXIT_FAILURE);
    }

    if (!options.group_by.empty()) {
        std::cout << absl::StrFormat("Picking from %u groups (%u songs).",
                                     songs.Len(), songs.LenURIs())
                  << std::endl;
    } else {
        std::cout << "Picking random songs out of a pool of " << songs.Len()
                  << "." << std::endl;
    }

    /* do the main action */
    if (options.queue_only) {
        size_t number_of_songs{};
        for (unsigned i = 0; i < options.queue_only; i++) {
            auto& picked_songs = songs.Pick();
            number_of_songs += picked_songs.size();
            mpd->Add(picked_songs);
        }

        /* print number of songs or groups (and songs) added */
        std::cout << absl::StrFormat(
            "Added %u %s%s", options.queue_only,
            options.group_by.empty() ? "song" : "group",
            options.queue_only > 1 ? "s" : "");
        if (!options.group_by.empty()) {
            std::cout << absl::StrFormat(" (%u songs)", number_of_songs);
        }
        std::cout << "." << std::endl;

    } else {
        Loop(mpd.get(), &songs, options);
    }

    return 0;
}
<commit_msg>cleanup: Fix nits in main.cc formatting.<commit_after>#include <stdlib.h>
#include <time.h>
#include <cassert>
#include <functional>
#include <iostream>
#include <string>
#include <variant>
#include <vector>

#include <mpd/connection.h>

#include "args.h"
#include "ashuffle.h"
#include "getpass.h"
#include "load.h"
#include "mpd_client.h"
#include "shuffle.h"

using namespace ashuffle;

namespace {

std::unique_ptr<Loader> BuildLoader(mpd::MPD* mpd, const Options& opts) {
    if (opts.file_in != nullptr && opts.check_uris) {
        return std::make_unique<FileMPDLoader>(mpd, opts.ruleset, opts.group_by,
                                               opts.file_in);
    } else if (opts.file_in != nullptr) {
        return std::make_unique<FileLoader>(opts.file_in);
    }

    return std::make_unique<MPDLoader>(mpd, opts.ruleset, opts.group_by);
}

}  // namespace

int main(int argc, const char* argv[]) {
    std::variant<Options, ParseError> parse =
        Options::ParseFromC(*mpd::client::Parser(), argv, argc);
    if (ParseError* err = std::get_if<ParseError>(&parse); err != nullptr) {
        switch (err->type) {
            case ParseError::Type::kUnknown:
                std::cerr << "unknown option parsing error. Please file a bug "
                          << "at https://github.com/joshkunz/ashuffle"
                          << std::endl;
                break;
            case ParseError::Type::kHelp:
                // We always print the help, so just break here.
                break;
            case ParseError::Type::kGeneric:
                std::cerr << "error: " << err->msg << std::endl;
                break;
            default:
                assert(false && "unreachable");
        }
        std::cerr << DisplayHelp;
        exit(EXIT_FAILURE);
    }

    Options options = std::move(std::get<Options>(parse));

    if (!options.check_uris && !options.group_by.empty()) {
        std::cerr << "-g/--group-by not supported with no-check" << std::endl;
        exit(EXIT_FAILURE);
    }

    std::function<std::string()> pass_f = [] {
        return GetPass(stdin, stdout, "mpd password: ");
    };
    /* attempt to connect to MPD */
    std::unique_ptr<mpd::MPD> mpd =
        Connect(*mpd::client::Dialer(), options, pass_f);

    ShuffleChain songs((size_t)options.tweak.window_size);

    {
        // We construct the loader in a new scope, since loaders can
        // consume a lot of memory.
        std::unique_ptr<Loader> loader = BuildLoader(mpd.get(), options);
        loader->Load(&songs);
    }

    // For integration testing, we sometimes just want to have ashuffle
    // dump the list of songs in its shuffle chain.
    if (options.test.print_all_songs_and_exit) {
        bool first = true;
        for (auto&& group : songs.Items()) {
            if (!first) {
                std::cout << "---" << std::endl;
            }
            first = false;
            for (auto&& song : group) {
                std::cout << song << std::endl;
            }
        }
        exit(EXIT_SUCCESS);
    }

    if (songs.Len() == 0) {
        std::cerr << "Song pool is empty." << std::endl;
        exit(EXIT_FAILURE);
    }

    if (!options.group_by.empty()) {
        std::cout << absl::StrFormat("Picking from %u groups (%u songs).",
                                     songs.Len(), songs.LenURIs())
                  << std::endl;
    } else {
        std::cout << "Picking random songs out of a pool of " << songs.Len()
                  << "." << std::endl;
    }

    /* do the main action */
    if (options.queue_only) {
        size_t number_of_songs;
        for (unsigned i = 0; i < options.queue_only; i++) {
            auto& picked_songs = songs.Pick();
            number_of_songs += picked_songs.size();
            mpd->Add(picked_songs);
        }

        /* print number of songs or groups (and songs) added */
        std::cout << absl::StrFormat(
            "Added %u %s%s", options.queue_only,
            options.group_by.empty() ? "song" : "group",
            options.queue_only > 1 ? "s" : "");
        if (!options.group_by.empty()) {
            std::cout << absl::StrFormat(" (%u songs)", number_of_songs);
        }
        std::cout << "." << std::endl;
    } else {
        Loop(mpd.get(), &songs, options);
    }

    return 0;
}
<|endoftext|>


<commit_before>/*!
 * \cond FILEINFO
 ******************************************************************************
 * \file main.cpp
 ******************************************************************************
 *
 * Copyright (C) ATS Advanced Telematic Systems GmbH GmbH, 2016
 *
 * \author Moritz Klinger
 *
 ******************************************************************************
 *
 * \brief  The main file of the project.
 *
 *
 ******************************************************************************
 *
 * \endcond
 */

/*****************************************************************************/
#include <signal.h>
#include <boost/program_options.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/thread.hpp>
#include <iostream>
#include <memory>

#include "channel.h"
#include "commands.h"
#include "config.h"
#include "events.h"
#include "eventsinterpreter.h"
#include "logger.h"
#include "sotahttpclient.h"
#ifdef WITH_GENIVI
#include "sotarviclient.h"
#endif

#ifdef BUILD_OSTREE
#include "crypto.h"
#include "ostree.h"
#include "sotauptaneclient.h"
#endif

#include "utils.h"

#include <sodium.h>

/*****************************************************************************/

namespace bpo = boost::program_options;

bpo::variables_map parse_options(int argc, char *argv[]) {
  bpo::options_description description("CommandLine Options");
  // clang-format off
  description.add_options()
      ("help,h", "help screen")
      ("version,v", "Current aktualizr version")
      ("loglevel", bpo::value<int>(), "set log level 0-4 (trace, debug, warning, info, error)")
      ("config,c", bpo::value<std::string>()->required(), "toml configuration file")
      ("gateway-http", bpo::value<bool>(), "enable the http gateway")
      ("gateway-rvi", bpo::value<bool>(), "enable the rvi gateway")
      ("gateway-socket", bpo::value<bool>(), "enable the socket gateway")
      ("gateway-dbus", bpo::value<bool>(), "enable the D-Bus gateway")
      ("dbus-system-bus", "Use the D-Bus system bus (rather than the session bus)")
      ("tls-server", bpo::value<std::string>(), "url, used for auto provisioning")
      ("repo-server", bpo::value<std::string>(), "url of the uptane repo repository")
      ("director-server", bpo::value<std::string>(), "url of the uptane director repository")
      ("ostree-server", bpo::value<std::string>(), "url of the ostree repository")
      ("primary-ecu-serial", bpo::value<std::string>(), "serial number of primary ecu")
      ("primary-ecu-hardware-id", bpo::value<std::string>(), "hardware id of primary ecu")
      ("disable-keyid-validation", "Disable keyid validation on client side" )
      ("poll-once", "Check for updates only once and exit")
      ("secondary-config", bpo::value<std::vector<std::string> >()->composing(), "set config for secondary");
  // clang-format on

  bpo::variables_map vm;
  try {
    bpo::store(bpo::parse_command_line(argc, argv, description), vm);
    bpo::notify(vm);
  } catch (const bpo::required_option &ex) {
    if (vm.count("help") != 0) {
      std::cout << description << '\n';
      exit(EXIT_SUCCESS);
    }
    if (vm.count("version") != 0) {
      std::cout << "Current aktualizr version is: " << AKTUALIZR_VERSION << "\n";
      exit(EXIT_SUCCESS);
    }

    if (ex.get_option_name() == "--config") {
      std::cout << ex.get_option_name() << " is missing.\nYou have to provide a valid configuration "
                                           "file using toml format. See the example configuration file "
                                           "in config/config.toml.example"
                << std::endl;
      exit(EXIT_FAILURE);
    } else {
      // print the error and append the default commandline option description
      std::cout << ex.what() << std::endl << description;
      exit(EXIT_SUCCESS);
    }
  } catch (const bpo::error &ex) {
    // log boost error
    LOGGER_LOG(LVL_warning, "boost command line option error: " << ex.what());

    // print the error message to the standard output too, as the user provided
    // a non-supported commandline option
    std::cout << ex.what() << '\n';

    // set the returnValue, thereby ctest will recognize
    // that something went wrong
    exit(EXIT_FAILURE);
  }

  return vm;
}

/*****************************************************************************/
int main(int argc, char *argv[]) {
  std::srand(static_cast<unsigned int>(std::time(0)));  // seeds pseudo random generator with cuurent time

  // create and initialize the return value to zero (everything is OK)
  int return_value = EXIT_SUCCESS;

  loggerInit();
  if (sodium_init() == -1) {
    LOGGER_LOG(LVL_error, "Unable to initialize libsodium");
    return EXIT_FAILURE;
  }

  bpo::variables_map commandline_map = parse_options(argc, argv);

  // check for loglevel
  if (commandline_map.count("loglevel") != 0) {
    // set the log level from command line option
    LoggerLevels severity = static_cast<LoggerLevels>(commandline_map["loglevel"].as<int>());
    if (severity < LVL_minimum) {
      LOGGER_LOG(LVL_debug, "Invalid log level");
      severity = LVL_trace;
    }
    if (LVL_maximum < severity) {
      LOGGER_LOG(LVL_warning, "Invalid log level");
      severity = LVL_error;
    }
    loggerSetSeverity(severity);
  }

  // Initialize config with default values, the update with config, then with cmd
  std::string filename = commandline_map["config"].as<std::string>();
  Config config(filename, commandline_map);

  command::Channel *commands_channel = new command::Channel();
  event::Channel *events_channel = new event::Channel();

  EventsInterpreter events_interpreter(config, events_channel, commands_channel);
  // run events interpreter in background
  events_interpreter.interpret();

  if (config.gateway.rvi) {
#ifdef WITH_GENIVI
    try {
      SotaRVIClient(config, events_channel).runForever(commands_channel);
    } catch (std::runtime_error e) {
      LOGGER_LOG(LVL_error, "Missing RVI configurations: " << e.what());
      exit(EXIT_FAILURE);
    }
#else
    LOGGER_LOG(LVL_error, "RVI support is not enabled");
    return EXIT_FAILURE;
#endif
  } else {
    if (config.core.auth_type == CERTIFICATE) {
#ifdef BUILD_OSTREE

      SotaUptaneClient(config, events_channel).runForever(commands_channel);
#endif
    } else {
      SotaHttpClient(config, events_channel).runForever(commands_channel);
    }
  }

  return return_value;
}
<commit_msg>Use /dev/urandom instead of current time<commit_after>/*!
 * \cond FILEINFO
 ******************************************************************************
 * \file main.cpp
 ******************************************************************************
 *
 * Copyright (C) ATS Advanced Telematic Systems GmbH GmbH, 2016
 *
 * \author Moritz Klinger
 *
 ******************************************************************************
 *
 * \brief  The main file of the project.
 *
 *
 ******************************************************************************
 *
 * \endcond
 */

/*****************************************************************************/
#include <signal.h>
#include <boost/program_options.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/thread.hpp>
#include <iostream>
#include <memory>

#include "channel.h"
#include "commands.h"
#include "config.h"
#include "events.h"
#include "eventsinterpreter.h"
#include "logger.h"
#include "sotahttpclient.h"
#ifdef WITH_GENIVI
#include "sotarviclient.h"
#endif

#ifdef BUILD_OSTREE
#include "crypto.h"
#include "ostree.h"
#include "sotauptaneclient.h"
#endif

#include "utils.h"

#include <sodium.h>

/*****************************************************************************/

namespace bpo = boost::program_options;

bpo::variables_map parse_options(int argc, char *argv[]) {
  bpo::options_description description("CommandLine Options");
  // clang-format off
  description.add_options()
      ("help,h", "help screen")
      ("version,v", "Current aktualizr version")
      ("loglevel", bpo::value<int>(), "set log level 0-4 (trace, debug, warning, info, error)")
      ("config,c", bpo::value<std::string>()->required(), "toml configuration file")
      ("gateway-http", bpo::value<bool>(), "enable the http gateway")
      ("gateway-rvi", bpo::value<bool>(), "enable the rvi gateway")
      ("gateway-socket", bpo::value<bool>(), "enable the socket gateway")
      ("gateway-dbus", bpo::value<bool>(), "enable the D-Bus gateway")
      ("dbus-system-bus", "Use the D-Bus system bus (rather than the session bus)")
      ("tls-server", bpo::value<std::string>(), "url, used for auto provisioning")
      ("repo-server", bpo::value<std::string>(), "url of the uptane repo repository")
      ("director-server", bpo::value<std::string>(), "url of the uptane director repository")
      ("ostree-server", bpo::value<std::string>(), "url of the ostree repository")
      ("primary-ecu-serial", bpo::value<std::string>(), "serial number of primary ecu")
      ("primary-ecu-hardware-id", bpo::value<std::string>(), "hardware id of primary ecu")
      ("disable-keyid-validation", "Disable keyid validation on client side" )
      ("poll-once", "Check for updates only once and exit")
      ("secondary-config", bpo::value<std::vector<std::string> >()->composing(), "set config for secondary");
  // clang-format on

  bpo::variables_map vm;
  try {
    bpo::store(bpo::parse_command_line(argc, argv, description), vm);
    bpo::notify(vm);
  } catch (const bpo::required_option &ex) {
    if (vm.count("help") != 0) {
      std::cout << description << '\n';
      exit(EXIT_SUCCESS);
    }
    if (vm.count("version") != 0) {
      std::cout << "Current aktualizr version is: " << AKTUALIZR_VERSION << "\n";
      exit(EXIT_SUCCESS);
    }

    if (ex.get_option_name() == "--config") {
      std::cout << ex.get_option_name() << " is missing.\nYou have to provide a valid configuration "
                                           "file using toml format. See the example configuration file "
                                           "in config/config.toml.example"
                << std::endl;
      exit(EXIT_FAILURE);
    } else {
      // print the error and append the default commandline option description
      std::cout << ex.what() << std::endl << description;
      exit(EXIT_SUCCESS);
    }
  } catch (const bpo::error &ex) {
    // log boost error
    LOGGER_LOG(LVL_warning, "boost command line option error: " << ex.what());

    // print the error message to the standard output too, as the user provided
    // a non-supported commandline option
    std::cout << ex.what() << '\n';

    // set the returnValue, thereby ctest will recognize
    // that something went wrong
    exit(EXIT_FAILURE);
  }

  return vm;
}

/*****************************************************************************/
int main(int argc, char *argv[]) {
  char block[4];
  std::ifstream urandom("/dev/urandom", std::ios::in | std::ios::binary);
  urandom.read(block, 4);
  urandom.close();
  std::srand(*(unsigned int *)block);  // seeds pseudo random generator with random number

  // create and initialize the return value to zero (everything is OK)
  int return_value = EXIT_SUCCESS;

  loggerInit();
  if (sodium_init() == -1) {
    LOGGER_LOG(LVL_error, "Unable to initialize libsodium");
    return EXIT_FAILURE;
  }

  bpo::variables_map commandline_map = parse_options(argc, argv);

  // check for loglevel
  if (commandline_map.count("loglevel") != 0) {
    // set the log level from command line option
    LoggerLevels severity = static_cast<LoggerLevels>(commandline_map["loglevel"].as<int>());
    if (severity < LVL_minimum) {
      LOGGER_LOG(LVL_debug, "Invalid log level");
      severity = LVL_trace;
    }
    if (LVL_maximum < severity) {
      LOGGER_LOG(LVL_warning, "Invalid log level");
      severity = LVL_error;
    }
    loggerSetSeverity(severity);
  }

  // Initialize config with default values, the update with config, then with cmd
  std::string filename = commandline_map["config"].as<std::string>();
  Config config(filename, commandline_map);

  command::Channel *commands_channel = new command::Channel();
  event::Channel *events_channel = new event::Channel();

  EventsInterpreter events_interpreter(config, events_channel, commands_channel);
  // run events interpreter in background
  events_interpreter.interpret();

  if (config.gateway.rvi) {
#ifdef WITH_GENIVI
    try {
      SotaRVIClient(config, events_channel).runForever(commands_channel);
    } catch (std::runtime_error e) {
      LOGGER_LOG(LVL_error, "Missing RVI configurations: " << e.what());
      exit(EXIT_FAILURE);
    }
#else
    LOGGER_LOG(LVL_error, "RVI support is not enabled");
    return EXIT_FAILURE;
#endif
  } else {
    if (config.core.auth_type == CERTIFICATE) {
#ifdef BUILD_OSTREE

      SotaUptaneClient(config, events_channel).runForever(commands_channel);
#endif
    } else {
      SotaHttpClient(config, events_channel).runForever(commands_channel);
    }
  }

  return return_value;
}
<|endoftext|>


<commit_before>/*
 * File:   main.cc
 * Author: collin
 *
 * Created on February 23, 2015, 10:23 AM
 */

#include <cstdlib>
#include<iostream>
#include<string>
#include<set>
#include<boost/lexical_cast.hpp>
#include"const.h"
#include"StringSet.h"
#include"StringPartitionSet.h"
//#include "Enumerator.h"

using namespace cpb;

/*
 *
 */
int main(int argc, char** argv)
{
    unsigned int alphabetSize, length;
    if (argc != 3)
    {
        std::cerr << "Usage `.\\string_partitions s n' where 0<s<10 is size of alphabet, n is length of strings." << std::endl;
        return cpb::FAIL;
    }
    try
    {
        alphabetSize = boost::lexical_cast<unsigned int>(argv[1]);
        length = boost::lexical_cast<unsigned int>(argv[2]);
    } catch (boost::bad_lexical_cast e)
    {
        std::cerr << "Usage `.\\enumerator s n' where 0<s<10 is size of alphabet, n is length of strings." << std::endl;
        return cpb::FAIL;
    }
    if (alphabetSize < 1 || alphabetSize > 9)
    {
        std::cerr << "Usage `.\\string_partitions s n' where 0<s<10 is size of alphabet, n is length of strings." << std::endl;
        return cpb::FAIL;
    }

    //create initial partition which is discrete
    StringPartitionSet baseSPS(alphabetSize, length);

//Make all pairs of distinct words.
    std::set<StringSet> pairs;
  for (auto wordOne : baseSPS.strings().cset())
    {
        for (auto wordTwo : baseSPS.strings().cset())
        {
            if (wordOne < wordTwo)
            {
                StringSet pairString;
                pairString.insert(wordOne);
                pairString.insert(wordTwo);
                pairs.insert(pairString);
            }
        }
    }

    for(auto pair: pairs)
    {std::cout<<pair.sortString()<<" ";}
    std::cout<<std::endl;

    std::set<StringPartitionSet> partitions;
       partitions.insert(baseSPS);

    std::set<StringPartitionSet> workingPartitions;
    workingPartitions = partitions;

    std::cout<<baseSPS.sortString()<<std::endl;

    for (auto pair : pairs)
    {
        for (auto sps : partitions)
        {
            sps.glueSetsByWords(pair);
            if(workingPartitions.end()==workingPartitions.find(sps))
            {
                workingPartitions.insert(sps);
                std::cout<<sps.sortString()<<std::endl;
            }

        }
        partitions.clear();
        partitions=workingPartitions;
    }

    std::cout<< "There are "<< partitions.size() << " valid foldings of DB("<<alphabetSize<<", "<<length<<")."<<std::endl;
    return cpb::SUCCESS;
}

<commit_msg>Will now count automata synchronising on strings of length 0 (there is only one).<commit_after>/*
 * File:   main.cc
 * Author: collin
 *
 * Created on February 23, 2015, 10:23 AM
 */

#include <cstdlib>
#include<iostream>
#include<string>
#include<set>
#include<boost/lexical_cast.hpp>
#include"const.h"
#include"StringSet.h"
#include"StringPartitionSet.h"
//#include "Enumerator.h"

using namespace cpb;

/*
 *
 */
int main(int argc, char** argv)
{
    unsigned int alphabetSize, length;
    if (argc != 3)
    {
        std::cerr << "Usage `.\\string_partitions s n' where 0<s<10 is size of alphabet, 0<=n is length of strings." << std::endl;
        return cpb::FAIL;
    }
    try
    {
        alphabetSize = boost::lexical_cast<unsigned int>(argv[1]);
        length = boost::lexical_cast<unsigned int>(argv[2]);
    } catch (boost::bad_lexical_cast e)
    {
        std::cerr << "Usage `.\\enumerator s n' where 0<s<10 is size of alphabet, 0<=n is length of strings." << std::endl;
        return cpb::FAIL;
    }
    if (alphabetSize < 1 || alphabetSize > 9 || length<0)
    {
        std::cerr << "Usage `.\\string_partitions s n' where 0<s<10 is size of alphabet, 0<=n is length of strings." << std::endl;
        return cpb::FAIL;
    }

    //create initial partition which is discrete
    StringPartitionSet baseSPS(alphabetSize, length);

//Make all pairs of distinct words.
    std::set<StringSet> pairs;
  for (auto wordOne : baseSPS.strings().cset())
    {
        for (auto wordTwo : baseSPS.strings().cset())
        {
            if (wordOne < wordTwo)
            {
                StringSet pairString;
                pairString.insert(wordOne);
                pairString.insert(wordTwo);
                pairs.insert(pairString);
            }
        }
    }

    for(auto pair: pairs)
    {std::cout<<pair.sortString()<<" ";}
    std::cout<<std::endl;

    std::set<StringPartitionSet> partitions;
       partitions.insert(baseSPS);

    std::set<StringPartitionSet> workingPartitions;
    workingPartitions = partitions;

    std::cout<<baseSPS.sortString()<<std::endl;

    for (auto pair : pairs)
    {
        for (auto sps : partitions)
        {
            sps.glueSetsByWords(pair);
            if(workingPartitions.end()==workingPartitions.find(sps))
            {
                workingPartitions.insert(sps);
                std::cout<<sps.sortString()<<std::endl;
            }

        }
        partitions.clear();
        partitions=workingPartitions;
    }

    std::cout<< "There are "<< partitions.size() << " valid foldings of DB("<<alphabetSize<<", "<<length<<")."<<std::endl;
    return cpb::SUCCESS;
}

<|endoftext|>