<commit_before>// $Id$
//
//  Copyright (c) 2013, Novartis Institutes for BioMedical Research Inc.
//  All rights reserved.
//
// 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 Novartis Institutes for BioMedical Research Inc.
//       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.
//

#include <Geometry/point.h>
#include <Numerics/Vector.h>
#include <GraphMol/RDKitBase.h>
#include <GraphMol/SmilesParse/SmilesParse.h>
#include <GraphMol/Substruct/SubstructMatch.h>
#include <boost/foreach.hpp>
#include "USRDescriptor.h"

#include <boost/flyweight.hpp>
#include <boost/flyweight/key_value.hpp>
#include <boost/flyweight/no_tracking.hpp>

namespace RDKit{

  namespace {
    void calcDistances(const RDGeom::Point3DConstPtrVect &coords,
                       const RDGeom::Point3D &point,
                       std::vector<double> &distances) {
      distances.resize(coords.size());
      unsigned int i = 0;
      // loop over coordinates
      BOOST_FOREACH(const RDGeom::Point3D *tpp, coords) {
        distances[i++] = (*tpp-point).length();
      }
    }

    void calcCentroid(const RDGeom::Point3DConstPtrVect &coords,
                      RDGeom::Point3D &pt) {
      PRECONDITION(!coords.empty(),"no coordinates");
      // set pt to zero
      pt *= 0.0;
      // loop over coordinates
      BOOST_FOREACH(const RDGeom::Point3D *opt, coords) {
        pt += *opt;
      }
      pt /= coords.size();
    }

    unsigned int largestValId(const std::vector<double> &v) {
      PRECONDITION(!v.empty(),"no values");
      double res = v[0];
      unsigned int id = 0;
      for (unsigned int i = 1; i < v.size(); ++i) {
        if (v[i] > res) {
          res = v[i];
          id = i;
        }
      }
      return id;
    }

    unsigned int smallestValId(const std::vector<double> &v) {
      PRECONDITION(!v.empty(),"no values");
      double res = v[0];
      unsigned int id = 0;
      for (unsigned int i = 1; i < v.size(); ++i) {
        if (v[i] < res) {
          res = v[i];
          id = i;
        }
      }
      return id;
    }

    void calcMoments(const std::vector<double> &dist,
                     std::vector<double> &descriptor,
                     int idx) {
      std::vector<double> moments (3, 0.0);
      unsigned int numPts = dist.size();
      if (numPts > 0) {
        // 1. moment: mean
        for (unsigned int i = 0; i < numPts; ++i) {
          moments[0] += dist[i];
        }
        moments[0] /= numPts;
        // 2. moment: standard deviation
        // 3. moment: cubic root of skewness
        for (unsigned int i = 0; i < numPts; ++i) {
          double diff = dist[i] - moments[0];
          moments[1] += diff * diff;
          moments[2] += diff * diff * diff;
        }
        moments[1] = sqrt(moments[1] / numPts);
        moments[2] /= numPts;
        moments[2] = cbrt(moments[2] / (moments[1] * moments[1] * moments[1]));
      }
      // add moments to descriptor
      std::copy(moments.begin(), moments.end(), descriptor.begin()+idx);
    }

    class ss_matcher {
      public:
        ss_matcher() {};
        ss_matcher(const std::string &pattern){
          RDKit::RWMol *p = RDKit::SmartsToMol(pattern);
          TEST_ASSERT(p);
          m_matcher.reset(p);
        };
        const RDKit::ROMol *getMatcher() const { return m_matcher.get(); };
      private:
        RDKit::ROMOL_SPTR m_matcher;
    };

    // Definitions for feature points from
    // http://hg.adrianschreyer.eu/usrcat/src/70e075d93cd2?at=default
    const char *smartsPatterns[4] = {
      "[#6+0!$(*~[#7,#8,F]),SH0+0v2,s+0,S^3,Cl+0,Br+0,I+0]", // hydrophobic
      "[a]", // aromatic
      "[$([O,S;H1;v2]-[!$(*=[O,N,P,S])]),$([O,S;H0;v2]),$([O,S;-]),\
$([N&v3;H1,H2]-[!$(*=[O,N,P,S])]),$([N;v3;H0]),$([n,o,s;+0]),F]", // acceptor
      "[N!H0v3,N!H0+v4,OH+0,SH+0,nH+0]" // donor
    };
    std::vector<std::string> featureSmarts(smartsPatterns,smartsPatterns+4);
    typedef boost::flyweight<boost::flyweights::key_value<std::string,ss_matcher>,boost::flyweights::no_tracking > pattern_flyweight;

    void getAtomIdsForFeatures(const ROMol &mol, std::vector<std::vector<unsigned int> > &atomIds) {
      unsigned int numFeatures = featureSmarts.size();
      PRECONDITION(atomIds.size() == numFeatures, "atomIds must have be the same size as featureSmarts");
      std::vector<const ROMol *> featureMatchers;
      featureMatchers.reserve(numFeatures);
      BOOST_FOREACH(const std::string &feature, featureSmarts) {
        const ROMol *matcher = pattern_flyweight(feature).get().getMatcher();
        featureMatchers.push_back(matcher);
      }
      for (unsigned int i = 0; i < numFeatures; ++i) {
        std::vector<MatchVectType> matchVect;
        // to maintain thread safety, we have to copy the pattern molecules:
        SubstructMatch(mol,ROMol(*featureMatchers[i],true),matchVect);
        BOOST_FOREACH(MatchVectType mv, matchVect) {
          for (MatchVectType::const_iterator mIt = mv.begin(); mIt != mv.end(); ++mIt){
            atomIds[i].push_back(mIt->second);
          }
        }
      } // end loop over features
    }

  } // end namespace

  namespace Descriptors {

    void USR(const ROMol &mol, std::vector<double> &descriptor, int confId) {
      PRECONDITION(descriptor.size() == 12, "descriptor must have 12 elements");
      unsigned int na = mol.getNumAtoms();
      // check that number of atoms > 3
      if (na < 3) {
        throw ValueErrorException("Number of atoms must be greater than 3");
      }
      // check that minimum a conformer exists
      if (mol.getNumConformers() == 0) {
        throw ConformerException("No conformations available on this molecule");
      }

      const Conformer &conf = mol.getConformer(confId);
      RDGeom::Point3DConstPtrVect coords(na);
      // loop over atoms
      for (unsigned int ai = 0; ai < na; ++ai) {
        coords[ai] = &conf.getAtomPos(ai);
      }
      // the four distances
      std::vector<std::vector<double> > dist(4);
      std::vector<RDGeom::Point3D> points(4);
      calcUSRDistributions(coords, dist, points);

      calcUSRFromDistributions(dist, descriptor);
    }

    void USRCAT(const ROMol &mol, std::vector<double> &descriptor,
                std::vector<std::vector<unsigned int> > &atomIds, int confId) {
      unsigned int na = mol.getNumAtoms();
      // check that number of atoms > 3
      if (na < 3) {
        throw ValueErrorException("Number of atoms must be greater than 3");
      }
      // check that minimum a conformer exists
      if (mol.getNumConformers() == 0) {
        throw ConformerException("No conformations available on this molecule");
      }

      // get atom selections
      unsigned int numClasses = atomIds.size();
      if (numClasses == 0) { // no user input, use default values
        numClasses = featureSmarts.size();
        atomIds.resize(numClasses);
        getAtomIdsForFeatures(mol, atomIds);
      }
      PRECONDITION(descriptor.size() == 12*(numClasses+1), "descriptor wrong size");

      const Conformer &conf = mol.getConformer(confId);
      RDGeom::Point3DConstPtrVect coords(na);
      // loop over atoms
      for (unsigned int ai = 0; ai < na; ++ai) {
        coords[ai] = &conf.getAtomPos(ai);
      }
      // the original USR
      std::vector<std::vector<double> > distribs(4);
      std::vector<RDGeom::Point3D> points(4);
      calcUSRDistributions(coords, distribs, points);
      std::vector<double> tmpDescriptor(12);
      calcUSRFromDistributions(distribs, tmpDescriptor);
      std::copy(tmpDescriptor.begin(), tmpDescriptor.end(), descriptor.begin());

      // loop over the atom selections
      unsigned int featIdx = 12;
      BOOST_FOREACH(std::vector<unsigned int> atomsInClass, atomIds) {
        // reduce the coordinates to the atoms of interest
        RDGeom::Point3DConstPtrVect reducedCoords;
        reducedCoords.reserve(atomsInClass.size());
        BOOST_FOREACH(unsigned int idx, atomsInClass) {
          reducedCoords.push_back(coords[idx]);
        }
        calcUSRDistributionsFromPoints(reducedCoords, points, distribs);
        calcUSRFromDistributions(distribs, tmpDescriptor);
        std::copy(tmpDescriptor.begin(), tmpDescriptor.end(), descriptor.begin()+featIdx);
        featIdx += 12;
      }
    }

    void calcUSRDistributions(const RDGeom::Point3DConstPtrVect &coords,
                              std::vector<std::vector<double> > &dist,
                              std::vector<RDGeom::Point3D> &points) {
      PRECONDITION(dist.size() == 4, "dist must have 4 elements");
      PRECONDITION(points.size() == 4, "points must have 4 elements");
      // ctd = centroid
      calcCentroid(coords, points[0]);
      calcDistances(coords, points[0], dist[0]);
      // catc = closest atom to centroid
      points[1] = (*coords[smallestValId(dist[0])]);
      calcDistances(coords, points[1], dist[1]);
      // fatc = farthest atom to centroid
      points[2] = (*coords[largestValId(dist[0])]);
      calcDistances(coords, points[2], dist[2]);
      // fatf = farthest atom to fatc
      points[3] = (*coords[largestValId(dist[2])]);
      calcDistances(coords, points[3], dist[3]);
    }

    void calcUSRDistributionsFromPoints(const RDGeom::Point3DConstPtrVect &coords,
                                        const std::vector<RDGeom::Point3D> &points,
                                        std::vector<std::vector<double> > &dist) {
      PRECONDITION(points.size() == dist.size(), "points and dist must have the same size");
      for (unsigned int i = 0; i < points.size(); ++i) {
         calcDistances(coords, points[i], dist[i]);
      }
    }

    void calcUSRFromDistributions(const std::vector<std::vector<double> > &dist,
                                  std::vector<double> &descriptor) {
      PRECONDITION(descriptor.size() == 3*dist.size(), "descriptor must have 3 times more elements than dist");
      for (unsigned int i = 0; i < dist.size(); ++i) {
        calcMoments(dist[i], descriptor, 3*i);
      }
    }

    double calcUSRScore(const std::vector<double> &d1, const std::vector<double> &d2,
                           const std::vector<double> &weights) {
      unsigned int num = 12; // length of each subset
      PRECONDITION(d1.size() == d2.size(), "descriptors must have the same size");
      PRECONDITION(weights.size() == (d1.size()/num), "size of weights not correct");
      double score = 1.0;
      for (unsigned int w = 0; w < (d1.size()/num); ++w) {
        double tmpScore = 0.0;
        unsigned int offset = num*w;
        for (unsigned int i = 0; i < num; ++i) {
            tmpScore += fabs(d1[i+offset] - d2[i+offset]);
        }
        tmpScore /= num;
        score += weights[w]*tmpScore;
      }
      return 1.0 / score;
    }

  } // end of namespace Descriptors
} //end of namespace RDKit
<commit_msg>small bug fix in USR descriptor<commit_after>// $Id$
//
//  Copyright (c) 2013, Novartis Institutes for BioMedical Research Inc.
//  All rights reserved.
//
// 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 Novartis Institutes for BioMedical Research Inc.
//       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.
//

#include <Geometry/point.h>
#include <Numerics/Vector.h>
#include <GraphMol/RDKitBase.h>
#include <GraphMol/SmilesParse/SmilesParse.h>
#include <GraphMol/Substruct/SubstructMatch.h>
#include <boost/foreach.hpp>
#include "USRDescriptor.h"

#include <boost/flyweight.hpp>
#include <boost/flyweight/key_value.hpp>
#include <boost/flyweight/no_tracking.hpp>

namespace RDKit{

