summaryrefslogblamecommitdiff
path: root/tnet_io/KaldiLib/MlfStream.cc
blob: a2f647859846d41f2530ed8e101e1810bf06f961 (plain) (tree)











































































































































































































































































                                                                                                                
#include "MlfStream.h"
#include "Common.h"
#include "Error.h"


namespace TNet
{
  //******************************************************************************
  LabelContainer::
  ~LabelContainer()
  {
    while (!this->mLabelList.empty())
    {
      delete this->mLabelList.back();
      this->mLabelList.pop_back();
    }
  }

  //******************************************************************************
  size_t
  LabelContainer::
  DirDepth(const std::string & rPath)
  {
    size_t depth     = 0;
    size_t length    = rPath.length();
    const char * s   = rPath.c_str();

    for (size_t i = 0; i < length; i++)
    {
      if (*s == '/' || *s == '\\')
      {
        depth++;
      }
      s++;
    }
    return depth;
  }


  //******************************************************************************
  void
  LabelContainer::
  Insert(const std::string &  rLabel,
         std::streampos  Pos)
  {
    LabelRecord     ls;
    size_t          depth;
    LabelRecord     tmp_ls;

    // we need to compute the depth of the label path if
    // wildcard is used
    // do we have a wildcard???
    if (rLabel[0] == '*')
    {
      depth = this->DirDepth(rLabel);
    }
    else
    {
      depth = MAX_LABEL_DEPTH;
    }

    // perhaps we want to store the depth of the path in the label for the wildcards
    // to work
    this->mDepths.insert(depth);

    // store the values
    ls.mStreamPos       = Pos;
    ls.miLabelListLimit = mLabelList.end();


    if (mLabelList.begin() != mLabelList.end()) {
      ls.miLabelListLimit--;
    }

    // if no wildcard chars, then we try to store in hash, otherwise store in 
    // list
    if (rLabel.find_first_of("*?%",1) == rLabel.npos)
    {
      if (!Find(rLabel, tmp_ls))
      {
        // look in the
        this->mLabelMap[rLabel] = ls;
      }
      else {
        ;
        //Warning("More general definition found when inserting " + rLabel + " ... label: " + MatchedPattern());
      }
    }
    else
    {
      this->mLabelList.push_back(new std::pair<std::string,LabelRecord>(rLabel, ls));
    }
  }


  //******************************************************************************
  bool
  LabelContainer::
  FindInHash(const std::string & rLabel, LabelRecord & rLS)
  {
    bool found = false;

    std::string str;

    // current depth within the str
    DepthType  current_depth    = MAX_LABEL_DEPTH;

    // current search position within the str
    size_t     prev             = rLabel.size() + 1;

    // we will walk through the set depts bacwards so we begin at the end and move
    // to the front...
    std::set<DepthType>::reverse_iterator ri    (this->mDepths.end());
    std::set<DepthType>::reverse_iterator rlast (this->mDepths.begin());
    LabelHashType::iterator               lab;

    // we perform the search until we run to the end of the set or we find something
    while ((!found) && (ri != rlast))
    {
      // we don't need to do anything with the string if the depth is set to
      // max label depth since it contains no *
      if (*ri == MAX_LABEL_DEPTH)
      {
        found = ((lab=this->mLabelMap.find(rLabel)) != this->mLabelMap.end());
        if (found) str = rLabel;
      }
      // we will crop the string and put * in the begining and try to search
      else
      {
        // we know that we walk backwards in the depths, so we need to first find
        // the last / and
        if (current_depth == MAX_LABEL_DEPTH)
        {
          if (*ri > 0)
          {
            // we find the ri-th / from back
            for (DepthType i=1; (i <= *ri) && (prev != rLabel.npos); i++)
            {
              prev = rLabel.find_last_of("/\\", prev-1);
            }
          }
          else
          {
            prev = 0;
          }

          // check if finding succeeded (prev == str.npos => failure, see STL)
          if (prev != rLabel.npos)
          {
            // construct the new string beign sought for
            str.assign(rLabel, prev, rLabel.size());
            str = '*' + str;

            // now we try to find
            found = ((lab=this->mLabelMap.find(str)) != this->mLabelMap.end());

            // say, that current depth is *ri
            current_depth = *ri;
          }
          else
          {
            prev = rLabel.size() + 1;
          }
        }     // if (current_depth == MAX_LABEL_DEPTH)
        else
        {
          // now we know at which / we are from the back, so we search forward now
          // and we need to reach the ri-th /
          while (current_depth > *ri)
          {
            // we try to find next /
            if ((prev = rLabel.find_first_of("/\\", prev+1)) != rLabel.npos)
              current_depth--;
            else
              return false;
          }

          // construct the new string beign sought for
          str.assign(rLabel, prev, rLabel.size());
          str = '*' + str;

          // now we try to find
          found = ((lab=this->mLabelMap.find(str)) != this->mLabelMap.end());
        }
      }

      // move one element further (jump to next observed depth)
      ri++;
    } // while (run)

    // some debug info
    if (found)
    {
      rLS                   = lab->second;
      this->mMatchedPattern = str;
    }

    return found;
  }


  //******************************************************************************
  bool
  LabelContainer::
  FindInList(const std::string & rLabel, LabelRecord & rLS, bool limitSearch)
  {

    bool                      found = false;
    std::string                    str;
    LabelListType::iterator   lab   = mLabelList.begin();
    LabelListType::iterator   limit;

    if (limitSearch && (rLS.miLabelListLimit != mLabelList.end()))
    {
      limit = rLS.miLabelListLimit;
      limit++;
    }
    else
    {
      limit = this->mLabelList.end();
    }

    // we perform sequential search until we run to the end of the list or we find
    // something
    while ((!found) && (lab != limit))
    {
      if (ProcessMask(rLabel, (*lab)->first, str))
      {
        found = true;
      }
      else
      {
        lab++;
      }
    } // while (run)

    // some debug info
    if (found)
    {
      rLS                       = (*lab)->second;
      this->mMatchedPattern     = (*lab)->first;
      this->mMatchedPatternMask = str;
    }
    return found;
  }


  //******************************************************************************
  bool
  LabelContainer::
  Find(const std::string & rLabel, LabelRecord & rLS)
  {
    // try to find the label in the Hash
    if (FindInHash(rLabel, rLS))
    {
      // we look in the list, but we limit the search.
      FindInList(rLabel, rLS, true);
      return true;
    } //if (this->mLabelContainer.FindInHash(rLabel, label_stream))
    else
    {
      // we didn't find it in the hash so we look in the list
      return FindInList(rLabel, rLS);
    }
  }

} // namespace TNet