  namespace {
    void calcDistances(const RDGeom::Point3DConstPtrVect &coords,
                       const RDGeom::Point3D &point,
                       std::vector<double> &distances) {
      distances.resize(coords.size());
      unsigned int i = 0;
      // loop over coordinates
      BOOST_FOREACH(const RDGeom::Point3D *tpp, coords) {
        distances[i++] = (*tpp-point).length();
      }
    }

    void calcCentroid(const RDGeom::Point3DConstPtrVect &coords,
                      RDGeom::Point3D &pt) {
      PRECONDITION(!coords.empty(),"no coordinates");
      // set pt to zero
      pt *= 0.0;
      // loop over coordinates
      BOOST_FOREACH(const RDGeom::Point3D *opt, coords) {
        pt += *opt;
      }
      pt /= coords.size();
    }

    unsigned int largestValId(const std::vector<double> &v) {
      PRECONDITION(!v.empty(),"no values");
      double res = v[0];
      unsigned int id = 0;
      for (unsigned int i = 1; i < v.size(); ++i) {
        if (v[i] > res) {
          res = v[i];
          id = i;
        }
      }
      return id;
    }

    unsigned int smallestValId(const std::vector<double> &v) {
      PRECONDITION(!v.empty(),"no values");
      double res = v[0];
      unsigned int id = 0;
      for (unsigned int i = 1; i < v.size(); ++i) {
        if (v[i] < res) {
          res = v[i];
          id = i;
        }
      }
      return id;
    }

    void calcMoments(const std::vector<double> &dist,
                     std::vector<double> &descriptor,
                     int idx) {
      std::vector<double> moments (3, 0.0);
      unsigned int numPts = dist.size();
      if (numPts > 0) {
        // 1. moment: mean
        for (unsigned int i = 0; i < numPts; ++i) {
          moments[0] += dist[i];
        }
        moments[0] /= numPts;
        // 2. moment: standard deviation
        // 3. moment: cubic root of skewness
        for (unsigned int i = 0; i < numPts; ++i) {
          double diff = dist[i] - moments[0];
          moments[1] += diff * diff;
          moments[2] += diff * diff * diff;
        }
        moments[1] = sqrt(moments[1] / numPts);
        moments[2] /= numPts;
        if (moments[1] == 0) {
          moments[2] = 0.0;
        } else {
          moments[2] = cbrt(moments[2] / (moments[1] * moments[1] * moments[1]));
        }
      }
      // add moments to descriptor
      std::copy(moments.begin(), moments.end(), descriptor.begin()+idx);
    }

    class ss_matcher {
      public:
        ss_matcher() {};
        ss_matcher(const std::string &pattern){
          RDKit::RWMol *p = RDKit::SmartsToMol(pattern);
          TEST_ASSERT(p);
          m_matcher.reset(p);
        };
        const RDKit::ROMol *getMatcher() const { return m_matcher.get(); };
      private:
        RDKit::ROMOL_SPTR m_matcher;
    };

    // Definitions for feature points from
    // http://hg.adrianschreyer.eu/usrcat/src/70e075d93cd2?at=default
    const char *smartsPatterns[4] = {
      "[#6+0!$(*~[#7,#8,F]),SH0+0v2,s+0,S^3,Cl+0,Br+0,I+0]", // hydrophobic
      "[a]", // aromatic
      "[$([O,S;H1;v2]-[!$(*=[O,N,P,S])]),$([O,S;H0;v2]),$([O,S;-]),\
$([N&v3;H1,H2]-[!$(*=[O,N,P,S])]),$([N;v3;H0]),$([n,o,s;+0]),F]", // acceptor
      "[N!H0v3,N!H0+v4,OH+0,SH+0,nH+0]" // donor
    };
    std::vector<std::string> featureSmarts(smartsPatterns,smartsPatterns+4);
    typedef boost::flyweight<boost::flyweights::key_value<std::string,ss_matcher>,boost::flyweights::no_tracking > pattern_flyweight;

    void getAtomIdsForFeatures(const ROMol &mol, std::vector<std::vector<unsigned int> > &atomIds) {
      unsigned int numFeatures = featureSmarts.size();
      PRECONDITION(atomIds.size() == numFeatures, "atomIds must have be the same size as featureSmarts");
      std::vector<const ROMol *> featureMatchers;
      featureMatchers.reserve(numFeatures);
      BOOST_FOREACH(const std::string &feature, featureSmarts) {
        const ROMol *matcher = pattern_flyweight(feature).get().getMatcher();
        featureMatchers.push_back(matcher);
      }
      for (unsigned int i = 0; i < numFeatures; ++i) {
        std::vector<MatchVectType> matchVect;
        // to maintain thread safety, we have to copy the pattern molecules:
        SubstructMatch(mol,ROMol(*featureMatchers[i],true),matchVect);
        BOOST_FOREACH(MatchVectType mv, matchVect) {
          for (MatchVectType::const_iterator mIt = mv.begin(); mIt != mv.end(); ++mIt){
            atomIds[i].push_back(mIt->second);
          }
        }
      } // end loop over features
    }

  } // end namespace

  namespace Descriptors {

    void USR(const ROMol &mol, std::vector<double> &descriptor, int confId) {
      PRECONDITION(descriptor.size() == 12, "descriptor must have 12 elements");
      unsigned int na = mol.getNumAtoms();
      // check that number of atoms > 3
      if (na < 3) {
        throw ValueErrorException("Number of atoms must be greater than 3");
      }
      // check that minimum a conformer exists
      if (mol.getNumConformers() == 0) {
        throw ConformerException("No conformations available on this molecule");
      }

      const Conformer &conf = mol.getConformer(confId);
      RDGeom::Point3DConstPtrVect coords(na);
      // loop over atoms
      for (unsigned int ai = 0; ai < na; ++ai) {
        coords[ai] = &conf.getAtomPos(ai);
      }
      // the four distances
      std::vector<std::vector<double> > dist(4);
      std::vector<RDGeom::Point3D> points(4);
      calcUSRDistributions(coords, dist, points);

      calcUSRFromDistributions(dist, descriptor);
    }

    void USRCAT(const ROMol &mol, std::vector<double> &descriptor,
                std::vector<std::vector<unsigned int> > &atomIds, int confId) {
      unsigned int na = mol.getNumAtoms();
      // check that number of atoms > 3
      if (na < 3) {
        throw ValueErrorException("Number of atoms must be greater than 3");
      }
      // check that minimum a conformer exists
      if (mol.getNumConformers() == 0) {
        throw ConformerException("No conformations available on this molecule");
      }

      // get atom selections
      unsigned int numClasses = atomIds.size();
      if (numClasses == 0) { // no user input, use default values
        numClasses = featureSmarts.size();
        atomIds.resize(numClasses);
        getAtomIdsForFeatures(mol, atomIds);
      }
      PRECONDITION(descriptor.size() == 12*(numClasses+1), "descriptor wrong size");

      const Conformer &conf = mol.getConformer(confId);
      RDGeom::Point3DConstPtrVect coords(na);
      // loop over atoms
      for (unsigned int ai = 0; ai < na; ++ai) {
        coords[ai] = &conf.getAtomPos(ai);
      }
      // the original USR
      std::vector<std::vector<double> > distribs(4);
      std::vector<RDGeom::Point3D> points(4);
      calcUSRDistributions(coords, distribs, points);
      std::vector<double> tmpDescriptor(12);
      calcUSRFromDistributions(distribs, tmpDescriptor);
      std::copy(tmpDescriptor.begin(), tmpDescriptor.end(), descriptor.begin());

      // loop over the atom selections
      unsigned int featIdx = 12;
      BOOST_FOREACH(std::vector<unsigned int> atomsInClass, atomIds) {
        // reduce the coordinates to the atoms of interest
        RDGeom::Point3DConstPtrVect reducedCoords;
        reducedCoords.reserve(atomsInClass.size());
        BOOST_FOREACH(unsigned int idx, atomsInClass) {
          reducedCoords.push_back(coords[idx]);
        }
        calcUSRDistributionsFromPoints(reducedCoords, points, distribs);
        calcUSRFromDistributions(distribs, tmpDescriptor);
        std::copy(tmpDescriptor.begin(), tmpDescriptor.end(), descriptor.begin()+featIdx);
        featIdx += 12;
      }
    }

    void calcUSRDistributions(const RDGeom::Point3DConstPtrVect &coords,
                              std::vector<std::vector<double> > &dist,
                              std::vector<RDGeom::Point3D> &points) {
      PRECONDITION(dist.size() == 4, "dist must have 4 elements");
      PRECONDITION(points.size() == 4, "points must have 4 elements");
      // ctd = centroid
      calcCentroid(coords, points[0]);
      calcDistances(coords, points[0], dist[0]);
      // catc = closest atom to centroid
      points[1] = (*coords[smallestValId(dist[0])]);
      calcDistances(coords, points[1], dist[1]);
      // fatc = farthest atom to centroid
      points[2] = (*coords[largestValId(dist[0])]);
      calcDistances(coords, points[2], dist[2]);
      // fatf = farthest atom to fatc
      points[3] = (*coords[largestValId(dist[2])]);
      calcDistances(coords, points[3], dist[3]);
    }

    void calcUSRDistributionsFromPoints(const RDGeom::Point3DConstPtrVect &coords,
                                        const std::vector<RDGeom::Point3D> &points,
                                        std::vector<std::vector<double> > &dist) {
      PRECONDITION(points.size() == dist.size(), "points and dist must have the same size");
      for (unsigned int i = 0; i < points.size(); ++i) {
         calcDistances(coords, points[i], dist[i]);
      }
    }

    void calcUSRFromDistributions(const std::vector<std::vector<double> > &dist,
                                  std::vector<double> &descriptor) {
      PRECONDITION(descriptor.size() == 3*dist.size(), "descriptor must have 3 times more elements than dist");
      for (unsigned int i = 0; i < dist.size(); ++i) {
        calcMoments(dist[i], descriptor, 3*i);
      }
    }

    double calcUSRScore(const std::vector<double> &d1, const std::vector<double> &d2,
                           const std::vector<double> &weights) {
      unsigned int num = 12; // length of each subset
      PRECONDITION(d1.size() == d2.size(), "descriptors must have the same size");
      PRECONDITION(weights.size() == (d1.size()/num), "size of weights not correct");
      double score = 1.0;
      for (unsigned int w = 0; w < (d1.size()/num); ++w) {
        double tmpScore = 0.0;
        unsigned int offset = num*w;
        for (unsigned int i = 0; i < num; ++i) {
            tmpScore += fabs(d1[i+offset] - d2[i+offset]);
        }
        tmpScore /= num;
        score += weights[w]*tmpScore;
      }
      return 1.0 / score;
    }

  } // end of namespace Descriptors
} //end of namespace RDKit
<|endoftext|>


<commit_before>// $Id$
//
//  Copyright (C) 2003-2008 Greg Landrum and Rational Discovery LLC
//
//   @@ All Rights Reserved  @@
//
#include <GraphMol/RDKitBase.h>
#include <DataStructs/ExplicitBitVect.h>
#include <DataStructs/BitOps.h>
#include "Fingerprints.h"
#include <GraphMol/Subgraphs/Subgraphs.h>
#include <GraphMol/Subgraphs/SubgraphUtils.h>
#include <RDGeneral/Invariant.h>
#include <boost/random.hpp>
#include <limits.h>
#include <boost/functional/hash.hpp>

namespace RDKit{
  // caller owns the result, it must be deleted
  ExplicitBitVect *DaylightFingerprintMol(const ROMol &mol,unsigned int minPath,
					  unsigned int maxPath,
					  unsigned int fpSize,unsigned int nBitsPerHash,
					  bool useHs,
					  double tgtDensity,unsigned int minSize){
    PRECONDITION(minPath!=0,"minPath==0");
    PRECONDITION(maxPath>=minPath,"maxPath<minPath");
    PRECONDITION(fpSize!=0,"fpSize==0");
    PRECONDITION(nBitsPerHash!=0,"nBitsPerHash==0");

    typedef boost::minstd_rand rng_type;
    typedef boost::uniform_int<> distrib_type;
    typedef boost::variate_generator<rng_type &,distrib_type> source_type;
    rng_type generator(42u);

    //
    // if we generate arbitrarily sized ints then mod them down to the
    // appropriate size, we can guarantee that a fingerprint of
    // size x has the same bits set as one of size 2x that's been folded
    // in half.  This is a nice guarantee to have.
    //
    distrib_type dist(0,INT_MAX);
    source_type randomSource(generator,dist);

    ExplicitBitVect *res = new ExplicitBitVect(fpSize);
    INT_PATH_LIST_MAP allPaths = findAllSubgraphsOfLengthsMtoN(mol,minPath,maxPath,
							       useHs);
    for(INT_PATH_LIST_MAP_CI paths=allPaths.begin();paths!=allPaths.end();paths++){
      for( PATH_LIST_CI pathIt=paths->second.begin();
	   pathIt!=paths->second.end();
	   pathIt++ ){
	const PATH_TYPE &path=*pathIt;
	float balabanJ = static_cast<float>(MolOps::computeBalabanJ(mol,true,true,
								    &path,false));

	unsigned long seed = *(unsigned long *)(&balabanJ);
	generator.seed(seed);

	for(unsigned int i=0;i<nBitsPerHash;i++){
	  unsigned int bit = randomSource();
	  bit %= fpSize;
	  res->SetBit(bit);
	}
      }
    }

    // EFF: this could be faster by folding by more than a factor
    // of 2 each time, but we're not going to be spending much
    // time here anyway
    while( static_cast<double>(res->GetNumOnBits())/res->GetNumBits() < tgtDensity &&
	   res->GetNumBits() >= 2*minSize ){
      ExplicitBitVect *tmpV=FoldFingerprint(*res,2);
      delete res;
      res = tmpV;
    }

    return res;
  }

  // caller owns the result, it must be deleted
  ExplicitBitVect *RDKFingerprintMol2(const ROMol &mol,unsigned int minPath,
                                      unsigned int maxPath,
                                      unsigned int fpSize,unsigned int nBitsPerHash,
                                      bool useHs,
                                      double tgtDensity,unsigned int minSize){
    PRECONDITION(minPath!=0,"minPath==0");
    PRECONDITION(maxPath>=minPath,"maxPath<minPath");
    PRECONDITION(fpSize!=0,"fpSize==0");
    PRECONDITION(nBitsPerHash!=0,"nBitsPerHash==0");

    typedef boost::minstd_rand rng_type;
    typedef boost::uniform_int<> distrib_type;
    typedef boost::variate_generator<rng_type &,distrib_type> source_type;
    rng_type generator(42u);

    //
    // if we generate arbitrarily sized ints then mod them down to the
    // appropriate size, we can guarantee that a fingerprint of
    // size x has the same bits set as one of size 2x that's been folded
    // in half.  This is a nice guarantee to have.
    //
    distrib_type dist(0,INT_MAX);
    source_type randomSource(generator,dist);

    ExplicitBitVect *res = new ExplicitBitVect(fpSize);
    INT_PATH_LIST_MAP allPaths = findAllSubgraphsOfLengthsMtoN(mol,minPath,maxPath,
							       useHs);
    std::set<unsigned long> hashesSeen;
    for(INT_PATH_LIST_MAP_CI paths=allPaths.begin();paths!=allPaths.end();paths++){
      for( PATH_LIST_CI pathIt=paths->second.begin();
	   pathIt!=paths->second.end();
	   pathIt++ ){
	const PATH_TYPE &path=*pathIt;

        // initialize the bond hashes to the number of neighbors the bond has in the path:
        std::vector<unsigned int> bondHashes(path.size());
        std::fill(bondHashes.begin(),bondHashes.end(),0);
        std::set<unsigned int> atomsInPath;
        for(unsigned int i=0;i<path.size();++i){
          const Bond *bi = mol.getBondWithIdx(path[i]);
          atomsInPath.insert(bi->getBeginAtomIdx());
          atomsInPath.insert(bi->getEndAtomIdx());
          for(unsigned int j=i+1;j<path.size();++j){
            const Bond *bj = mol.getBondWithIdx(path[j]);
            if(bi->getBeginAtomIdx()==bj->getBeginAtomIdx() ||
               bi->getBeginAtomIdx()==bj->getEndAtomIdx() ||
               bi->getEndAtomIdx()==bj->getBeginAtomIdx() ||
               bi->getEndAtomIdx()==bj->getEndAtomIdx() ){
              ++bondHashes[i];
              ++bondHashes[j];
            }
          }
          // we have the count of neighbors for bond bi, compute its hash:
          unsigned int a1Hash,a2Hash;
          a1Hash = (bi->getBeginAtom()->getAtomicNum()%128)<<1 | bi->getBeginAtom()->getIsAromatic();
          a2Hash = (bi->getEndAtom()->getAtomicNum()%128)<<1 | bi->getEndAtom()->getIsAromatic();
          if(a1Hash<a2Hash) std::swap(a1Hash,a2Hash);
          unsigned int bondHash;
          if(bi->getIsAromatic()){
            // makes sure aromatic bonds always hash the same:
            bondHash = Bond::AROMATIC;
          } else {
            bondHash = bi->getBondType();
          }
          unsigned int nBitsInHash=0;
          bondHashes[i] = bondHashes[i]%8; // 3 bits here
          nBitsInHash+=3;
          bondHashes[i] |= (bondHash%16)<<nBitsInHash; // 4 bits here
          nBitsInHash+=4;
          bondHashes[i] |= a1Hash<<nBitsInHash; // 8 bits
          nBitsInHash+=8;
          bondHashes[i] |= a2Hash<<nBitsInHash; // 8 bits
        }

        // ok, we have a hash for each bond, now order that list:
        bool reverseIt=false;
        for(unsigned int i=0;i<path.size();++i){
          for(unsigned int j=path.size()-1;j>i;--j){
            if(bondHashes[i]!=bondHashes[j]){
              if(bondHashes[i]<bondHashes[j]){
                reverseIt=true;
              }
              i=path.size()+1;
              break;
            }
          }
        }
        if(reverseIt){
          std::reverse(bondHashes.begin(),bondHashes.end());
        }
        // finally, we will add the number of distinct atoms in the path at the end
        // of the vect. This allows us to distinguish C1CC1 from CC(C)C
        bondHashes.push_back(atomsInPath.size());

        // hash the path to generate a seed:
        boost::hash<std::vector<unsigned int> > vectHasher;
	unsigned long seed = vectHasher(bondHashes);

        // if we've seen the seed already, don't bother resetting bits we've
        // already done:
        if(hashesSeen.find(seed)==hashesSeen.end()){
          hashesSeen.insert(seed);
          generator.seed(seed);
          for(unsigned int i=0;i<nBitsPerHash;i++){
            unsigned int bit = randomSource();
            bit %= fpSize;
            res->SetBit(bit);
          }
        }
      }
    }

    // EFF: this could be faster by folding by more than a factor
    // of 2 each time, but we're not going to be spending much
    // time here anyway
    if(tgtDensity>0.0){
      while( static_cast<double>(res->GetNumOnBits())/res->GetNumBits() < tgtDensity &&
             res->GetNumBits() >= 2*minSize ){
        ExplicitBitVect *tmpV=FoldFingerprint(*res,2);
        delete res;
        res = tmpV;
      }
    }

    return res;
  }

}
<commit_msg>make sure sim(C1CCC1,CCCC)>sim(C1CC1,CCC)<commit_after>// $Id$
//
//  Copyright (C) 2003-2008 Greg Landrum and Rational Discovery LLC
//
//   @@ All Rights Reserved  @@
//
#include <GraphMol/RDKitBase.h>
#include <DataStructs/ExplicitBitVect.h>
#include <DataStructs/BitOps.h>
#include "Fingerprints.h"
#include <GraphMol/Subgraphs/Subgraphs.h>
#include <GraphMol/Subgraphs/SubgraphUtils.h>
#include <RDGeneral/Invariant.h>
#include <boost/random.hpp>
#include <limits.h>
#include <boost/functional/hash.hpp>

namespace RDKit{
  // caller owns the result, it must be deleted
  ExplicitBitVect *DaylightFingerprintMol(const ROMol &mol,unsigned int minPath,
					  unsigned int maxPath,
					  unsigned int fpSize,unsigned int nBitsPerHash,
					  bool useHs,
					  double tgtDensity,unsigned int minSize){
    PRECONDITION(minPath!=0,"minPath==0");
    PRECONDITION(maxPath>=minPath,"maxPath<minPath");
    PRECONDITION(fpSize!=0,"fpSize==0");
    PRECONDITION(nBitsPerHash!=0,"nBitsPerHash==0");

    typedef boost::minstd_rand rng_type;
    typedef boost::uniform_int<> distrib_type;
    typedef boost::variate_generator<rng_type &,distrib_type> source_type;
    rng_type generator(42u);

    //
    // if we generate arbitrarily sized ints then mod them down to the
    // appropriate size, we can guarantee that a fingerprint of
    // size x has the same bits set as one of size 2x that's been folded
    // in half.  This is a nice guarantee to have.
    //
    distrib_type dist(0,INT_MAX);
    source_type randomSource(generator,dist);

    ExplicitBitVect *res = new ExplicitBitVect(fpSize);
    INT_PATH_LIST_MAP allPaths = findAllSubgraphsOfLengthsMtoN(mol,minPath,maxPath,
							       useHs);
    for(INT_PATH_LIST_MAP_CI paths=allPaths.begin();paths!=allPaths.end();paths++){
      for( PATH_LIST_CI pathIt=paths->second.begin();
	   pathIt!=paths->second.end();
	   pathIt++ ){
	const PATH_TYPE &path=*pathIt;
	float balabanJ = static_cast<float>(MolOps::computeBalabanJ(mol,true,true,
								    &path,false));

	unsigned long seed = *(unsigned long *)(&balabanJ);
	generator.seed(seed);

	for(unsigned int i=0;i<nBitsPerHash;i++){
	  unsigned int bit = randomSource();
	  bit %= fpSize;
	  res->SetBit(bit);
	}
      }
    }

    // EFF: this could be faster by folding by more than a factor
    // of 2 each time, but we're not going to be spending much
    // time here anyway
    while( static_cast<double>(res->GetNumOnBits())/res->GetNumBits() < tgtDensity &&
	   res->GetNumBits() >= 2*minSize ){
      ExplicitBitVect *tmpV=FoldFingerprint(*res,2);
      delete res;
      res = tmpV;
    }

    return res;
  }

  // caller owns the result, it must be deleted
  ExplicitBitVect *RDKFingerprintMol2(const ROMol &mol,unsigned int minPath,
                                      unsigned int maxPath,
                                      unsigned int fpSize,unsigned int nBitsPerHash,
                                      bool useHs,
                                      double tgtDensity,unsigned int minSize){
    PRECONDITION(minPath!=0,"minPath==0");
    PRECONDITION(maxPath>=minPath,"maxPath<minPath");
    PRECONDITION(fpSize!=0,"fpSize==0");
    PRECONDITION(nBitsPerHash!=0,"nBitsPerHash==0");

    typedef boost::minstd_rand rng_type;
    typedef boost::uniform_int<> distrib_type;
    typedef boost::variate_generator<rng_type &,distrib_type> source_type;
    rng_type generator(42u);

    //
    // if we generate arbitrarily sized ints then mod them down to the
    // appropriate size, we can guarantee that a fingerprint of
    // size x has the same bits set as one of size 2x that's been folded
    // in half.  This is a nice guarantee to have.
    //
    distrib_type dist(0,INT_MAX);
    source_type randomSource(generator,dist);

    ExplicitBitVect *res = new ExplicitBitVect(fpSize);
    INT_PATH_LIST_MAP allPaths = findAllSubgraphsOfLengthsMtoN(mol,minPath,maxPath,
							       useHs);
    std::set<unsigned long> hashesSeen;
    for(INT_PATH_LIST_MAP_CI paths=allPaths.begin();paths!=allPaths.end();paths++){
      for( PATH_LIST_CI pathIt=paths->second.begin();
	   pathIt!=paths->second.end();
	   pathIt++ ){
	const PATH_TYPE &path=*pathIt;
#ifdef VERBOSE_FINGERPRINTING
        std::cerr<<"Path: ";
        std::copy(path.begin(),path.end(),std::ostream_iterator<int>(std::cerr,", "));
        std::cerr<<std::endl;
#endif
        // initialize the bond hashes to the number of neighbors the bond has in the path:
        std::vector<unsigned int> bondNbrs(path.size());
        std::fill(bondNbrs.begin(),bondNbrs.end(),0);
        std::set<unsigned int> atomsInPath;
        std::vector<unsigned int> bondHashes;
        bondHashes.reserve(path.size()+1);
        for(unsigned int i=0;i<path.size();++i){
          const Bond *bi = mol.getBondWithIdx(path[i]);
          atomsInPath.insert(bi->getBeginAtomIdx());
          atomsInPath.insert(bi->getEndAtomIdx());
          for(unsigned int j=i+1;j<path.size();++j){
            const Bond *bj = mol.getBondWithIdx(path[j]);
            if(bi->getBeginAtomIdx()==bj->getBeginAtomIdx() ||
               bi->getBeginAtomIdx()==bj->getEndAtomIdx() ||
               bi->getEndAtomIdx()==bj->getBeginAtomIdx() ||
               bi->getEndAtomIdx()==bj->getEndAtomIdx() ){
              ++bondNbrs[i];
              ++bondNbrs[j];
            }
          }
#ifdef VERBOSE_FINGERPRINTING
          std::cerr<<"   bond("<<i<<"):"<<bondNbrs[i]<<std::endl;
#endif
          // we have the count of neighbors for bond bi, compute its hash:
          unsigned int a1Hash,a2Hash;
          a1Hash = (bi->getBeginAtom()->getAtomicNum()%128)<<1 | bi->getBeginAtom()->getIsAromatic();
          a2Hash = (bi->getEndAtom()->getAtomicNum()%128)<<1 | bi->getEndAtom()->getIsAromatic();
          if(a1Hash<a2Hash) std::swap(a1Hash,a2Hash);
          unsigned int bondHash;
          if(bi->getIsAromatic()){
            // makes sure aromatic bonds always hash the same:
            bondHash = Bond::AROMATIC;
          } else {
            bondHash = bi->getBondType();
          }
          unsigned int nBitsInHash=0;
          unsigned int ourHash=bondNbrs[i]%8; // 3 bits here
          nBitsInHash+=3;
          ourHash |= (bondHash%16)<<nBitsInHash; // 4 bits here
          nBitsInHash+=4;
          ourHash |= a1Hash<<nBitsInHash; // 8 bits
          nBitsInHash+=8;
          ourHash |= a2Hash<<nBitsInHash; // 8 bits
          bondHashes.insert(std::lower_bound(bondHashes.begin(),bondHashes.end(),ourHash),ourHash);
        }

        // ok, we have a hash for each bond, now order that list:
#if 0
        bool reverseIt=false;
        for(unsigned int i=0;i<path.size();++i){
          for(unsigned int j=path.size()-1;j>i;--j){
            if(bondNbrs[i]!=bondNbrs[j]){
              if(bondNbrs[i]<bondNbrs[j]){
                reverseIt=true;
              }
              i=path.size()+1;
              break;
            }
          }
        }
        if(reverseIt){
          std::reverse(bondNbrs.begin(),bondNbrs.end());
        }
#endif
        // finally, we will add the number of distinct atoms in the path at the end
        // of the vect. This allows us to distinguish C1CC1 from CC(C)C
        bondHashes.push_back(atomsInPath.size());

        // hash the path to generate a seed:
        boost::hash<std::vector<unsigned int> > vectHasher;
	unsigned long seed = vectHasher(bondHashes);

#ifdef VERBOSE_FINGERPRINTING
        std::cerr<<" hash: "<<seed<<std::endl;
#endif
        // if we've seen the seed already, don't bother resetting bits we've
        // already done:
        if(hashesSeen.find(seed)==hashesSeen.end()){
          hashesSeen.insert(seed);
          generator.seed(seed);
          for(unsigned int i=0;i<nBitsPerHash;i++){
            unsigned int bit = randomSource();
            bit %= fpSize;
            res->SetBit(bit);
          }
        }
      }
    }

    // EFF: this could be faster by folding by more than a factor
    // of 2 each time, but we're not going to be spending much
    // time here anyway
    if(tgtDensity>0.0){
      while( static_cast<double>(res->GetNumOnBits())/res->GetNumBits() < tgtDensity &&
             res->GetNumBits() >= 2*minSize ){
        ExplicitBitVect *tmpV=FoldFingerprint(*res,2);
        delete res;
        res = tmpV;
      }
    }

    return res;
  }

}
<|endoftext|>


<commit_before>/*
* This source file is part of ArkGameFrame
* For the latest info, see https://github.com/ArkGame
*
* Copyright (c) 2013-2018 ArkGame authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#include "AFCElementModule.h"
#include "AFCClassModule.h"
#include "SDK/Core/AFDataNode.h"

AFCElementModule::AFCElementModule(AFIPluginManager* p)
    : m_pClassModule(nullptr)
    , mbLoaded(false)
{
    pPluginManager = p;
}

AFCElementModule::~AFCElementModule()
{

}

bool AFCElementModule::Init()
{
    m_pClassModule = pPluginManager->FindModule<AFIClassModule>();

    return Load();
}

bool AFCElementModule::Shut()
{
    return Clear();
}

bool AFCElementModule::Load()
{
    if(mbLoaded)
    {
        return false;
    }

    ARK_SHARE_PTR<AFIClass> pLogicClass = m_pClassModule->First();
    while(nullptr != pLogicClass)
    {
        const std::string& strInstancePath = pLogicClass->GetInstancePath();
        if(strInstancePath.empty())
        {
            pLogicClass = m_pClassModule->Next();
            continue;
        }
        //////////////////////////////////////////////////////////////////////////
        rapidxml::xml_document<> xDoc;
        int nDataSize = 0;

        std::string strFile = pPluginManager->GetConfigPath() + strInstancePath;
        rapidxml::file<> fdoc(strFile.c_str());
        nDataSize = fdoc.size();
        ARK_SHARE_PTR<char>pData(new char[nDataSize + 1]);
        strncpy(pData.get(), fdoc.data(), nDataSize);

        pData.get()[nDataSize] = 0;
        xDoc.parse<0>(pData.get());
        //////////////////////////////////////////////////////////////////////////
        //support for unlimited layer class inherits
        rapidxml::xml_node<>* root = xDoc.first_node();
        for(rapidxml::xml_node<>* attrNode = root->first_node(); attrNode; attrNode = attrNode->next_sibling())
        {
            if(!Load(attrNode, pLogicClass))
            {
                return false;
            }
        }

        mbLoaded = true;
        pLogicClass = m_pClassModule->Next();
    }

    return true;
}

bool AFCElementModule::Load(rapidxml::xml_node<>* attrNode, ARK_SHARE_PTR<AFIClass> pLogicClass)
{
    //attrNode is the node of a object
    std::string strConfigID = attrNode->first_attribute("Id")->value();
    if(strConfigID.empty())
    {
        ARK_ASSERT(0, strConfigID, __FILE__, __FUNCTION__);
        return false;
    }

    if(ExistElement(strConfigID))
    {
        ARK_ASSERT(0, strConfigID, __FILE__, __FUNCTION__);
        return false;
    }

    ElementConfigInfo* pElementInfo = ARK_NEW ElementConfigInfo();
    mxElementConfigMap.AddElement(strConfigID, pElementInfo);

    //can find all config id by class name
    pLogicClass->AddConfigName(strConfigID);

    ARK_SHARE_PTR<AFIDataNodeManager> pElementNodeManager = pElementInfo->GetNodeManager();
    ARK_SHARE_PTR<AFIDataTableManager> pElementTableManager = pElementInfo->GetTableManager();

    //1.add DataNode
    //2.set the default value of them
    ARK_SHARE_PTR<AFIDataNodeManager> pClassNodeManager = pLogicClass->GetNodeManager();
    ARK_SHARE_PTR<AFIDataTableManager> pClassTableManager = pLogicClass->GetTableManager();
    if(pClassNodeManager != nullptr&& pClassTableManager != nullptr)
    {
        size_t nodeCount = pClassNodeManager->GetNodeCount();
        for(size_t i = 0; i < nodeCount; ++i)
        {
            AFDataNode* pNode = pClassNodeManager->GetNodeByIndex(i);
            if(pNode != nullptr)
            {
                pElementNodeManager->AddNode(pNode->name.c_str(), pNode->value, pNode->feature);
            }
        }
        //////////////////////////////////////////////////////////////////////////
        size_t tableCount = pClassTableManager->GetCount();
        for(size_t i = 0; i < tableCount; ++i)
        {
            AFDataTable* pTable = pClassTableManager->GetTableByIndex(i);
            if(pTable != nullptr)
            {
                continue;
            }

            AFCDataList col_type_list;
            pTable->GetColTypeList(col_type_list);
            int8_t feature = pTable->GetFeature();
            pElementTableManager->AddTable(NULL_GUID, pTable->GetName(), col_type_list, feature);
        }
    }

    //3.set the config value to them
    for(rapidxml::xml_attribute<>* pAttribute = attrNode->first_attribute(); pAttribute; pAttribute = pAttribute->next_attribute())
    {
        const char* pstrConfigName = pAttribute->name();
        const char* pstrConfigValue = pAttribute->value();

        AFDataNode* pTmpNode = pElementNodeManager->GetNode(pstrConfigName);
        if(pTmpNode == nullptr)
        {
            continue;
        }

        const int eType = pTmpNode->GetType();
        switch(eType)
        {
        case DT_BOOLEAN:
            {
                pTmpNode->value.SetInt(ARK_LEXICAL_CAST<bool>(pstrConfigValue));
            }
            break;
        case DT_INT:
            {
                if(!LegalNumber(pstrConfigValue))
                {
                    ARK_ASSERT(0, pTmpNode->name.c_str(), __FILE__, __FUNCTION__);
                }
                pTmpNode->value.SetInt(ARK_LEXICAL_CAST<int32_t>(pstrConfigValue));
            }
            break;
        case DT_INT64:
            {
                pTmpNode->value.SetInt64(ARK_LEXICAL_CAST<int64_t>(pstrConfigValue));
            }
            break;
        case DT_FLOAT:
            {
                if(strlen(pstrConfigValue) <= 0)
                {
                    ARK_ASSERT(0, pTmpNode->name.c_str(), __FILE__, __FUNCTION__);
                }
                pTmpNode->value.SetFloat(ARK_LEXICAL_CAST<float>(pstrConfigValue));
            }
            break;
        case DT_DOUBLE:
            {
                if(strlen(pstrConfigValue) <= 0)
                {
                    ARK_ASSERT(0, pTmpNode->name.c_str(), __FILE__, __FUNCTION__);
                }
                pTmpNode->value.SetDouble(ARK_LEXICAL_CAST<double>(pstrConfigValue));
            }
            break;
        case DT_STRING:
            {
                pTmpNode->value.SetString(pstrConfigValue);
            }
            break;
        case DT_OBJECT:
            {
                if(strlen(pstrConfigValue) <= 0)
                {
                    ARK_ASSERT(0, pTmpNode->name.c_str(), __FILE__, __FUNCTION__);
                }
                pTmpNode->value.SetObject(NULL_GUID);
            }
            break;
        default:
            ARK_ASSERT(0, pTmpNode->name.c_str(), __FILE__, __FUNCTION__);
            break;
        }
    }

    pElementNodeManager->SetNodeString("ClassName", pLogicClass->GetClassName().c_str());

    return true;
}

bool AFCElementModule::Save()
{
    return true;
}

bool AFCElementModule::GetNodeBool(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if(pNode != nullptr)
    {
        return pNode->value.GetBool();
    }

    return NULL_BOOLEAN;
}

int32_t AFCElementModule::GetNodeInt(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if (pNode != nullptr)
    {
        return pNode->value.GetInt();
    }

    return NULL_INT;
}

int64_t AFCElementModule::GetNodeInt64(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if (pNode != nullptr)
    {
        return pNode->value.GetInt64();
    }

    return NULL_INT64;
}

float AFCElementModule::GetNodeFloat(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if (pNode != nullptr)
    {
        return pNode->value.GetFloat();
    }

    return NULL_FLOAT;
}

double AFCElementModule::GetNodeDouble(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if (pNode != nullptr)
    {
        return pNode->value.GetDouble();
    }

    return NULL_DOUBLE;
}

const char* AFCElementModule::GetNodeString(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if (pNode != nullptr)
    {
        return pNode->value.GetString();
    }

    return nullptr;
}

AFDataNode* AFCElementModule::GetNode(const std::string& strConfigName, const std::string& strDataNodeName)
{
    ElementConfigInfo* pElementInfo = mxElementConfigMap.GetElement(strConfigName);
    if(pElementInfo != nullptr)
    {
        return pElementInfo->GetNodeManager()->GetNode(strDataNodeName.c_str());
    }

    return nullptr;
}

ARK_SHARE_PTR<AFIDataNodeManager> AFCElementModule::GetNodeManager(const std::string& strConfigName)
{
    ElementConfigInfo* pElementInfo = mxElementConfigMap.GetElement(strConfigName);
    if(pElementInfo != nullptr)
    {
        return pElementInfo->GetNodeManager();
    }

    return nullptr;
}

ARK_SHARE_PTR<AFIDataTableManager> AFCElementModule::GetTableManager(const std::string& strConfigName)
{
    ElementConfigInfo* pElementInfo = mxElementConfigMap.GetElement(strConfigName);
    if(pElementInfo != nullptr)
    {
        return pElementInfo->GetTableManager();
    }

    return nullptr;
}

bool AFCElementModule::ExistElement(const std::string& strConfigName)
{
    ElementConfigInfo* pElementInfo = mxElementConfigMap.GetElement(strConfigName);
    return (pElementInfo != nullptr);
}

bool AFCElementModule::ExistElement(const std::string& strClassName, const std::string& strConfigName)
{
    ElementConfigInfo* pElementInfo = mxElementConfigMap.GetElement(strConfigName);
    if(pElementInfo == nullptr)
    {
        return false;
    }

    const std::string strClass(pElementInfo->GetNodeManager()->GetNodeString("ClassName"));
    if(strClass != strClassName)
    {
        return false;
    }

    return true;
}

bool AFCElementModule::LegalNumber(const char* str)
{
    int nLen = int(strlen(str));
    if(nLen <= 0)
    {
        return false;
    }

    int nStart = 0;
    if('-' == str[0])
    {
        nStart = 1;
    }

    for(int i = nStart; i < nLen; ++i)
    {
        if(!isdigit(str[i]))
        {
            return false;
        }
    }

    return true;
}

bool AFCElementModule::AfterInit()
{
    return true;

}

bool AFCElementModule::BeforeShut()
{
    return true;

}

void AFCElementModule::Update()
{

}

bool AFCElementModule::Clear()
{
    mxElementConfigMap.Clear();

    mbLoaded = false;
    return true;
}

//ARK_SHARE_PTR<AFIComponentManager> AFCElementModule::GetComponentManager(const std::string& strConfigName)
//{
//    ARK_SHARE_PTR<ElementConfigInfo> pElementInfo = GetElement(strConfigName);
//    if(nullptr != pElementInfo)
//    {
//        return pElementInfo->GetComponentManager();
//    }
//
//    return nullptr;
//}
<commit_msg>fix an error type<commit_after>/*
* This source file is part of ArkGameFrame
* For the latest info, see https://github.com/ArkGame
*
* Copyright (c) 2013-2018 ArkGame authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#include "AFCElementModule.h"
#include "AFCClassModule.h"
#include "SDK/Core/AFDataNode.h"

AFCElementModule::AFCElementModule(AFIPluginManager* p)
    : m_pClassModule(nullptr)
    , mbLoaded(false)
{
    pPluginManager = p;
}

AFCElementModule::~AFCElementModule()
{

}

bool AFCElementModule::Init()
{
    m_pClassModule = pPluginManager->FindModule<AFIClassModule>();

    return Load();
}

bool AFCElementModule::Shut()
{
    return Clear();
}

bool AFCElementModule::Load()
{
    if(mbLoaded)
    {
        return false;
    }

    ARK_SHARE_PTR<AFIClass> pLogicClass = m_pClassModule->First();
    while(nullptr != pLogicClass)
    {
        const std::string& strInstancePath = pLogicClass->GetInstancePath();
        if(strInstancePath.empty())
        {
            pLogicClass = m_pClassModule->Next();
            continue;
        }
        //////////////////////////////////////////////////////////////////////////
        rapidxml::xml_document<> xDoc;
        int nDataSize = 0;

        std::string strFile = pPluginManager->GetConfigPath() + strInstancePath;
        rapidxml::file<> fdoc(strFile.c_str());
        nDataSize = fdoc.size();
        ARK_SHARE_PTR<char>pData(new char[nDataSize + 1]);
        strncpy(pData.get(), fdoc.data(), nDataSize);

        pData.get()[nDataSize] = 0;
        xDoc.parse<0>(pData.get());
        //////////////////////////////////////////////////////////////////////////
        //support for unlimited layer class inherits
        rapidxml::xml_node<>* root = xDoc.first_node();
        for(rapidxml::xml_node<>* attrNode = root->first_node(); attrNode; attrNode = attrNode->next_sibling())
        {
            if(!Load(attrNode, pLogicClass))
            {
                return false;
            }
        }

        mbLoaded = true;
        pLogicClass = m_pClassModule->Next();
    }

    return true;
}

bool AFCElementModule::Load(rapidxml::xml_node<>* attrNode, ARK_SHARE_PTR<AFIClass> pLogicClass)
{
    //attrNode is the node of a object
    std::string strConfigID = attrNode->first_attribute("Id")->value();
    if(strConfigID.empty())
    {
        ARK_ASSERT(0, strConfigID, __FILE__, __FUNCTION__);
        return false;
    }

    if(ExistElement(strConfigID))
    {
        ARK_ASSERT(0, strConfigID, __FILE__, __FUNCTION__);
        return false;
    }

    ElementConfigInfo* pElementInfo = ARK_NEW ElementConfigInfo();
    mxElementConfigMap.AddElement(strConfigID, pElementInfo);

    //can find all config id by class name
    pLogicClass->AddConfigName(strConfigID);

    ARK_SHARE_PTR<AFIDataNodeManager> pElementNodeManager = pElementInfo->GetNodeManager();
    ARK_SHARE_PTR<AFIDataTableManager> pElementTableManager = pElementInfo->GetTableManager();

    //1.add DataNode
    //2.set the default value of them
    ARK_SHARE_PTR<AFIDataNodeManager> pClassNodeManager = pLogicClass->GetNodeManager();
    ARK_SHARE_PTR<AFIDataTableManager> pClassTableManager = pLogicClass->GetTableManager();
    if(pClassNodeManager != nullptr&& pClassTableManager != nullptr)
    {
        size_t nodeCount = pClassNodeManager->GetNodeCount();
        for(size_t i = 0; i < nodeCount; ++i)
        {
            AFDataNode* pNode = pClassNodeManager->GetNodeByIndex(i);
            if(pNode != nullptr)
            {
                pElementNodeManager->AddNode(pNode->name.c_str(), pNode->value, pNode->feature);
            }
        }
        //////////////////////////////////////////////////////////////////////////
        size_t tableCount = pClassTableManager->GetCount();
        for(size_t i = 0; i < tableCount; ++i)
        {
            AFDataTable* pTable = pClassTableManager->GetTableByIndex(i);
            if(pTable != nullptr)
            {
                continue;
            }

            AFCDataList col_type_list;
            pTable->GetColTypeList(col_type_list);
            int8_t feature = pTable->GetFeature();
            pElementTableManager->AddTable(NULL_GUID, pTable->GetName(), col_type_list, feature);
        }
    }

    //3.set the config value to them
    for(rapidxml::xml_attribute<>* pAttribute = attrNode->first_attribute(); pAttribute; pAttribute = pAttribute->next_attribute())
    {
        const char* pstrConfigName = pAttribute->name();
        const char* pstrConfigValue = pAttribute->value();

        AFDataNode* pTmpNode = pElementNodeManager->GetNode(pstrConfigName);
        if(pTmpNode == nullptr)
        {
            continue;
        }

        const int eType = pTmpNode->GetType();
        switch(eType)
        {
        case DT_BOOLEAN:
            {
                pTmpNode->value.SetBool(ARK_LEXICAL_CAST<bool>(pstrConfigValue));
            }
            break;
        case DT_INT:
            {
                if(!LegalNumber(pstrConfigValue))
                {
                    ARK_ASSERT(0, pTmpNode->name.c_str(), __FILE__, __FUNCTION__);
                }
                pTmpNode->value.SetInt(ARK_LEXICAL_CAST<int32_t>(pstrConfigValue));
            }
            break;
        case DT_INT64:
            {
                pTmpNode->value.SetInt64(ARK_LEXICAL_CAST<int64_t>(pstrConfigValue));
            }
            break;
        case DT_FLOAT:
            {
                if(strlen(pstrConfigValue) <= 0)
                {
                    ARK_ASSERT(0, pTmpNode->name.c_str(), __FILE__, __FUNCTION__);
                }
                pTmpNode->value.SetFloat(ARK_LEXICAL_CAST<float>(pstrConfigValue));
            }
            break;
        case DT_DOUBLE:
            {
                if(strlen(pstrConfigValue) <= 0)
                {
                    ARK_ASSERT(0, pTmpNode->name.c_str(), __FILE__, __FUNCTION__);
                }
                pTmpNode->value.SetDouble(ARK_LEXICAL_CAST<double>(pstrConfigValue));
            }
            break;
        case DT_STRING:
            {
                pTmpNode->value.SetString(pstrConfigValue);
            }
            break;
        case DT_OBJECT:
            {
                if(strlen(pstrConfigValue) <= 0)
                {
                    ARK_ASSERT(0, pTmpNode->name.c_str(), __FILE__, __FUNCTION__);
                }
                pTmpNode->value.SetObject(NULL_GUID);
            }
            break;
        default:
            ARK_ASSERT(0, pTmpNode->name.c_str(), __FILE__, __FUNCTION__);
            break;
        }
    }

    pElementNodeManager->SetNodeString("ClassName", pLogicClass->GetClassName().c_str());

    return true;
}

bool AFCElementModule::Save()
{
    return true;
}

bool AFCElementModule::GetNodeBool(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if(pNode != nullptr)
    {
        return pNode->value.GetBool();
    }

    return NULL_BOOLEAN;
}

int32_t AFCElementModule::GetNodeInt(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if (pNode != nullptr)
    {
        return pNode->value.GetInt();
    }

    return NULL_INT;
}

int64_t AFCElementModule::GetNodeInt64(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if (pNode != nullptr)
    {
        return pNode->value.GetInt64();
    }

    return NULL_INT64;
}

float AFCElementModule::GetNodeFloat(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if (pNode != nullptr)
    {
        return pNode->value.GetFloat();
    }

    return NULL_FLOAT;
}

double AFCElementModule::GetNodeDouble(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if (pNode != nullptr)
    {
        return pNode->value.GetDouble();
    }

    return NULL_DOUBLE;
}

const char* AFCElementModule::GetNodeString(const std::string& strConfigName, const std::string& strDataNodeName)
{
    AFDataNode* pNode = GetNode(strConfigName, strDataNodeName);
    if (pNode != nullptr)
    {
        return pNode->value.GetString();
    }

    return nullptr;
}

AFDataNode* AFCElementModule::GetNode(const std::string& strConfigName, const std::string& strDataNodeName)
{
    ElementConfigInfo* pElementInfo = mxElementConfigMap.GetElement(strConfigName);
    if(pElementInfo != nullptr)
    {
        return pElementInfo->GetNodeManager()->GetNode(strDataNodeName.c_str());
    }

    return nullptr;
}

ARK_SHARE_PTR<AFIDataNodeManager> AFCElementModule::GetNodeManager(const std::string& strConfigName)
{
    ElementConfigInfo* pElementInfo = mxElementConfigMap.GetElement(strConfigName);
    if(pElementInfo != nullptr)
    {
        return pElementInfo->GetNodeManager();
    }

    return nullptr;
}

ARK_SHARE_PTR<AFIDataTableManager> AFCElementModule::GetTableManager(const std::string& strConfigName)
{
    ElementConfigInfo* pElementInfo = mxElementConfigMap.GetElement(strConfigName);
    if(pElementInfo != nullptr)
    {
        return pElementInfo->GetTableManager();
    }

    return nullptr;
}

bool AFCElementModule::ExistElement(const std::string& strConfigName)
{
    ElementConfigInfo* pElementInfo = mxElementConfigMap.GetElement(strConfigName);
    return (pElementInfo != nullptr);
}

bool AFCElementModule::ExistElement(const std::string& strClassName, const std::string& strConfigName)
{
    ElementConfigInfo* pElementInfo = mxElementConfigMap.GetElement(strConfigName);
    if(pElementInfo == nullptr)
    {
        return false;
    }

    const std::string strClass(pElementInfo->GetNodeManager()->GetNodeString("ClassName"));
    if(strClass != strClassName)
    {
        return false;
    }

    return true;
}

bool AFCElementModule::LegalNumber(const char* str)
{
    int nLen = int(strlen(str));
    if(nLen <= 0)
    {
        return false;
    }

    int nStart = 0;
    if('-' == str[0])
    {
        nStart = 1;
    }

    for(int i = nStart; i < nLen; ++i)
    {
        if(!isdigit(str[i]))
        {
            return false;
        }
    }

    return true;
}

bool AFCElementModule::AfterInit()
{
    return true;

}

bool AFCElementModule::BeforeShut()
{
    return true;

}

void AFCElementModule::Update()
{

}

bool AFCElementModule::Clear()
{
    mxElementConfigMap.Clear();

    mbLoaded = false;
    return true;
}

//ARK_SHARE_PTR<AFIComponentManager> AFCElementModule::GetComponentManager(const std::string& strConfigName)
//{
//    ARK_SHARE_PTR<ElementConfigInfo> pElementInfo = GetElement(strConfigName);
//    if(nullptr != pElementInfo)
//    {
//        return pElementInfo->GetComponentManager();
//    }
//
//    return nullptr;
//}
<|endoftext|>


<commit_before>#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <iterator>

template <class T>
class Node {

private:
    typedef typename T::const_iterator iter;
    typedef typename T::difference_type difftype;

    void Insert(iter a, iter b);
    void Walk(std::vector<T> &out);
    void Display(int);
    void Display(void (*fcn) (Node<T>), int level);
    typename T::difference_type DifferAt(iter beg);

public:
    Node() {};
    explicit Node(const T &pre) :
	prefix(pre) {
	Nodes.reserve(26);
    };

    Node(T &pre, const Node<T> &n) :
	prefix(pre) {
	Nodes.reserve(26);
	Nodes.push_back(n);
    }

    Node(iter a, iter b) :
	prefix(a,b) {
	Nodes.reserve(26);
    };

    Node(const Node<T>& rhs) :
	prefix(rhs.prefix), Nodes(rhs.Nodes) {};

    const Node<T>& operator=(const Node<T>& rhs) {
    return rhs;
    }

    void Display();
    void Display(void (*fcn) (Node<T>));
    void Insert(const T &a);
    std::vector<T> Walk();

    T prefix;
    std::vector<Node<T> > Nodes;

};

template <class T>
typename T::difference_type Node<T>::DifferAt(Node<T>::iter beg) {
    auto nodebeg = prefix.begin();
    auto storeend = prefix.end();
    auto storebeg = beg;

    for (; (nodebeg != storeend) && (*beg == *nodebeg); ++nodebeg ) {
	++beg;
    }
    return std::distance(storebeg, beg);
}

template <class T>
void Node<T>::Insert(const T &newitem) {
    Insert(newitem.begin(), newitem.end());
}

template <class T>
void Node<T>::Insert(Node<T>::iter beg, Node<T>::iter end) {

    for (auto nbeg = Nodes.begin(); nbeg != Nodes.end(); ++nbeg) {
	auto sub = nbeg->DifferAt(beg);

	T ssub = T(beg,beg+sub);

	if (ssub == nbeg->prefix) {
	    nbeg->Insert(beg+sub,end);
	    return;
	}

	if (ssub.size() > 0) {
	    nbeg->prefix.assign(ssub);
	    *nbeg = Node<T>(ssub, *nbeg);
	    nbeg->Insert(beg+sub,end);
	    return;
	}
    }

    Nodes.push_back(Node<T>(beg,end));
}

template <class T>
std::vector<T> Node<T>::Walk() {
    std::vector<T> out;
    out.push_back(prefix);

    for (auto beg = Nodes.begin(); beg != Nodes.end(); ++beg) {
	beg->Walk(out);
    }

    return out;
}

template <class T>
void Node<T>::Walk(std::vector<T> &out) {
    out.push_back(prefix);

    for (auto beg = Nodes.begin(); beg != Nodes.end(); ++beg) {
	beg->Walk(out);
    }
}

template <class T>
void Node<T>::Display() {

    std::cout << "Prefix tree: " << prefix << std::endl;
    for (auto b = Nodes.begin(); b != Nodes.end(); ++b) {
	b->Display(1);
    }
}

template <class T>
void Node<T>::Display(int level) {
    std::cout << std::string(level, '\t') << prefix << std::endl;
    for (auto b = Nodes.begin(); b != Nodes.end(); ++b) {
	b->Display(level+1);
    }
}

template <class T>
void Node<T>::Display(void (*fcn) (Node<T>)) {
    std::cout << "Prefix tree: ";
    fcn(*this);
    std::cout << std::endl;

    for (auto seg : Nodes)
	seg.Display(fcn, 1);
}

template <class T>
void Node<T>::Display(void (*fcn) (Node<T>), int level) {
    std::cout << std::string(level, '\t');
    std::cout << ".";
    fcn(*this);
    std::cout << std::endl;
    for (auto seg : Nodes)
	seg.Display(fcn, level+1);
}

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

    Node<std::string> n;
    n.Display();
    return 0;
}
<commit_msg>Further optimizations<commit_after>#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <iterator>

template <class T>
class Node {

private:
    typedef typename T::const_iterator iter;
    typedef typename T::difference_type difftype;

    void Insert(iter a, iter b);
    void Walk(std::vector<T> &out);
    void Display(int);
    void Display(void (*fcn) (Node<T>), int level);
    typename T::difference_type DifferAt(iter beg);

public:
    Node() {};
    explicit Node(const T &pre) :
	prefix(pre) {};

    explicit Node(T &pre, const Node<T> &n) :
	prefix(pre), Nodes(1,n) {};

    explicit Node(iter a, iter b) :
	prefix(a,b) {};

    const Node<T>& operator=(const Node<T>& rhs) {
	return rhs;
    }

    void Display();
    void Display(void (*fcn) (Node<T>));
    void Insert(const T &a);
    std::vector<T> Walk();

    T prefix;
    std::vector<Node<T> > Nodes;

};

template <class T>
typename T::difference_type Node<T>::DifferAt(Node<T>::iter beg) {
    auto nodebeg = prefix.begin();
    auto storeend = prefix.end();
    auto storebeg = beg;

    for (; (nodebeg != storeend) && (*beg == *nodebeg); ++nodebeg ) {
	++beg;
    }
    return std::distance(storebeg, beg);
}

template <class T>
void Node<T>::Insert(const T &newitem) {
    Insert(newitem.begin(), newitem.end());
}

template <class T>
void Node<T>::Insert(Node<T>::iter beg, Node<T>::iter end) {

    for (auto nbeg = Nodes.begin(); nbeg != Nodes.end(); ++nbeg) {
	auto sub = nbeg->DifferAt(beg);

	T ssub = T(beg,beg+sub);

	if (ssub == nbeg->prefix) {
	    nbeg->Insert(beg+sub,end);
	    return;
	}

	if (ssub.size() > 0) {
	    nbeg->prefix.assign(ssub);
	    *nbeg = Node<T>(ssub, *nbeg);
	    nbeg->Insert(beg+sub,end);
	    return;
	}
    }

    Nodes.push_back(Node<T>(beg,end));
}

template <class T>
std::vector<T> Node<T>::Walk() {
    std::vector<T> out;
    out.push_back(prefix);

    for (auto beg = Nodes.begin(); beg != Nodes.end(); ++beg) {
	beg->Walk(out);
    }

    return out;
}

template <class T>
void Node<T>::Walk(std::vector<T> &out) {
    out.push_back(prefix);

    for (auto beg = Nodes.begin(); beg != Nodes.end(); ++beg) {
	beg->Walk(out);
    }
}

template <class T>
void Node<T>::Display() {

    std::cout << "Prefix tree: " << prefix << std::endl;
    for (auto b = Nodes.begin(); b != Nodes.end(); ++b) {
	b->Display(1);
    }
}

template <class T>
void Node<T>::Display(int level) {
    std::cout << std::string(level, '\t') << prefix << std::endl;
    for (auto b = Nodes.begin(); b != Nodes.end(); ++b) {
	b->Display(level+1);
    }
}

template <class T>
void Node<T>::Display(void (*fcn) (Node<T>)) {
    std::cout << "Prefix tree: ";
    fcn(*this);
    std::cout << std::endl;

    for (auto seg : Nodes)
	seg.Display(fcn, 1);
}

template <class T>
void Node<T>::Display(void (*fcn) (Node<T>), int level) {
    std::cout << std::string(level, '\t');
    std::cout << ".";
    fcn(*this);
    std::cout << std::endl;
    for (auto seg : Nodes)
	seg.Display(fcn, level+1);
}

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

    Node<std::string> n;

    if (argc < 2) {
	std::cout << "Please supply a file" << std::endl;
    }

    std::ifstream infile(argv[1], std::ifstream::in);

    std::string s;
    while (!infile.eof()) {
	std::getline(infile, s);
	n.Insert(s);
    }
    return 0;
}
<|endoftext|>


<commit_before><commit_msg>bump.cpp: use float literal as vector operand (GNU extension?)<commit_after><|endoftext|>


<commit_before><commit_msg>[fix] elegant<commit_after><|endoftext|>


<commit_before><commit_msg>Add scheduler to AppInit<commit_after><|endoftext|>


<commit_before><commit_msg>Mining Rewards Back To 99 at block 110,000<commit_after><|endoftext|>


<commit_before><commit_msg>fixes<commit_after><|endoftext|>


<commit_before><commit_msg>Reindexing fleg fixed<commit_after><|endoftext|>


<commit_before><commit_msg>Print blank line after debug output chunk<commit_after><|endoftext|>


<commit_before><commit_msg>Added nanovg import<commit_after><|endoftext|>


<commit_before><commit_msg>Two programs<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: msgpool.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 23:06:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"

#ifndef _STREAM_HXX //autogen
#include <tools/stream.hxx>
#endif
#ifndef _RSCSFX_HXX //autogen
#include <rsc/rscsfx.hxx>
#endif
#ifndef GCC
#endif

// wg. pSlotPool
#include "appdata.hxx"
#include <sfx2/msgpool.hxx>
#include <sfx2/minarray.hxx>
#include <sfx2/msg.hxx>
#include <sfx2/app.hxx>
#include <sfx2/objface.hxx>
#include "sfxtypes.hxx"
#include <sfx2/macrconf.hxx>
#include "sfxresid.hxx"
#include "arrdecl.hxx"
#include <sfx2/module.hxx>

#include <sfx2/sfx.hrc>

//====================================================================

struct SfxSIDRegistration_Impl
{
    String          _aGroup;
    String          _aName;
    USHORT          _nSID;
};

struct SfxSlotType_Impl
{
    USHORT  nId;
    TypeId  nType;

    SfxSlotType_Impl( USHORT nTheId, TypeId nTheType ):
        nId(nTheId), nType(nTheType)
    {}
};

DECL_2BYTEARRAY(SfxSlotGroupArr_Impl, USHORT, 6, 4)
DECL_PTRARRAY(SfxInterfaceArr_Impl, SfxInterface*, 6, 3)
DECL_PTRARRAY(SfxSlotTypeArr_Impl, SfxSlotType_Impl*, 8, 8)

//====================================================================

SfxSlotPool::SfxSlotPool( SfxSlotPool *pParent, ResMgr* pResManager )
 : _pGroups(0)
 , _pTypes(0)
 , _pParentPool( pParent )
 , _pResMgr( pResManager )
 , _pInterfaces(0)
 , _nCurGroup(0)
 , _nCurInterface(0)
 , _nCurMsg(0)
 , _pUnoSlots( 0 )
{
    if ( !_pResMgr )
        _pResMgr = SfxApplication::GetOrCreate()->GetOffResManager_Impl();
}

//====================================================================

SfxSlotPool::~SfxSlotPool()
{
    _pParentPool = 0;
    for ( SfxInterface *pIF = FirstInterface(); pIF; pIF = FirstInterface() )
        delete pIF;
    delete _pInterfaces;
    delete _pGroups;
    if ( _pTypes )
    {
        for ( USHORT n =_pTypes->Count(); n--; )
            delete _pTypes->GetObject(n);
        delete _pTypes;
    }
}

//====================================================================

// registers the availability of the Interface of functions

void SfxSlotPool::RegisterInterface( SfxInterface& rInterface )
{
    DBG_MEMTEST();

    // add to the list of SfxObjectInterface instances
    if ( _pInterfaces == 0 )
        _pInterfaces = new SfxInterfaceArr_Impl;
    _pInterfaces->Append(&rInterface);

    // bei einem (einzelnen) Null-Slot abbrechen (aus syntaktischen Gr"unden
    // enthalten interfaces immer mindestens einen Slot)
    if ( rInterface.Count() == 1 && !rInterface[0]->nSlotId )
        return;

    // possibly add Interface-id and group-ids of funcs to the list of groups
    if ( !_pGroups )
    {
        _pGroups = new SfxSlotGroupArr_Impl;

        if ( _pParentPool )
        {
            // Die Groups im parent Slotpool sind auch hier bekannt
            SfxSlotGroupArr_Impl& rGroups = *_pParentPool->_pGroups;
            for ( USHORT n=0; n<rGroups.Count(); n++ )
                _pGroups->Append( rGroups[n] );
        }
    }

    if ( !_pTypes )
        _pTypes = new SfxSlotTypeArr_Impl;
    for ( USHORT nFunc = 0; nFunc < rInterface.Count(); ++nFunc )
    {
        SfxSlot *pDef = rInterface[nFunc];
        if ( pDef->GetGroupId() && /* pDef->GetGroupId() != GID_INTERN && */
             !_pGroups->Contains(pDef->GetGroupId()) )
        {
            if (pDef->GetGroupId() == GID_INTERN)
                _pGroups->Insert(0, pDef->GetGroupId());
            else
                _pGroups->Append(pDef->GetGroupId());
        }
#if 0
        const TypeId &rTypeId = pDef->GetType()->Type();
        if ( /*rTypeId != TYPE(SfxVoidItem) &&*/ rTypeId != 0 )
        {
            USHORT nPos;
            for ( nPos = 0; nPos < _pTypes->Count(); ++nPos )
            {
                if ( _pTypes->GetObject(nPos)->nId == pDef->GetSlotId() )
                {
                    DBG_ASSERT( rTypeId == _pTypes->GetObject(nPos)->nType,
                                "same slot id with unequal item types" );
                }
                else if ( _pTypes->GetObject(nPos)->nId > pDef->GetSlotId() )
                    break;
            }
            if ( nPos >= _pTypes->Count() ||
                 _pTypes->GetObject(nPos)->nId > pDef->GetSlotId() )
                _pTypes->Append( new SfxSlotType_Impl( pDef->GetSlotId(), rTypeId ) );
        }
#endif
    }
}

//====================================================================

TypeId SfxSlotPool::GetSlotType( USHORT nId ) const
{
    const SfxSlot* pSlot = (const_cast <SfxSlotPool*> (this))->GetSlot( nId );
    return pSlot ? pSlot->GetType()->Type() : 0;
/*
    for ( USHORT nPos = 0; nPos < _pTypes->Count(); ++nPos )
    {
        if ( _pTypes->GetObject(nPos)->nId == nId )
            return _pTypes->GetObject(nPos)->nType;
    }
    return _pParentPool ? _pParentPool->GetSlotType( nId ) : 0;
 */
}

//====================================================================

// unregisters the availability of the Interface of functions

void SfxSlotPool::ReleaseInterface( SfxInterface& rInterface )
{
    DBG_MEMTEST();
    DBG_ASSERT( _pInterfaces, "releasing SfxInterface, but there are none" );
    // remove from the list of SfxInterface instances
    _pInterfaces->Remove(&rInterface);
}

//--------------------------------------------------------------------

// get the first SfxMessage for a special Id (e.g. for getting check-mode)

const SfxSlot* SfxSlotPool::GetSlot( USHORT nId )
{
    DBG_MEMTEST();
    DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );

    // Zun"achst die eigenen Interfaces absuchen
    for ( USHORT nInterf = 0; nInterf < _pInterfaces->Count(); ++nInterf )
    {
        const SfxSlot *pDef = _pInterfaces->GetObject(nInterf)->GetSlot(nId);
        if ( pDef )
            return pDef;
    }

    // Dann beim eventuell vorhandenen parent versuchen
    return _pParentPool ? _pParentPool->GetSlot( nId ) : 0;
}

//--------------------------------------------------------------------

// skips to the next group

String SfxSlotPool::SeekGroup( USHORT nNo )
{
    DBG_MEMTEST();
    DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );

    // if the group exists, use it
    if ( _pGroups && nNo < _pGroups->Count() )
    {
        _nCurGroup = nNo;
        if ( _pParentPool )
        {
            // Meistens stimmt die Reihenfolge der Ids "uberein
            USHORT nParentCount = _pParentPool->_pGroups->Count();
            if ( nNo < nParentCount && (*_pGroups)[nNo] == (*_pParentPool->_pGroups)[nNo] )
                _pParentPool->_nCurGroup = nNo;
            else
            {
                // Ansonsten mu\s gesucht werden
                // Wenn die Gruppe im parent pool nicht gefunden wird, wird
                // _nCurGroup au\serhalb des g"ultigen Bereiches gesetzt
                USHORT i;
                for ( i=1; i<nParentCount; i++ )
                    if ( (*_pGroups)[nNo] == (*_pParentPool->_pGroups)[i] )
                        break;
                _pParentPool->_nCurGroup = i;
            }
        }

        SfxResId aResId( (*_pGroups)[_nCurGroup] );
        aResId.SetRT(RSC_STRING);
        if ( !aResId.GetResMgr()->IsAvailable(aResId) )
        {
            DBG_ERROR( "GroupId-Name nicht im SFX definiert!" );
            return String();
        }

        return String( aResId );
    }

    return String();
}

//--------------------------------------------------------------------

USHORT SfxSlotPool::GetGroupCount()
{
    return _pGroups->Count();
}

//--------------------------------------------------------------------

// internal search loop

const SfxSlot* SfxSlotPool::SeekSlot( USHORT nStartInterface )
{
    DBG_MEMTEST();
    DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );

    // Die Numerierung der interfaces startet beim parent pool
    USHORT nFirstInterface = _pParentPool ? _pParentPool->_pInterfaces->Count() : 0;

    // sind wir am Ende des Parent-Pools angekommen?
    if ( nStartInterface < nFirstInterface &&
         _pParentPool->_nCurGroup >= _pParentPool->_pGroups->Count() )
        nStartInterface = nFirstInterface;

    // liegt das Interface noch im Parent-Pool?
    if ( nStartInterface < nFirstInterface )
    {
        DBG_ASSERT( _pParentPool, "Kein parent pool!" );
        _nCurInterface = nStartInterface;
        return _pParentPool->SeekSlot( nStartInterface );
    }

    // find the first func-def with the current group id
    USHORT nCount = _pInterfaces->Count() + nFirstInterface;
    for ( _nCurInterface = nStartInterface;
            _nCurInterface < nCount;
          ++_nCurInterface )
    {
        SfxInterface* pInterface = (*_pInterfaces)[_nCurInterface-nFirstInterface];
        for ( _nCurMsg = 0;
              _nCurMsg < pInterface->Count();
              ++_nCurMsg )
        {
            const SfxSlot* pMsg = (*pInterface)[_nCurMsg];
            if ( pMsg->GetGroupId() == _pGroups->GetObject(_nCurGroup) )
                return pMsg;
        }
    }

    return 0;
}

//--------------------------------------------------------------------

// skips to the next func in the current group

const SfxSlot* SfxSlotPool::NextSlot()
{
    DBG_MEMTEST();
    DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );

    // Die Numerierung der interfaces startet beim parent pool
    USHORT nFirstInterface = _pParentPool ? _pParentPool->_pInterfaces->Count() : 0;

    if ( _nCurInterface < nFirstInterface && _nCurGroup >= _pParentPool->_pGroups->Count() )
        _nCurInterface = nFirstInterface;

    if ( _nCurInterface < nFirstInterface )
    {
        DBG_ASSERT( _pParentPool, "Kein parent pool!" );
        const SfxSlot *pSlot = _pParentPool->NextSlot();
        _nCurInterface = _pParentPool->_nCurInterface;
        if ( pSlot )
            return pSlot;
        if ( _nCurInterface == nFirstInterface )
            // parent pool ist fertig
            return SeekSlot( nFirstInterface );
    }

    USHORT nInterface = _nCurInterface - nFirstInterface;
    // possibly we are already at the end
    if ( nInterface >= _pInterfaces->Count() )
        return 0;

    // look for further matching func-defs within the same Interface
    SfxInterface* pInterface = (*_pInterfaces)[nInterface];
    while ( ++_nCurMsg < pInterface->Count() )
    {
        SfxSlot* pMsg = (*pInterface)[_nCurMsg];
        if ( pMsg->GetGroupId() == _pGroups->GetObject(_nCurGroup) )
            return pMsg;
    }

    return SeekSlot(++_nCurInterface );
}

//--------------------------------------------------------------------

// SlotName erfragen, gfs. mit HilfeText

//--------------------------------------------------------------------

SfxInterface* SfxSlotPool::FirstInterface()
{
    _nCurInterface = 0;
    if ( !_pInterfaces || !_pInterfaces->Count() )
        return 0;
    return _pParentPool ? _pParentPool->FirstInterface() : (*_pInterfaces)[0];
}

//--------------------------------------------------------------------

SfxInterface* SfxSlotPool::NextInterface()
{
    _nCurInterface++;
    USHORT nFirstInterface = _pParentPool ? _pParentPool->_pInterfaces->Count() : 0;
    if ( _nCurInterface < nFirstInterface )
        return (*_pParentPool->_pInterfaces)[_nCurInterface];
    USHORT nInterface = _nCurInterface - nFirstInterface;
    return nInterface < _pInterfaces->Count() ? (*_pInterfaces)[nInterface] : 0;
}

const SfxSlot* SfxSlotPool::GetUnoSlot( const String& rName )
{
    const SfxSlot *pSlot = NULL;
    for ( USHORT nInterface=0; nInterface<_pInterfaces->Count(); nInterface++ )
    {
        pSlot = (*_pInterfaces)[nInterface]->GetSlot( rName );
        if ( pSlot )
            break;
    }

    if ( !pSlot && _pParentPool )
        pSlot = _pParentPool->GetUnoSlot( rName );

    return pSlot;
}

SfxSlotPool& SfxSlotPool::GetSlotPool( SfxViewFrame *pFrame )
{
    SfxModule *pMod = SfxModule::GetActiveModule( pFrame );
    if ( pMod && pMod->GetSlotPool() )
        return *pMod->GetSlotPool();
    else
        return *SFX_APP()->Get_Impl()->pSlotPool;
}

<commit_msg>INTEGRATION: CWS changefileheader (1.12.216); FILE MERGED 2008/04/01 15:38:59 thb 1.12.216.2: #i85898# Stripping all external header guards 2008/03/31 13:38:11 rt 1.12.216.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: msgpool.cxx,v $
 * $Revision: 1.13 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"
#include <tools/stream.hxx>
#include <rsc/rscsfx.hxx>
#ifndef GCC
#endif

// wg. pSlotPool
#include "appdata.hxx"
#include <sfx2/msgpool.hxx>
#include <sfx2/minarray.hxx>
#include <sfx2/msg.hxx>
#include <sfx2/app.hxx>
#include <sfx2/objface.hxx>
#include "sfxtypes.hxx"
#include <sfx2/macrconf.hxx>
#include "sfxresid.hxx"
#include "arrdecl.hxx"
#include <sfx2/module.hxx>

#include <sfx2/sfx.hrc>

//====================================================================

struct SfxSIDRegistration_Impl
{
    String          _aGroup;
    String          _aName;
    USHORT          _nSID;
};

struct SfxSlotType_Impl
{
    USHORT  nId;
    TypeId  nType;

    SfxSlotType_Impl( USHORT nTheId, TypeId nTheType ):
        nId(nTheId), nType(nTheType)
    {}
};

DECL_2BYTEARRAY(SfxSlotGroupArr_Impl, USHORT, 6, 4)
DECL_PTRARRAY(SfxInterfaceArr_Impl, SfxInterface*, 6, 3)
DECL_PTRARRAY(SfxSlotTypeArr_Impl, SfxSlotType_Impl*, 8, 8)

//====================================================================

SfxSlotPool::SfxSlotPool( SfxSlotPool *pParent, ResMgr* pResManager )
 : _pGroups(0)
 , _pTypes(0)
 , _pParentPool( pParent )
 , _pResMgr( pResManager )
 , _pInterfaces(0)
 , _nCurGroup(0)
 , _nCurInterface(0)
 , _nCurMsg(0)
 , _pUnoSlots( 0 )
{
    if ( !_pResMgr )
        _pResMgr = SfxApplication::GetOrCreate()->GetOffResManager_Impl();
}

//====================================================================

SfxSlotPool::~SfxSlotPool()
{
    _pParentPool = 0;
    for ( SfxInterface *pIF = FirstInterface(); pIF; pIF = FirstInterface() )
        delete pIF;
    delete _pInterfaces;
    delete _pGroups;
    if ( _pTypes )
    {
        for ( USHORT n =_pTypes->Count(); n--; )
            delete _pTypes->GetObject(n);
        delete _pTypes;
    }
}

//====================================================================

// registers the availability of the Interface of functions

void SfxSlotPool::RegisterInterface( SfxInterface& rInterface )
{
    DBG_MEMTEST();

    // add to the list of SfxObjectInterface instances
    if ( _pInterfaces == 0 )
        _pInterfaces = new SfxInterfaceArr_Impl;
    _pInterfaces->Append(&rInterface);

    // bei einem (einzelnen) Null-Slot abbrechen (aus syntaktischen Gr"unden
    // enthalten interfaces immer mindestens einen Slot)
    if ( rInterface.Count() == 1 && !rInterface[0]->nSlotId )
        return;

    // possibly add Interface-id and group-ids of funcs to the list of groups
    if ( !_pGroups )
    {
        _pGroups = new SfxSlotGroupArr_Impl;

        if ( _pParentPool )
        {
            // Die Groups im parent Slotpool sind auch hier bekannt
            SfxSlotGroupArr_Impl& rGroups = *_pParentPool->_pGroups;
            for ( USHORT n=0; n<rGroups.Count(); n++ )
                _pGroups->Append( rGroups[n] );
        }
    }

    if ( !_pTypes )
        _pTypes = new SfxSlotTypeArr_Impl;
    for ( USHORT nFunc = 0; nFunc < rInterface.Count(); ++nFunc )
    {
        SfxSlot *pDef = rInterface[nFunc];
        if ( pDef->GetGroupId() && /* pDef->GetGroupId() != GID_INTERN && */
             !_pGroups->Contains(pDef->GetGroupId()) )
        {
            if (pDef->GetGroupId() == GID_INTERN)
                _pGroups->Insert(0, pDef->GetGroupId());
            else
                _pGroups->Append(pDef->GetGroupId());
        }
#if 0
        const TypeId &rTypeId = pDef->GetType()->Type();
        if ( /*rTypeId != TYPE(SfxVoidItem) &&*/ rTypeId != 0 )
        {
            USHORT nPos;
            for ( nPos = 0; nPos < _pTypes->Count(); ++nPos )
            {
                if ( _pTypes->GetObject(nPos)->nId == pDef->GetSlotId() )
                {
                    DBG_ASSERT( rTypeId == _pTypes->GetObject(nPos)->nType,
                                "same slot id with unequal item types" );
                }
                else if ( _pTypes->GetObject(nPos)->nId > pDef->GetSlotId() )
                    break;
            }
            if ( nPos >= _pTypes->Count() ||
                 _pTypes->GetObject(nPos)->nId > pDef->GetSlotId() )
                _pTypes->Append( new SfxSlotType_Impl( pDef->GetSlotId(), rTypeId ) );
        }
#endif
    }
}

//====================================================================

TypeId SfxSlotPool::GetSlotType( USHORT nId ) const
{
    const SfxSlot* pSlot = (const_cast <SfxSlotPool*> (this))->GetSlot( nId );
    return pSlot ? pSlot->GetType()->Type() : 0;
/*
    for ( USHORT nPos = 0; nPos < _pTypes->Count(); ++nPos )
    {
        if ( _pTypes->GetObject(nPos)->nId == nId )
            return _pTypes->GetObject(nPos)->nType;
    }
    return _pParentPool ? _pParentPool->GetSlotType( nId ) : 0;
 */
}

//====================================================================

// unregisters the availability of the Interface of functions

void SfxSlotPool::ReleaseInterface( SfxInterface& rInterface )
{
    DBG_MEMTEST();
    DBG_ASSERT( _pInterfaces, "releasing SfxInterface, but there are none" );
    // remove from the list of SfxInterface instances
    _pInterfaces->Remove(&rInterface);
}

//--------------------------------------------------------------------

// get the first SfxMessage for a special Id (e.g. for getting check-mode)

const SfxSlot* SfxSlotPool::GetSlot( USHORT nId )
{
    DBG_MEMTEST();
    DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );

    // Zun"achst die eigenen Interfaces absuchen
    for ( USHORT nInterf = 0; nInterf < _pInterfaces->Count(); ++nInterf )
    {
        const SfxSlot *pDef = _pInterfaces->GetObject(nInterf)->GetSlot(nId);
        if ( pDef )
            return pDef;
    }

    // Dann beim eventuell vorhandenen parent versuchen
    return _pParentPool ? _pParentPool->GetSlot( nId ) : 0;
}

//--------------------------------------------------------------------

// skips to the next group

String SfxSlotPool::SeekGroup( USHORT nNo )
{
    DBG_MEMTEST();
    DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );

    // if the group exists, use it
    if ( _pGroups && nNo < _pGroups->Count() )
    {
        _nCurGroup = nNo;
        if ( _pParentPool )
        {
            // Meistens stimmt die Reihenfolge der Ids "uberein
            USHORT nParentCount = _pParentPool->_pGroups->Count();
            if ( nNo < nParentCount && (*_pGroups)[nNo] == (*_pParentPool->_pGroups)[nNo] )
                _pParentPool->_nCurGroup = nNo;
            else
            {
                // Ansonsten mu\s gesucht werden
                // Wenn die Gruppe im parent pool nicht gefunden wird, wird
                // _nCurGroup au\serhalb des g"ultigen Bereiches gesetzt
                USHORT i;
                for ( i=1; i<nParentCount; i++ )
                    if ( (*_pGroups)[nNo] == (*_pParentPool->_pGroups)[i] )
                        break;
                _pParentPool->_nCurGroup = i;
            }
        }

        SfxResId aResId( (*_pGroups)[_nCurGroup] );
        aResId.SetRT(RSC_STRING);
        if ( !aResId.GetResMgr()->IsAvailable(aResId) )
        {
            DBG_ERROR( "GroupId-Name nicht im SFX definiert!" );
            return String();
        }

        return String( aResId );
    }

    return String();
}

//--------------------------------------------------------------------

USHORT SfxSlotPool::GetGroupCount()
{
    return _pGroups->Count();
}

//--------------------------------------------------------------------

// internal search loop

const SfxSlot* SfxSlotPool::SeekSlot( USHORT nStartInterface )
{
    DBG_MEMTEST();
    DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );

    // Die Numerierung der interfaces startet beim parent pool
    USHORT nFirstInterface = _pParentPool ? _pParentPool->_pInterfaces->Count() : 0;

    // sind wir am Ende des Parent-Pools angekommen?
    if ( nStartInterface < nFirstInterface &&
         _pParentPool->_nCurGroup >= _pParentPool->_pGroups->Count() )
        nStartInterface = nFirstInterface;

    // liegt das Interface noch im Parent-Pool?
    if ( nStartInterface < nFirstInterface )
    {
        DBG_ASSERT( _pParentPool, "Kein parent pool!" );
        _nCurInterface = nStartInterface;
        return _pParentPool->SeekSlot( nStartInterface );
    }

    // find the first func-def with the current group id
    USHORT nCount = _pInterfaces->Count() + nFirstInterface;
    for ( _nCurInterface = nStartInterface;
            _nCurInterface < nCount;
          ++_nCurInterface )
    {
        SfxInterface* pInterface = (*_pInterfaces)[_nCurInterface-nFirstInterface];
        for ( _nCurMsg = 0;
              _nCurMsg < pInterface->Count();
              ++_nCurMsg )
        {
            const SfxSlot* pMsg = (*pInterface)[_nCurMsg];
            if ( pMsg->GetGroupId() == _pGroups->GetObject(_nCurGroup) )
                return pMsg;
        }
    }

    return 0;
}

//--------------------------------------------------------------------

// skips to the next func in the current group

const SfxSlot* SfxSlotPool::NextSlot()
{
    DBG_MEMTEST();
    DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );

    // Die Numerierung der interfaces startet beim parent pool
    USHORT nFirstInterface = _pParentPool ? _pParentPool->_pInterfaces->Count() : 0;

    if ( _nCurInterface < nFirstInterface && _nCurGroup >= _pParentPool->_pGroups->Count() )
        _nCurInterface = nFirstInterface;

    if ( _nCurInterface < nFirstInterface )
    {
        DBG_ASSERT( _pParentPool, "Kein parent pool!" );
        const SfxSlot *pSlot = _pParentPool->NextSlot();
        _nCurInterface = _pParentPool->_nCurInterface;
        if ( pSlot )
            return pSlot;
        if ( _nCurInterface == nFirstInterface )
            // parent pool ist fertig
            return SeekSlot( nFirstInterface );
    }

    USHORT nInterface = _nCurInterface - nFirstInterface;
    // possibly we are already at the end
    if ( nInterface >= _pInterfaces->Count() )
        return 0;

    // look for further matching func-defs within the same Interface
    SfxInterface* pInterface = (*_pInterfaces)[nInterface];
    while ( ++_nCurMsg < pInterface->Count() )
    {
        SfxSlot* pMsg = (*pInterface)[_nCurMsg];
        if ( pMsg->GetGroupId() == _pGroups->GetObject(_nCurGroup) )
            return pMsg;
    }

    return SeekSlot(++_nCurInterface );
}

//--------------------------------------------------------------------

// SlotName erfragen, gfs. mit HilfeText

//--------------------------------------------------------------------

SfxInterface* SfxSlotPool::FirstInterface()
{
    _nCurInterface = 0;
    if ( !_pInterfaces || !_pInterfaces->Count() )
        return 0;
    return _pParentPool ? _pParentPool->FirstInterface() : (*_pInterfaces)[0];
}

//--------------------------------------------------------------------

SfxInterface* SfxSlotPool::NextInterface()
{
    _nCurInterface++;
    USHORT nFirstInterface = _pParentPool ? _pParentPool->_pInterfaces->Count() : 0;
    if ( _nCurInterface < nFirstInterface )
        return (*_pParentPool->_pInterfaces)[_nCurInterface];
    USHORT nInterface = _nCurInterface - nFirstInterface;
    return nInterface < _pInterfaces->Count() ? (*_pInterfaces)[nInterface] : 0;
}

const SfxSlot* SfxSlotPool::GetUnoSlot( const String& rName )
{
    const SfxSlot *pSlot = NULL;
    for ( USHORT nInterface=0; nInterface<_pInterfaces->Count(); nInterface++ )
    {
        pSlot = (*_pInterfaces)[nInterface]->GetSlot( rName );
        if ( pSlot )
            break;
    }

    if ( !pSlot && _pParentPool )
        pSlot = _pParentPool->GetUnoSlot( rName );

    return pSlot;
}

SfxSlotPool& SfxSlotPool::GetSlotPool( SfxViewFrame *pFrame )
{
    SfxModule *pMod = SfxModule::GetActiveModule( pFrame );
    if ( pMod && pMod->GetSlotPool() )
        return *pMod->GetSlotPool();
    else
        return *SFX_APP()->Get_Impl()->pSlotPool;
}

<|endoftext|>