<commit_before>/*
 *            Copyright 2009-2016 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      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 <votca/xtp/esp2multipole.h>

namespace votca { namespace xtp {

void Esp2multipole::Initialize(Property* options) {
    string key = "options." + Identify();
    _use_ecp=false;

    _use_mulliken=false;
    _use_CHELPG=false;
    _use_GDMA=false;
    _use_CHELPG_SVD=false;

    _state     = options->get(key + ".state").as<string> ();
    _state_no     = options->get(key + ".statenumber").as<int> ();
    _spin     = options->get(key + ".spin").as<string> ();
    if ( options->exists(key+".ecp")) {
       _use_ecp=options->get(key + ".ecp").as<bool> ();
    }
    if ( options->exists(key+".method")) {
         _method = options->get(key + ".method").as<string> ();
         if (_method=="Mulliken")_use_mulliken=true;
         else if(_method=="mulliken")_use_mulliken=true;
         else if(_method=="CHELPG")_use_CHELPG=true;
         else if(_method=="GDMA") throw std::runtime_error("GDMA not implemented yet");
         else if(_method=="CHELPG_SVD") throw std::runtime_error("CHELPG_SVD not implemented yet");
         else  throw std::runtime_error("Method not recognized. Only Mulliken and CHELPG implemented");
         }
    else _use_CHELPG=true;
    if (!_use_mulliken){
         _integrationmethod     = options->get(key + ".integrationmethod").as<string> ();
    }

    if (!(_integrationmethod=="numeric" || _integrationmethod=="analytic")){
        std::runtime_error("Method not recognized. Only numeric and analytic available");
    }
    if ( options->exists(key+".gridsize")) {
         _gridsize = options->get(key+".gridsize").as<string>();
         }
    else _gridsize="medium";
    if ( options->exists(key+".openmp")) {
         _openmp_threads = options->get(key+".openmp").as<int>();
         }
    else _openmp_threads=0;
    if ( options->exists(key+".svd")) {
         _do_svd = options->get(key+".svd.do_svd").as<bool>();
         _conditionnumber = options->get(key+".svd.conditionnumber").as<double>();
         }

    // get the path to the shared folders with xml files
    char *votca_share = getenv("VOTCASHARE");
    if(votca_share == NULL) throw std::runtime_error("VOTCASHARE not set, cannot open help files.");

}
string  Esp2multipole::GetIdentifier(){
    string identifier;
    if(_state=="transition" && _spin=="singlet" ){
        identifier=(boost::format("n2s%i") % _state_no).str();
    }
    else if(_state=="transition" && _spin=="triplet" ){
        identifier=(boost::format("n2t%i") % _state_no).str();
    }
    else if(_state=="excited" && _spin=="triplet" ){
        identifier=(boost::format("t%i") % _state_no).str();
    }
    else if(_state=="excited" && _spin=="singlet" ){
        identifier=(boost::format("s%i") % _state_no).str();
    }
    else if(_state=="excited" && _spin=="singlet" ){
        identifier=(boost::format("s%i") % _state_no).str();
    }
    else if(_state=="ground"  ){
        identifier="n";
    }
    else{
        throw std::runtime_error("Esp2multipole::GetIdentifier did not recognize config");
    }
    return identifier;
}

void Esp2multipole::WritetoFile(Orbitals& _orbitals,string _output_file, string identifier){
    _use_mps=false;
    _use_pdb=false;
    string data_format  = boost::filesystem::extension(_output_file);
    if (data_format==".mps")_use_mps=true;
    else if(data_format==".pdb")_use_pdb=true;
    else  throw std::runtime_error("Outputfile format not recognized. Export only to .pdb and .mps");
     string tag="TOOL:"+Identify()+"_"+_state+"_"+_spin+boost::lexical_cast<string>(_state_no);
    if(_use_mps){
        QMMInterface Converter;
        PolarSeg* result=Converter.Convert(_orbitals.QMAtoms());

        result->WriteMPS(_output_file,tag);
        }
    else if(_use_pdb){
        FILE *out;
        out = fopen(_output_file.c_str(), "w");
       _orbitals.WritePDB(out, tag);
    }
}

void Esp2multipole::Extractingcharges( Orbitals& _orbitals ){
    int threads=1;
#ifdef _OPENMP
            if ( _openmp_threads > 0 ) omp_set_num_threads(_openmp_threads);
            threads=omp_get_max_threads();
#endif
   LOG(logDEBUG, _log) << "===== Running on "<< threads << " threads ===== " << flush;

        vector< QMAtom* > Atomlist =_orbitals.QMAtoms();
        ub::matrix<double> DMAT_tot;
        BasisSet bs;
        bs.LoadBasisSet(_orbitals.getDFTbasis());
        AOBasis basis;
        basis.AOBasisFill(&bs, Atomlist );
        basis.ReorderMOs(_orbitals.MOCoefficients(), _orbitals.getQMpackage(), "votca" );
        bool _do_transition=false;
        if(_state=="transition"){
            _do_transition=true;
            if (_spin=="singlet"){
                DMAT_tot=_orbitals.TransitionDensityMatrix(_orbitals.MOCoefficients() , _orbitals.BSESingletCoefficients(), _state_no-1);
            }
            else if (_spin=="triplet"){
                DMAT_tot=_orbitals.TransitionDensityMatrix(_orbitals.MOCoefficients() , _orbitals.BSETripletCoefficients(), _state_no-1);
            }
            else throw std::runtime_error("Spin entry not recognized");
        }
        else if (_state=="ground" || _state=="excited"){

            ub::matrix<double> &DMATGS=_orbitals.DensityMatrixGroundState(_orbitals.MOCoefficients());
            DMAT_tot=DMATGS;
            if ( _state_no > 0 && _state=="excited"){
                std::vector<ub::matrix<double> > DMAT;
                if (_spin=="singlet"){
                    DMAT = _orbitals.DensityMatrixExcitedState( _orbitals.MOCoefficients() , _orbitals.BSESingletCoefficients(), _state_no-1);

                }
                else if (_spin=="triplet"){
                    DMAT = _orbitals.DensityMatrixExcitedState( _orbitals.MOCoefficients() , _orbitals.BSETripletCoefficients(), _state_no-1);
                }
                else throw std::runtime_error("Spin entry not recognized");
                DMAT_tot=DMAT_tot-DMAT[0]+DMAT[1];
            }
	   // Ground state + hole_contribution + electron contribution
	}
        else throw std::runtime_error("State entry not recognized");

        if (_use_mulliken) {
            Mulliken mulliken;
            mulliken.EvaluateMulliken(Atomlist, DMAT_tot, basis, bs, _do_transition);

        }
        else if (_use_CHELPG){
            Espfit esp=Espfit(&_log);
            esp.setUseECPs(_use_ecp);
            if(_do_svd){
                esp.setUseSVD(_do_svd,_conditionnumber);
            }
            if (_integrationmethod=="numeric")  {
                esp.Fit2Density(Atomlist, DMAT_tot, basis,bs,_gridsize);
            }
            else if (_integrationmethod=="analytic")  esp.Fit2Density_analytic(Atomlist,DMAT_tot,basis);
        }
}

}}
<commit_msg>added format header to esp2multipole<commit_after>/*
 *            Copyright 2009-2016 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      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 <votca/xtp/esp2multipole.h>
#include <boost/format.hpp>

namespace votca { namespace xtp {

void Esp2multipole::Initialize(Property* options) {
    string key = "options." + Identify();
    _use_ecp=false;

    _use_mulliken=false;
    _use_CHELPG=false;
    _use_GDMA=false;
    _use_CHELPG_SVD=false;

    _state     = options->get(key + ".state").as<string> ();
    _state_no     = options->get(key + ".statenumber").as<int> ();
    _spin     = options->get(key + ".spin").as<string> ();
    if ( options->exists(key+".ecp")) {
       _use_ecp=options->get(key + ".ecp").as<bool> ();
    }
    if ( options->exists(key+".method")) {
         _method = options->get(key + ".method").as<string> ();
         if (_method=="Mulliken")_use_mulliken=true;
         else if(_method=="mulliken")_use_mulliken=true;
         else if(_method=="CHELPG")_use_CHELPG=true;
         else if(_method=="GDMA") throw std::runtime_error("GDMA not implemented yet");
         else if(_method=="CHELPG_SVD") throw std::runtime_error("CHELPG_SVD not implemented yet");
         else  throw std::runtime_error("Method not recognized. Only Mulliken and CHELPG implemented");
         }
    else _use_CHELPG=true;
    if (!_use_mulliken){
         _integrationmethod     = options->get(key + ".integrationmethod").as<string> ();
    }

    if (!(_integrationmethod=="numeric" || _integrationmethod=="analytic")){
        std::runtime_error("Method not recognized. Only numeric and analytic available");
    }
    if ( options->exists(key+".gridsize")) {
         _gridsize = options->get(key+".gridsize").as<string>();
         }
    else _gridsize="medium";
    if ( options->exists(key+".openmp")) {
         _openmp_threads = options->get(key+".openmp").as<int>();
         }
    else _openmp_threads=0;
    if ( options->exists(key+".svd")) {
         _do_svd = options->get(key+".svd.do_svd").as<bool>();
         _conditionnumber = options->get(key+".svd.conditionnumber").as<double>();
         }

    // get the path to the shared folders with xml files
    char *votca_share = getenv("VOTCASHARE");
    if(votca_share == NULL) throw std::runtime_error("VOTCASHARE not set, cannot open help files.");

}
string  Esp2multipole::GetIdentifier(){
    string identifier;
    if(_state=="transition" && _spin=="singlet" ){
        identifier=(boost::format("n2s%i") % _state_no).str();
    }
    else if(_state=="transition" && _spin=="triplet" ){
        identifier=(boost::format("n2t%i") % _state_no).str();
    }
    else if(_state=="excited" && _spin=="triplet" ){
        identifier=(boost::format("t%i") % _state_no).str();
    }
    else if(_state=="excited" && _spin=="singlet" ){
        identifier=(boost::format("s%i") % _state_no).str();
    }
    else if(_state=="excited" && _spin=="singlet" ){
        identifier=(boost::format("s%i") % _state_no).str();
    }
    else if(_state=="ground"  ){
        identifier="n";
    }
    else{
        throw std::runtime_error("Esp2multipole::GetIdentifier did not recognize config");
    }
    return identifier;
}

void Esp2multipole::WritetoFile(Orbitals& _orbitals,string _output_file, string identifier){
    _use_mps=false;
    _use_pdb=false;
    string data_format  = boost::filesystem::extension(_output_file);
    if (data_format==".mps")_use_mps=true;
    else if(data_format==".pdb")_use_pdb=true;
    else  throw std::runtime_error("Outputfile format not recognized. Export only to .pdb and .mps");
     string tag="TOOL:"+Identify()+"_"+_state+"_"+_spin+boost::lexical_cast<string>(_state_no);
    if(_use_mps){
        QMMInterface Converter;
        PolarSeg* result=Converter.Convert(_orbitals.QMAtoms());

        result->WriteMPS(_output_file,tag);
        }
    else if(_use_pdb){
        FILE *out;
        out = fopen(_output_file.c_str(), "w");
       _orbitals.WritePDB(out, tag);
    }
}

void Esp2multipole::Extractingcharges( Orbitals& _orbitals ){
    int threads=1;
#ifdef _OPENMP
            if ( _openmp_threads > 0 ) omp_set_num_threads(_openmp_threads);
            threads=omp_get_max_threads();
#endif
   LOG(logDEBUG, _log) << "===== Running on "<< threads << " threads ===== " << flush;

        vector< QMAtom* > Atomlist =_orbitals.QMAtoms();
        ub::matrix<double> DMAT_tot;
        BasisSet bs;
        bs.LoadBasisSet(_orbitals.getDFTbasis());
        AOBasis basis;
        basis.AOBasisFill(&bs, Atomlist );
        basis.ReorderMOs(_orbitals.MOCoefficients(), _orbitals.getQMpackage(), "votca" );
        bool _do_transition=false;
        if(_state=="transition"){
            _do_transition=true;
            if (_spin=="singlet"){
                DMAT_tot=_orbitals.TransitionDensityMatrix(_orbitals.MOCoefficients() , _orbitals.BSESingletCoefficients(), _state_no-1);
            }
            else if (_spin=="triplet"){
                DMAT_tot=_orbitals.TransitionDensityMatrix(_orbitals.MOCoefficients() , _orbitals.BSETripletCoefficients(), _state_no-1);
            }
            else throw std::runtime_error("Spin entry not recognized");
        }
        else if (_state=="ground" || _state=="excited"){

            ub::matrix<double> &DMATGS=_orbitals.DensityMatrixGroundState(_orbitals.MOCoefficients());
            DMAT_tot=DMATGS;
            if ( _state_no > 0 && _state=="excited"){
                std::vector<ub::matrix<double> > DMAT;
                if (_spin=="singlet"){
                    DMAT = _orbitals.DensityMatrixExcitedState( _orbitals.MOCoefficients() , _orbitals.BSESingletCoefficients(), _state_no-1);

                }
                else if (_spin=="triplet"){
                    DMAT = _orbitals.DensityMatrixExcitedState( _orbitals.MOCoefficients() , _orbitals.BSETripletCoefficients(), _state_no-1);
                }
                else throw std::runtime_error("Spin entry not recognized");
                DMAT_tot=DMAT_tot-DMAT[0]+DMAT[1];
            }
	   // Ground state + hole_contribution + electron contribution
	}
        else throw std::runtime_error("State entry not recognized");

        if (_use_mulliken) {
            Mulliken mulliken;
            mulliken.EvaluateMulliken(Atomlist, DMAT_tot, basis, bs, _do_transition);

        }
        else if (_use_CHELPG){
            Espfit esp=Espfit(&_log);
            esp.setUseECPs(_use_ecp);
            if(_do_svd){
                esp.setUseSVD(_do_svd,_conditionnumber);
            }
            if (_integrationmethod=="numeric")  {
                esp.Fit2Density(Atomlist, DMAT_tot, basis,bs,_gridsize);
            }
            else if (_integrationmethod=="analytic")  esp.Fit2Density_analytic(Atomlist,DMAT_tot,basis);
        }
}

}}
<|endoftext|>


<commit_before>/*
   Copyright (c) 2013 Monty Program Ab

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; version 2 of
   the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
*/

/*
  a engine that auto-creates tables with rows filled with sequential values
*/

#include <mysql_version.h>
#include <handler.h>
#include <table.h>
#include <field.h>

typedef struct st_share {
  const char *name;
  THR_LOCK lock;
  uint use_count;
  struct st_share *next;

  ulonglong from, to, step;
  bool reverse;
} SHARE;

class ha_seq: public handler
{
private:
  THR_LOCK_DATA lock;
  SHARE *seqs;
  ulonglong cur;

public:
  ha_seq(handlerton *hton, TABLE_SHARE *table_arg)
    : handler(hton, table_arg), seqs(0) { }
  ulonglong table_flags() const
  { return HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE; }

  /* open/close/locking */
  int create(const char *name, TABLE *table_arg,
             HA_CREATE_INFO *create_info) { return HA_ERR_WRONG_COMMAND; }

  int open(const char *name, int mode, uint test_if_locked);
  int close(void);
  THR_LOCK_DATA **store_lock(THD *, THR_LOCK_DATA **, enum thr_lock_type);

  /* table scan */
  int rnd_init(bool scan);
  int rnd_next(unsigned char *buf);
  void position(const uchar *record);
  int rnd_pos(uchar *buf, uchar *pos);
  int info(uint flag);

  /* indexes */
  ulong index_flags(uint inx, uint part, bool all_parts) const
  { return HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER |
           HA_READ_RANGE | HA_KEYREAD_ONLY; }
  uint max_supported_keys() const { return 1; }
  int index_read_map(uchar *buf, const uchar *key, key_part_map keypart_map,
                     enum ha_rkey_function find_flag);
  int index_next(uchar *buf);
  int index_prev(uchar *buf);
  int index_first(uchar *buf);
  int index_last(uchar *buf);
  ha_rows records_in_range(uint inx, key_range *min_key,
                                   key_range *max_key);

  double scan_time() { return nvalues(); }
  double read_time(uint index, uint ranges, ha_rows rows) { return rows; }
  double keyread_time(uint index, uint ranges, ha_rows rows) { return rows; }

private:
  void set(uchar *buf);
  ulonglong nvalues() { return (seqs->to - seqs->from)/seqs->step; }
};

THR_LOCK_DATA **ha_seq::store_lock(THD *thd, THR_LOCK_DATA **to,
                           enum thr_lock_type lock_type)
{
  if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
    lock.type= TL_WRITE_ALLOW_WRITE;
  *to ++= &lock;
  return to;
}

void ha_seq::set(unsigned char *buf)
{
  my_bitmap_map *old_map = dbug_tmp_use_all_columns(table, table->write_set);
  my_ptrdiff_t offset = (my_ptrdiff_t) (buf - table->record[0]);
  Field *field = table->field[0];
  field->move_field_offset(offset);
  field->store(cur, true);
  field->move_field_offset(-offset);
  dbug_tmp_restore_column_map(table->write_set, old_map);
}

int ha_seq::rnd_init(bool scan)
{
  cur= seqs->reverse ? seqs->to : seqs->from;
  return 0;
}

int ha_seq::rnd_next(unsigned char *buf)
{
  if (seqs->reverse)
    return index_prev(buf);
  else
    return index_next(buf);
}

void ha_seq::position(const uchar *record)
{
  *(ulonglong*)ref= cur;
}

int ha_seq::rnd_pos(uchar *buf, uchar *pos)
{
  cur= *(ulonglong*)pos;
  return rnd_next(buf);
}

int ha_seq::info(uint flag)
{
  if (flag & HA_STATUS_VARIABLE)
    stats.records = nvalues();
  return 0;
}

int ha_seq::index_read_map(uchar *buf, const uchar *key_arg,
                           key_part_map keypart_map,
                           enum ha_rkey_function find_flag)
{
  ulonglong key= uint8korr(key_arg);
  switch (find_flag) {
  case HA_READ_AFTER_KEY:
    key++;
    // fall through
  case HA_READ_KEY_OR_NEXT:
    if (key <= seqs->from)
      cur= seqs->from;
    else
    {
      cur= (key - seqs->from + seqs->step - 1) / seqs->step * seqs->step + seqs->from;
      if (cur >= seqs->to)
        return HA_ERR_KEY_NOT_FOUND;
    }
    return index_next(buf);

  case HA_READ_KEY_EXACT:
    if ((key - seqs->from) % seqs->step != 0 || key < seqs->from || key >= seqs->to)
      return HA_ERR_KEY_NOT_FOUND;
    cur= key;
    return index_next(buf);

  case HA_READ_BEFORE_KEY:
    key--;
    // fall through
  case HA_READ_PREFIX_LAST_OR_PREV:
    if (key >= seqs->to)
      cur= seqs->to;
    else
    {
      if (key < seqs->from)
        return HA_ERR_KEY_NOT_FOUND;
      cur= (key - seqs->from) / seqs->step * seqs->step + seqs->from;
    }
    return index_prev(buf);
  default: return HA_ERR_WRONG_COMMAND;
  }
}

int ha_seq::index_next(uchar *buf)
{
  if (cur == seqs->to)
    return HA_ERR_END_OF_FILE;
  set(buf);
  cur+= seqs->step;
  return 0;
}

int ha_seq::index_prev(uchar *buf)
{
  if (cur == seqs->from)
    return HA_ERR_END_OF_FILE;
  cur-= seqs->step;
  set(buf);
  return 0;
}

int ha_seq::index_first(uchar *buf)
{
  cur= seqs->from;
  return index_next(buf);
}

int ha_seq::index_last(uchar *buf)
{
  cur= seqs->to;
  return index_prev(buf);
}

ha_rows ha_seq::records_in_range(uint inx, key_range *min_key,
                                 key_range *max_key)
{
  ulonglong kmin= min_key ? uint8korr(min_key->key) : seqs->from;
  ulonglong kmax= max_key ? uint8korr(max_key->key) : seqs->to - 1;
  if (kmin >= seqs->to || kmax < seqs->from || kmin > kmax)
    return 0;
  return (kmax - seqs->from) / seqs->step -
         (kmin - seqs->from + seqs->step - 1) / seqs->step + 1;
}

int ha_seq::open(const char *name, int mode, uint test_if_locked)
{
  mysql_mutex_lock(&table->s->LOCK_ha_data);
  seqs= (SHARE*)table->s->ha_data;
  DBUG_ASSERT(my_strcasecmp(table_alias_charset, name, seqs->name) == 0);
  if (seqs->use_count++ == 0)
    thr_lock_init(&seqs->lock);
  mysql_mutex_unlock(&table->s->LOCK_ha_data);

  ref_length= sizeof(cur);
  thr_lock_data_init(&seqs->lock,&lock,NULL);
  return 0;
}

int ha_seq::close(void)
{
  mysql_mutex_lock(&table->s->LOCK_ha_data);
  if (--seqs->use_count == 0)
    thr_lock_delete(&seqs->lock);
  mysql_mutex_unlock(&table->s->LOCK_ha_data);
  return 0;
}

static handler *create_handler(handlerton *hton, TABLE_SHARE *table,
                               MEM_ROOT *mem_root)
{
  return new (mem_root) ha_seq(hton, table);
}

static bool parse_table_name(const char *name, size_t name_length,
                             ulonglong *from, ulonglong *to, ulonglong *step)
{
  uint n1= 0, n2= 0;
  *step= 1;

  // the table is discovered if its name matches the pattern of seq_1_to_10 or
  // seq_1_to_10_step_3
  sscanf(name, "seq_%llu_to_%llu%n_step_%llu%n",
         from, to, &n1, step, &n2);
  return n1 != name_length && n2 != name_length;
}

static int discover_table(handlerton *hton, THD *thd, TABLE_SHARE *share)
{
  ulonglong from, to, step;
  if (parse_table_name(share->table_name.str, share->table_name.length,
                       &from, &to, &step))
    return HA_ERR_NO_SUCH_TABLE;

  if (step == 0)
    return HA_WRONG_CREATE_OPTION;

  const char *sql="create table seq (seq bigint unsigned primary key)";
  int res= share->init_from_sql_statement_string(thd, 0, sql, strlen(sql));
  if (res)
    return res;

  bool reverse;
  if ((reverse = from > to))
  {
    if (step > from - to)
      to = from;
    else
      swap_variables(ulonglong, from, to);
    /*
      when keyread is allowed, optimizer will always prefer an index to a
      table scan for our tables, and we'll never see the range reversed.
    */
    share->keys_for_keyread.clear_all();
  }

  to= (to - from) / step * step + step + from;

  SHARE *seqs= (SHARE*)alloc_root(&share->mem_root, sizeof(*seqs));
  bzero(seqs, sizeof(*seqs));
  seqs->name = share->normalized_path.str;
  seqs->from= from;
  seqs->to= to;
  seqs->step= step;
  seqs->reverse= reverse;

  share->ha_data = seqs;
  return 0;
}

static int discover_table_existence(handlerton *hton, const char *db,
                                    const char *table_name)
{
  ulonglong from, to, step;
  return !parse_table_name(table_name, strlen(table_name), &from, &to, &step);
}

static int dummy_ret_int() { return 0; }

static int init(void *p)
{
  handlerton *hton= (handlerton *)p;
  hton->create= create_handler;
  hton->discover_table= discover_table;
  hton->discover_table_existence= discover_table_existence;
  hton->commit= hton->rollback= hton->prepare=
   (int (*)(handlerton *, THD *, bool)) &dummy_ret_int;
  hton->savepoint_set= hton->savepoint_rollback= hton->savepoint_release=
   (int  (*)(handlerton *, THD *, void *)) &dummy_ret_int;

  return 0;
}

static struct st_mysql_storage_engine descriptor =
{ MYSQL_HANDLERTON_INTERFACE_VERSION };

maria_declare_plugin(sequence)
{
  MYSQL_STORAGE_ENGINE_PLUGIN,
  &descriptor,
  "SEQUENCE",
  "Sergei Golubchik",
  "Generated tables filled with sequential values",
  PLUGIN_LICENSE_GPL,
  init,
  NULL,
  0x0100,
  NULL,
  NULL,
  "0.1",
  MariaDB_PLUGIN_MATURITY_EXPERIMENTAL
}
maria_declare_plugin_end;

<commit_msg>MDEV-4786 - merge 10.0-monty → 10.0<commit_after>/*
   Copyright (c) 2013 Monty Program Ab

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; version 2 of
   the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
*/

/*
  a engine that auto-creates tables with rows filled with sequential values
*/

#include <mysql_version.h>
#include <handler.h>
#include <table.h>
#include <field.h>

class SHARE : public Handler_share {
public:
  const char *name;
  THR_LOCK lock;

  ulonglong from, to, step;
  bool reverse;

  SHARE(const char *name_arg, ulonglong from_arg, ulonglong to_arg,
        ulonglong step_arg, bool reverse_arg):
    name(name_arg), from(from_arg), to(to_arg), step(step_arg),
    reverse(reverse_arg)
  {
    thr_lock_init(&lock);
  }
  ~SHARE()
  {
    thr_lock_delete(&lock);
  }
};

class ha_seq: public handler
{
private:
  THR_LOCK_DATA lock;
  SHARE *seqs;
  SHARE *get_share();
  ulonglong cur;

public:
  ha_seq(handlerton *hton, TABLE_SHARE *table_arg)
    : handler(hton, table_arg), seqs(0) { }
  ulonglong table_flags() const
  { return HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE; }

  /* open/close/locking */
  int create(const char *name, TABLE *table_arg,
             HA_CREATE_INFO *create_info) { return HA_ERR_WRONG_COMMAND; }

  int open(const char *name, int mode, uint test_if_locked);
  int close(void);
  THR_LOCK_DATA **store_lock(THD *, THR_LOCK_DATA **, enum thr_lock_type);

  /* table scan */
  int rnd_init(bool scan);
  int rnd_next(unsigned char *buf);
  void position(const uchar *record);
  int rnd_pos(uchar *buf, uchar *pos);
  int info(uint flag);

  /* indexes */
  ulong index_flags(uint inx, uint part, bool all_parts) const
  { return HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER |
           HA_READ_RANGE | HA_KEYREAD_ONLY; }
  uint max_supported_keys() const { return 1; }
  int index_read_map(uchar *buf, const uchar *key, key_part_map keypart_map,
                     enum ha_rkey_function find_flag);
  int index_next(uchar *buf);
  int index_prev(uchar *buf);
  int index_first(uchar *buf);
  int index_last(uchar *buf);
  ha_rows records_in_range(uint inx, key_range *min_key,
                                   key_range *max_key);

  double scan_time() { return nvalues(); }
  double read_time(uint index, uint ranges, ha_rows rows) { return rows; }
  double keyread_time(uint index, uint ranges, ha_rows rows) { return rows; }

private:
  void set(uchar *buf);
  ulonglong nvalues() { return (seqs->to - seqs->from)/seqs->step; }
};

THR_LOCK_DATA **ha_seq::store_lock(THD *thd, THR_LOCK_DATA **to,
                           enum thr_lock_type lock_type)
{
  if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
    lock.type= TL_WRITE_ALLOW_WRITE;
  *to ++= &lock;
  return to;
}

void ha_seq::set(unsigned char *buf)
{
  my_bitmap_map *old_map = dbug_tmp_use_all_columns(table, table->write_set);
  my_ptrdiff_t offset = (my_ptrdiff_t) (buf - table->record[0]);
  Field *field = table->field[0];
  field->move_field_offset(offset);
  field->store(cur, true);
  field->move_field_offset(-offset);
  dbug_tmp_restore_column_map(table->write_set, old_map);
}

int ha_seq::rnd_init(bool scan)
{
  cur= seqs->reverse ? seqs->to : seqs->from;
  return 0;
}

int ha_seq::rnd_next(unsigned char *buf)
{
  if (seqs->reverse)
    return index_prev(buf);
  else
    return index_next(buf);
}

void ha_seq::position(const uchar *record)
{
  *(ulonglong*)ref= cur;
}

int ha_seq::rnd_pos(uchar *buf, uchar *pos)
{
  cur= *(ulonglong*)pos;
  return rnd_next(buf);
}

int ha_seq::info(uint flag)
{
  if (flag & HA_STATUS_VARIABLE)
    stats.records = nvalues();
  return 0;
}

int ha_seq::index_read_map(uchar *buf, const uchar *key_arg,
                           key_part_map keypart_map,
                           enum ha_rkey_function find_flag)
{
  ulonglong key= uint8korr(key_arg);
  switch (find_flag) {
  case HA_READ_AFTER_KEY:
    key++;
    // fall through
  case HA_READ_KEY_OR_NEXT:
    if (key <= seqs->from)
      cur= seqs->from;
    else
    {
      cur= (key - seqs->from + seqs->step - 1) / seqs->step * seqs->step + seqs->from;
      if (cur >= seqs->to)
        return HA_ERR_KEY_NOT_FOUND;
    }
    return index_next(buf);

  case HA_READ_KEY_EXACT:
    if ((key - seqs->from) % seqs->step != 0 || key < seqs->from || key >= seqs->to)
      return HA_ERR_KEY_NOT_FOUND;
    cur= key;
    return index_next(buf);

  case HA_READ_BEFORE_KEY:
    key--;
    // fall through
  case HA_READ_PREFIX_LAST_OR_PREV:
    if (key >= seqs->to)
      cur= seqs->to;
    else
    {
      if (key < seqs->from)
        return HA_ERR_KEY_NOT_FOUND;
      cur= (key - seqs->from) / seqs->step * seqs->step + seqs->from;
    }
    return index_prev(buf);
  default: return HA_ERR_WRONG_COMMAND;
  }
}

int ha_seq::index_next(uchar *buf)
{
  if (cur == seqs->to)
    return HA_ERR_END_OF_FILE;
  set(buf);
  cur+= seqs->step;
  return 0;
}

int ha_seq::index_prev(uchar *buf)
{
  if (cur == seqs->from)
    return HA_ERR_END_OF_FILE;
  cur-= seqs->step;
  set(buf);
  return 0;
}

int ha_seq::index_first(uchar *buf)
{
  cur= seqs->from;
  return index_next(buf);
}

int ha_seq::index_last(uchar *buf)
{
  cur= seqs->to;
  return index_prev(buf);
}

ha_rows ha_seq::records_in_range(uint inx, key_range *min_key,
                                 key_range *max_key)
{
  ulonglong kmin= min_key ? uint8korr(min_key->key) : seqs->from;
  ulonglong kmax= max_key ? uint8korr(max_key->key) : seqs->to - 1;
  if (kmin >= seqs->to || kmax < seqs->from || kmin > kmax)
    return 0;
  return (kmax - seqs->from) / seqs->step -
         (kmin - seqs->from + seqs->step - 1) / seqs->step + 1;
}

int ha_seq::open(const char *name, int mode, uint test_if_locked)
{
  if (!(seqs= get_share()))
    return HA_ERR_OUT_OF_MEM;
  DBUG_ASSERT(my_strcasecmp(table_alias_charset, name, seqs->name) == 0);

  ref_length= sizeof(cur);
  thr_lock_data_init(&seqs->lock,&lock,NULL);
  return 0;
}

int ha_seq::close(void)
{
  return 0;
}

static handler *create_handler(handlerton *hton, TABLE_SHARE *table,
                               MEM_ROOT *mem_root)
{
  return new (mem_root) ha_seq(hton, table);
}

static bool parse_table_name(const char *name, size_t name_length,
                             ulonglong *from, ulonglong *to, ulonglong *step)
{
  uint n1= 0, n2= 0;
  *step= 1;

  // the table is discovered if its name matches the pattern of seq_1_to_10 or
  // seq_1_to_10_step_3
  sscanf(name, "seq_%llu_to_%llu%n_step_%llu%n",
         from, to, &n1, step, &n2);
  return n1 != name_length && n2 != name_length;
}

SHARE *ha_seq::get_share()
{
  SHARE *tmp_share;
  lock_shared_ha_data();
  if (!(tmp_share= static_cast<SHARE*>(get_ha_share_ptr())))
  {
    bool reverse;
    ulonglong from, to, step;

    parse_table_name(table_share->table_name.str,
                     table_share->table_name.length, &from, &to, &step);

    if ((reverse = from > to))
    {
      if (step > from - to)
        to = from;
      else
        swap_variables(ulonglong, from, to);
      /*
        when keyread is allowed, optimizer will always prefer an index to a
        table scan for our tables, and we'll never see the range reversed.
      */
      table_share->keys_for_keyread.clear_all();
    }

    to= (to - from) / step * step + step + from;

    tmp_share= new SHARE(table_share->normalized_path.str, from, to, step, reverse);

    if (!tmp_share)
      goto err;
    set_ha_share_ptr(static_cast<Handler_share*>(tmp_share));
  }
err:
  unlock_shared_ha_data();
  return tmp_share;
}

static int discover_table(handlerton *hton, THD *thd, TABLE_SHARE *share)
{
  ulonglong from, to, step;
  if (parse_table_name(share->table_name.str, share->table_name.length,
                       &from, &to, &step))
    return HA_ERR_NO_SUCH_TABLE;

  if (step == 0)
    return HA_WRONG_CREATE_OPTION;

  const char *sql="create table seq (seq bigint unsigned primary key)";
  return share->init_from_sql_statement_string(thd, 0, sql, strlen(sql));
}

static int discover_table_existence(handlerton *hton, const char *db,
                                    const char *table_name)
{
  ulonglong from, to, step;
  return !parse_table_name(table_name, strlen(table_name), &from, &to, &step);
}

static int dummy_ret_int() { return 0; }

static int init(void *p)
{
  handlerton *hton= (handlerton *)p;
  hton->create= create_handler;
  hton->discover_table= discover_table;
  hton->discover_table_existence= discover_table_existence;
  hton->commit= hton->rollback= hton->prepare=
   (int (*)(handlerton *, THD *, bool)) &dummy_ret_int;
  hton->savepoint_set= hton->savepoint_rollback= hton->savepoint_release=
   (int  (*)(handlerton *, THD *, void *)) &dummy_ret_int;

  return 0;
}

static struct st_mysql_storage_engine descriptor =
{ MYSQL_HANDLERTON_INTERFACE_VERSION };

maria_declare_plugin(sequence)
{
  MYSQL_STORAGE_ENGINE_PLUGIN,
  &descriptor,
  "SEQUENCE",
  "Sergei Golubchik",
  "Generated tables filled with sequential values",
  PLUGIN_LICENSE_GPL,
  init,
  NULL,
  0x0100,
  NULL,
  NULL,
  "0.1",
  MariaDB_PLUGIN_MATURITY_EXPERIMENTAL
}
maria_declare_plugin_end;

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include "calc/CTables.hxx"
#include "calc/CTable.hxx"
#include "file/FCatalog.hxx"
#include "file/FConnection.hxx"
#include "calc/CCatalog.hxx"
#include <comphelper/types.hxx>

using namespace ::comphelper;
using namespace connectivity;
using namespace connectivity::calc;
using namespace connectivity::file;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::container;

sdbcx::ObjectType OCalcTables::createObject(const OUString& _rName)
{
    OCalcTable* pTable = new OCalcTable(this,(OCalcConnection*)static_cast<OFileCatalog&>(m_rParent).getConnection(),
                                        _rName,OUString("TABLE"));
    sdbcx::ObjectType xRet = pTable;
    pTable->construct();
    return xRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>loplugin:cstylecast, involving pointer to incomplete type<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include <sal/config.h>

#include <calc/CConnection.hxx>
#include "calc/CTables.hxx"
#include "calc/CTable.hxx"
#include "file/FCatalog.hxx"
#include "file/FConnection.hxx"
#include "calc/CCatalog.hxx"
#include <comphelper/types.hxx>

using namespace ::comphelper;
using namespace connectivity;
using namespace connectivity::calc;
using namespace connectivity::file;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::container;

sdbcx::ObjectType OCalcTables::createObject(const OUString& _rName)
{
    OCalcTable* pTable = new OCalcTable(this, static_cast<OCalcConnection*>(static_cast<OFileCatalog&>(m_rParent).getConnection()),
                                        _rName,OUString("TABLE"));
    sdbcx::ObjectType xRet = pTable;
    pTable->construct();
    return xRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include "ITEMS.H"

#include "CONTROL.H"

int level_items;
short next_item_free;
short next_item_active;
short GlobalPulleyFrigItem;

void InitialiseItemArray(int numitems)//418E8(<), 41D3C(<)
{
	next_item_active = -1;

	struct ITEM_INFO* item = &items[0];

#if 0
	int a2 = level_items;
	int a1 = level_items;
	int v0 = ((a2 << 3) + level_items) << 4;
#endif

	//FIXME: Ugly
	item = (struct ITEM_INFO*)(char*)item + (((level_items << 3) + level_items) << 4);

	next_item_free = level_items;

	if ((level_items + 1) < numitems)
	{
		for (int i = (level_items + 1); i < numitems; i++, item++)
		{
			item->next_item = i;

			//FIXME: Union flags.
			*(int*)item->active &= -2;
		}
	}

	//Last
	item->next_item = -1;
}

void RemoveActiveItem(short item_num)
{
	//short linknum; // $v1
}<commit_msg>Add RemoveActiveItem();<commit_after>#include "ITEMS.H"

#include "CONTROL.H"

int level_items;
short next_item_free;
short next_item_active;
short GlobalPulleyFrigItem;

void InitialiseItemArray(int numitems)//418E8(<), 41D3C(<)
{
	next_item_active = -1;

	struct ITEM_INFO* item = &items[0];

#if 0
	int a2 = level_items;
	int a1 = level_items;
	int v0 = ((a2 << 3) + level_items) << 4;
#endif

	//FIXME: Ugly
	item = (struct ITEM_INFO*)(char*)item + (((level_items << 3) + level_items) << 4);

	next_item_free = level_items;

	if ((level_items + 1) < numitems)
	{
		for (int i = (level_items + 1); i < numitems; i++, item++)
		{
			item->next_item = i;

			//FIXME: Union flags.
			*(int*)item->active &= -2;
		}
	}

	//Last
	item->next_item = -1;
}

void RemoveActiveItem(short item_num)//41E98, 422EC
{
	//short linknum; // $v1
	struct ITEM_INFO* a1 = &items[item_num];
	int v0 = a1->active;

	if (a1->active != 0)
	{
		*(int*)a1->active &= -2;
		v0 = *(int*) a1->active;

		if (next_item_active == item_num)
		{
			next_item_active = items[item_num].next_active;
			return;
		}//0x4235C

		if (next_item_active == -1)//CHECK
		{
			next_item_active = -1;
			return;
		}

		struct ITEM_INFO* a2 = &items[0];
		int a3 = -1;
		v0 = next_item_active << 3;

		while (next_item_active != -1)
		{
			v0 += -1;
			v0 <<= 4;
			struct ITEM_INFO* a11 = (struct ITEM_INFO*)(((char*) a2) + v0);
			a11->next_active = next_item_active;
			v0 = next_item_active << 3;
			v0 += next_item_active;

			if (next_item_active == item_num)
			{
				v0 <<= 4;
				struct ITEM_INFO* v00 = (struct ITEM_INFO*)(((char*) a2) + v0);
				v00->next_active = next_item_active;
				return;
			}//0x42344
		}
	}//0x4233C

	next_item_active = -2;
	return;
}<|endoftext|>


<commit_before>/*
 * HashingOverlapper.cpp
 *
 *  Created on: 31.01.2013
 *      Author: cls
 */

#include "HashingOverlapper.h"

namespace EnsembleClustering {

HashingOverlapper::HashingOverlapper() {
	// TODO Auto-generated constructor stub

}

HashingOverlapper::~HashingOverlapper() {
	// TODO Auto-generated destructor stub
}

Clustering HashingOverlapper::run(Graph& G,
		std::vector<Clustering>& clusterings) {

	// hash function sdbm
	auto sdbm = [](int64_t cid) {
		unsigned char* str = (unsigned char*) &cid;
		unsigned long h = 0;
		int c;
		while (c = *str++) {
			h = c + (h << 6) + (h << 16) - h;
		}
		return h;
	};

	auto djb2 = [](int64_t cid) {
		unsigned char* str = (unsigned char*) &cid;
		unsigned long hash = 5381;
		int c;
		while (c = *str++) {
			hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
		}
		return hash;
	};

	Clustering core(G.numberOfNodes());

	// select hash function
	auto hash = djb2;

	G.parallelForNodes([&](node v) {
		size_t cHash = 0;
		for (Clustering zeta : clusterings) {
			cHash += hash(zeta[v]);
		}
		cHash = cHash & 0xffff;
		core[v] = cHash;
	});

	// TODO: this is a quick fix for the issue that clusterings start with an upper id bound of n. bounds are needed and checked for iteration over all clusters
	cluster maxCluster = 0;
	G.forNodes([&](node v) {
		if (core[v] > maxCluster) {
			maxCluster = core[v];
		}
	});
	INFO("upperBound: " << core.upperBound());
	core.setUpperBound(maxCluster + 1);
	INFO("upperBound: " << core.upperBound());
	assert (core.upperBound() == (maxCluster + 1));
	INFO("maxCluster: " << maxCluster);

	return core;
}

} /* namespace EnsembleClustering */
<commit_msg>optimized HashingOverlapper<commit_after>/*
 * HashingOverlapper.cpp
 *
 *  Created on: 31.01.2013
 *      Author: cls
 */

#include "HashingOverlapper.h"

namespace EnsembleClustering {

HashingOverlapper::HashingOverlapper() {
	// TODO Auto-generated constructor stub

}

HashingOverlapper::~HashingOverlapper() {
	// TODO Auto-generated destructor stub
}

Clustering HashingOverlapper::run(Graph& G,
		std::vector<Clustering>& clusterings) {

	// hash function sdbm
	auto sdbm = [](int64_t cid) {
		unsigned char* str = (unsigned char*) &cid;
		unsigned long h = 0;
		int c;
		while (c = *str++) {
			h = c + (h << 6) + (h << 16) - h;
		}
		return h;
	};

	auto djb2 = [](int64_t cid) {
		unsigned char* str = (unsigned char*) &cid;
		unsigned long hash = 5381;
		int c;
		while (c = *str++) {
			hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
		}
		return hash;
	};

	Clustering core(G.numberOfNodes());

	// select hash function
	auto hash = djb2;

	core.setAll(0);
	for (Clustering zeta : clusterings) {
		G.parallelForNodes([&](node v){
			core[v] += (hash(zeta[v]) & 0xffff);
		});
	}

	// TODO: this is a quick fix for the issue that clusterings start with an upper id bound of n. bounds are needed and checked for iteration over all clusters
	cluster maxCluster = 0;
	G.forNodes([&](node v) {
		if (core[v] > maxCluster) {
			maxCluster = core[v];
		}
	});
	INFO("upperBound: " << core.upperBound());
	core.setUpperBound(maxCluster + 1);
	INFO("upperBound: " << core.upperBound());
	assert (core.upperBound() == (maxCluster + 1));
	INFO("maxCluster: " << maxCluster);

	return core;
}

} /* namespace EnsembleClustering */
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */

/*
 * XSEC
 *
 * XSECEnv := Configuration class - used by the other classes to retrieve
 *            information on the environment they are working under
 *
 * $Id$
 *
 */

// XSEC Includes
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/framework/XSECURIResolver.hpp>
#include <xsec/dsig/DSIGConstants.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>

#include <xercesc/util/XMLUniDefs.hpp>

struct XSECEnv::IdAttributeStruct {
	bool		m_useNamespace;		/* Was this defined with a namespace? */
	XMLCh		* mp_namespace;		/* Namespace of attribute */
	XMLCh		* mp_name;			/* Name of attribute */
};

XERCES_CPP_NAMESPACE_USE

// --------------------------------------------------------------------------------
//           Default prefix strings
// --------------------------------------------------------------------------------

const XMLCh s_default11Prefix[] = {

	chLatin_d,
	chLatin_s,
    chDigit_1,
    chDigit_1,
	chNull

};

const XMLCh s_defaultECPrefix[] = {

	chLatin_e,
	chLatin_c,
	chNull

};

const XMLCh s_defaultXPFPrefix[] = {

	chLatin_x,
	chLatin_p,
	chLatin_f,
	chNull

};

const XMLCh s_defaultXENCPrefix[] = {

	chLatin_x,
	chLatin_e,
	chLatin_n,
	chLatin_c,
	chNull

};

const XMLCh s_defaultXENC11Prefix[] = {

	chLatin_x,
	chLatin_e,
	chLatin_n,
	chLatin_c,
    chDigit_1,
    chDigit_1,
	chNull

};

const XMLCh s_defaultXKMSPrefix[] = {

	chLatin_x,
	chLatin_k,
	chLatin_m,
	chLatin_s,
	chNull

};

// --------------------------------------------------------------------------------
//           Default Id names
// --------------------------------------------------------------------------------

const XMLCh s_Id[] = {

	chLatin_I,
	chLatin_d,
	chNull

};

const XMLCh s_id[] = {

	chLatin_i,
	chLatin_d,
	chNull

};

// --------------------------------------------------------------------------------
//           Env
// --------------------------------------------------------------------------------

// Constructors and Destructors

XSECEnv::XSECEnv(DOMDocument *doc) {

	mp_doc = doc;

	mp_prefixNS = XMLString::replicate(DSIGConstants::s_unicodeStrEmpty);
    mp_11PrefixNS = XMLString::replicate(s_default11Prefix);
	mp_ecPrefixNS = XMLString::replicate(s_defaultECPrefix);
	mp_xpfPrefixNS = XMLString::replicate(s_defaultXPFPrefix);
	mp_xencPrefixNS = XMLString::replicate(s_defaultXENCPrefix);
    mp_xenc11PrefixNS = XMLString::replicate(s_defaultXENC11Prefix);
	mp_xkmsPrefixNS = XMLString::replicate(s_defaultXKMSPrefix);

	m_prettyPrintFlag = true;

	mp_URIResolver = NULL;

	// Set up our formatter
	XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes,
												XMLFormatter::UnRep_CharRef));

	// Set up IDs
	m_idByAttributeNameFlag = true;		// At the moment this is on by default
	// Register "Id" and "id" as valid Attribute names
	registerIdAttributeName(s_Id);
	registerIdAttributeName(s_id);

}

XSECEnv::XSECEnv(const XSECEnv & theOther) {

	mp_doc = theOther.mp_doc;

	mp_prefixNS = XMLString::replicate(theOther.mp_prefixNS);
    mp_11PrefixNS = XMLString::replicate(theOther.mp_11PrefixNS);
	mp_ecPrefixNS = XMLString::replicate(theOther.mp_ecPrefixNS);
	mp_xpfPrefixNS = XMLString::replicate(theOther.mp_xpfPrefixNS);
	mp_xencPrefixNS = XMLString::replicate(theOther.mp_xencPrefixNS);
    mp_xenc11PrefixNS = XMLString::replicate(s_defaultXENC11Prefix);
	mp_xkmsPrefixNS = XMLString::replicate(theOther.mp_xkmsPrefixNS);

	m_prettyPrintFlag = theOther.m_prettyPrintFlag;

	if (theOther.mp_URIResolver != NULL)
		mp_URIResolver = theOther.mp_URIResolver->clone();
	else
		mp_URIResolver = NULL;

	// Set up our formatter
	XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes,
												XMLFormatter::UnRep_CharRef));

	// Set up IDs
	m_idByAttributeNameFlag = theOther.m_idByAttributeNameFlag;

	for (int i = 0; i < theOther.getIdAttributeNameListSize() ; ++i) {
		registerIdAttributeName(theOther.getIdAttributeNameListItem(i));
	}

}

XSECEnv::~XSECEnv() {

	if (mp_formatter != NULL) {
		delete mp_formatter;
	}

	if (mp_prefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_prefixNS);
	}

    if (mp_11PrefixNS != NULL) {
        XSEC_RELEASE_XMLCH(mp_11PrefixNS);
    }

	if (mp_ecPrefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_ecPrefixNS);
	}

	if (mp_xpfPrefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_xpfPrefixNS);
	}

	if (mp_xencPrefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_xencPrefixNS);
	}

	if (mp_xenc11PrefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_xenc11PrefixNS);
	}

	if (mp_xkmsPrefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_xkmsPrefixNS);
	}

	if (mp_URIResolver != NULL) {
		delete mp_URIResolver;
	}

	// Clean up Id attribute names
	IdNameVectorType::iterator it;

	for (it = m_idAttributeNameList.begin(); it != m_idAttributeNameList.end(); it++) {
		IdAttributeType * i = *it;
		if (i->mp_namespace != NULL)
			XSEC_RELEASE_XMLCH((i->mp_namespace));
		if (i->mp_name)
			XSEC_RELEASE_XMLCH((i->mp_name));

		delete *it;
	}

	m_idAttributeNameList.empty();

}

// --------------------------------------------------------------------------------
//           Set and Get Resolvers
// --------------------------------------------------------------------------------

void XSECEnv::setURIResolver(XSECURIResolver * resolver) {

	if (mp_URIResolver != 0)
		delete mp_URIResolver;

	mp_URIResolver = resolver->clone();

}

XSECURIResolver * XSECEnv::getURIResolver(void) const {

	return mp_URIResolver;

}

// --------------------------------------------------------------------------------
//           Set and Get Prefixes
// --------------------------------------------------------------------------------

void XSECEnv::setDSIGNSPrefix(const XMLCh * prefix) {

	if (mp_prefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_prefixNS);

	mp_prefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setDSIG11NSPrefix(const XMLCh * prefix) {

	if (mp_11PrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_11PrefixNS);

	mp_11PrefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setECNSPrefix(const XMLCh * prefix) {

	if (mp_ecPrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_ecPrefixNS);

	mp_ecPrefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setXPFNSPrefix(const XMLCh * prefix) {

	if (mp_xpfPrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_xpfPrefixNS);

	mp_xpfPrefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setXENCNSPrefix(const XMLCh * prefix) {

	if (mp_xencPrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_xencPrefixNS);

	mp_xencPrefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setXENC11NSPrefix(const XMLCh * prefix) {

	if (mp_xenc11PrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_xenc11PrefixNS);

	mp_xenc11PrefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setXKMSNSPrefix(const XMLCh * prefix) {

	if (mp_xkmsPrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_xkmsPrefixNS);

	mp_xkmsPrefixNS = XMLString::replicate(prefix);

}

// --------------------------------------------------------------------------------
//           Id Attribute Names Handling
// --------------------------------------------------------------------------------

void XSECEnv::setIdByAttributeName(bool flag) {

	m_idByAttributeNameFlag = flag;

}

bool XSECEnv::getIdByAttributeName(void) const {

	return m_idByAttributeNameFlag;

}

bool XSECEnv::isRegisteredIdAttributeName(const XMLCh * name) const {

	int sz = (int) m_idAttributeNameList.size();

	for (int i = 0; i < sz; ++i) {
		if (!m_idAttributeNameList[i]->m_useNamespace &&
			strEquals(m_idAttributeNameList[i]->mp_name, name))
			return true;
	}

	return false;

}

void XSECEnv::registerIdAttributeName(const XMLCh * name) {

	if (isRegisteredIdAttributeName(name))
		return;

	IdAttributeType * iat;

	iat = new IdAttributeType;
	m_idAttributeNameList.push_back(iat);

	iat->m_useNamespace = false;
	iat->mp_namespace = NULL;
	iat->mp_name = XMLString::replicate(name);

}

bool XSECEnv::deregisterIdAttributeName(const XMLCh * name) {

	IdNameVectorType::iterator it;

	for (it = m_idAttributeNameList.begin(); it != m_idAttributeNameList.end(); it++) {
		if (!((*it)->m_useNamespace) && strEquals((*it)->mp_name, name)) {

			// Remove this item
			XSEC_RELEASE_XMLCH(((*it)->mp_name));
			delete *it;
			m_idAttributeNameList.erase(it);
			return true;
		}
	}

	return false;
}

bool XSECEnv::isRegisteredIdAttributeNameNS(const XMLCh * ns, const XMLCh * name) const {

	int sz = (int) m_idAttributeNameList.size();

	for (int i = 0; i < sz; ++i) {
		if (m_idAttributeNameList[i]->m_useNamespace &&
			strEquals(m_idAttributeNameList[i]->mp_namespace, ns) &&
			strEquals(m_idAttributeNameList[i]->mp_name, name))
			return true;
	}

	return false;

}

void XSECEnv::registerIdAttributeNameNS(const XMLCh * ns, const XMLCh * name) {

	if (isRegisteredIdAttributeNameNS(ns, name))
		return;

	IdAttributeType * iat;

	iat = new IdAttributeType;
	m_idAttributeNameList.push_back(iat);

	iat->m_useNamespace = true;
	iat->mp_namespace = XMLString::replicate(ns);;
	iat->mp_name = XMLString::replicate(name);

}

bool XSECEnv::deregisterIdAttributeNameNS(const XMLCh * ns, const XMLCh * name) {

	IdNameVectorType::iterator it;

	for (it = m_idAttributeNameList.begin(); it != m_idAttributeNameList.end(); it++) {
		if (((*it)->m_useNamespace) &&
			strEquals((*it)->mp_namespace, ns) &&
			strEquals((*it)->mp_name, name)) {

			// Remove this item
			XSEC_RELEASE_XMLCH(((*it)->mp_name));
			delete *it;
			m_idAttributeNameList.erase(it);
			return true;
		}
	}

	return false;
}

int XSECEnv::getIdAttributeNameListSize() const {

	return (int) m_idAttributeNameList.size();

}

const XMLCh * XSECEnv::getIdAttributeNameListItem(int index) const {

	if (index >= 0 && index < (int) m_idAttributeNameList.size())
		return m_idAttributeNameList[index]->mp_name;

	return NULL;

}

const XMLCh * XSECEnv::getIdAttributeNameListItemNS(int index) const {

	if (index >= 0 && index < (int) m_idAttributeNameList.size())
		return m_idAttributeNameList[index]->mp_namespace;

	return NULL;

}

bool XSECEnv::getIdAttributeNameListItemIsNS(int index) const {

	if (index >= 0 && index < (int) m_idAttributeNameList.size())
		return m_idAttributeNameList[index]->m_useNamespace;

	return false;

}

// --------------------------------------------------------------------------------
//           Set and Get Resolvers
// --------------------------------------------------------------------------------

void XSECEnv::doPrettyPrint(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * node) const {

	// Very simple
	if (m_prettyPrintFlag)
		node->appendChild(mp_doc->createTextNode(DSIGConstants::s_unicodeStrNL));

}

<commit_msg>Turn off broken default ID resolution by default.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */

/*
 * XSEC
 *
 * XSECEnv := Configuration class - used by the other classes to retrieve
 *            information on the environment they are working under
 *
 * $Id$
 *
 */

// XSEC Includes
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/framework/XSECURIResolver.hpp>
#include <xsec/dsig/DSIGConstants.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>

#include <xercesc/util/XMLUniDefs.hpp>

struct XSECEnv::IdAttributeStruct {
	bool		m_useNamespace;		/* Was this defined with a namespace? */
	XMLCh		* mp_namespace;		/* Namespace of attribute */
	XMLCh		* mp_name;			/* Name of attribute */
};

XERCES_CPP_NAMESPACE_USE

// --------------------------------------------------------------------------------
//           Default prefix strings
// --------------------------------------------------------------------------------

const XMLCh s_default11Prefix[] = {

	chLatin_d,
	chLatin_s,
    chDigit_1,
    chDigit_1,
	chNull

};

const XMLCh s_defaultECPrefix[] = {

	chLatin_e,
	chLatin_c,
	chNull

};

const XMLCh s_defaultXPFPrefix[] = {

	chLatin_x,
	chLatin_p,
	chLatin_f,
	chNull

};

const XMLCh s_defaultXENCPrefix[] = {

	chLatin_x,
	chLatin_e,
	chLatin_n,
	chLatin_c,
	chNull

};

const XMLCh s_defaultXENC11Prefix[] = {

	chLatin_x,
	chLatin_e,
	chLatin_n,
	chLatin_c,
    chDigit_1,
    chDigit_1,
	chNull

};

const XMLCh s_defaultXKMSPrefix[] = {

	chLatin_x,
	chLatin_k,
	chLatin_m,
	chLatin_s,
	chNull

};

// --------------------------------------------------------------------------------
//           Default Id names
// --------------------------------------------------------------------------------

const XMLCh s_Id[] = {

	chLatin_I,
	chLatin_d,
	chNull

};

const XMLCh s_id[] = {

	chLatin_i,
	chLatin_d,
	chNull

};

// --------------------------------------------------------------------------------
//           Env
// --------------------------------------------------------------------------------

// Constructors and Destructors

XSECEnv::XSECEnv(DOMDocument *doc) {

	mp_doc = doc;

	mp_prefixNS = XMLString::replicate(DSIGConstants::s_unicodeStrEmpty);
    mp_11PrefixNS = XMLString::replicate(s_default11Prefix);
	mp_ecPrefixNS = XMLString::replicate(s_defaultECPrefix);
	mp_xpfPrefixNS = XMLString::replicate(s_defaultXPFPrefix);
	mp_xencPrefixNS = XMLString::replicate(s_defaultXENCPrefix);
    mp_xenc11PrefixNS = XMLString::replicate(s_defaultXENC11Prefix);
	mp_xkmsPrefixNS = XMLString::replicate(s_defaultXKMSPrefix);

	m_prettyPrintFlag = true;

	mp_URIResolver = NULL;

	// Set up our formatter
	XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes,
												XMLFormatter::UnRep_CharRef));

	// Set up IDs
	m_idByAttributeNameFlag = false;		// At the moment this is on by default
	// Register "Id" and "id" as valid Attribute names
	registerIdAttributeName(s_Id);
	registerIdAttributeName(s_id);

}

XSECEnv::XSECEnv(const XSECEnv & theOther) {

	mp_doc = theOther.mp_doc;

	mp_prefixNS = XMLString::replicate(theOther.mp_prefixNS);
    mp_11PrefixNS = XMLString::replicate(theOther.mp_11PrefixNS);
	mp_ecPrefixNS = XMLString::replicate(theOther.mp_ecPrefixNS);
	mp_xpfPrefixNS = XMLString::replicate(theOther.mp_xpfPrefixNS);
	mp_xencPrefixNS = XMLString::replicate(theOther.mp_xencPrefixNS);
    mp_xenc11PrefixNS = XMLString::replicate(s_defaultXENC11Prefix);
	mp_xkmsPrefixNS = XMLString::replicate(theOther.mp_xkmsPrefixNS);

	m_prettyPrintFlag = theOther.m_prettyPrintFlag;

	if (theOther.mp_URIResolver != NULL)
		mp_URIResolver = theOther.mp_URIResolver->clone();
	else
		mp_URIResolver = NULL;

	// Set up our formatter
	XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes,
												XMLFormatter::UnRep_CharRef));

	// Set up IDs
	m_idByAttributeNameFlag = theOther.m_idByAttributeNameFlag;

	for (int i = 0; i < theOther.getIdAttributeNameListSize() ; ++i) {
		registerIdAttributeName(theOther.getIdAttributeNameListItem(i));
	}

}

XSECEnv::~XSECEnv() {

	if (mp_formatter != NULL) {
		delete mp_formatter;
	}

	if (mp_prefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_prefixNS);
	}

    if (mp_11PrefixNS != NULL) {
        XSEC_RELEASE_XMLCH(mp_11PrefixNS);
    }

	if (mp_ecPrefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_ecPrefixNS);
	}

	if (mp_xpfPrefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_xpfPrefixNS);
	}

	if (mp_xencPrefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_xencPrefixNS);
	}

	if (mp_xenc11PrefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_xenc11PrefixNS);
	}

	if (mp_xkmsPrefixNS != NULL) {
		XSEC_RELEASE_XMLCH(mp_xkmsPrefixNS);
	}

	if (mp_URIResolver != NULL) {
		delete mp_URIResolver;
	}

	// Clean up Id attribute names
	IdNameVectorType::iterator it;

	for (it = m_idAttributeNameList.begin(); it != m_idAttributeNameList.end(); it++) {
		IdAttributeType * i = *it;
		if (i->mp_namespace != NULL)
			XSEC_RELEASE_XMLCH((i->mp_namespace));
		if (i->mp_name)
			XSEC_RELEASE_XMLCH((i->mp_name));

		delete *it;
	}

	m_idAttributeNameList.empty();

}

// --------------------------------------------------------------------------------
//           Set and Get Resolvers
// --------------------------------------------------------------------------------

void XSECEnv::setURIResolver(XSECURIResolver * resolver) {

	if (mp_URIResolver != 0)
		delete mp_URIResolver;

	mp_URIResolver = resolver->clone();

}

XSECURIResolver * XSECEnv::getURIResolver(void) const {

	return mp_URIResolver;

}

// --------------------------------------------------------------------------------
//           Set and Get Prefixes
// --------------------------------------------------------------------------------

void XSECEnv::setDSIGNSPrefix(const XMLCh * prefix) {

	if (mp_prefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_prefixNS);

	mp_prefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setDSIG11NSPrefix(const XMLCh * prefix) {

	if (mp_11PrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_11PrefixNS);

	mp_11PrefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setECNSPrefix(const XMLCh * prefix) {

	if (mp_ecPrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_ecPrefixNS);

	mp_ecPrefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setXPFNSPrefix(const XMLCh * prefix) {

	if (mp_xpfPrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_xpfPrefixNS);

	mp_xpfPrefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setXENCNSPrefix(const XMLCh * prefix) {

	if (mp_xencPrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_xencPrefixNS);

	mp_xencPrefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setXENC11NSPrefix(const XMLCh * prefix) {

	if (mp_xenc11PrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_xenc11PrefixNS);

	mp_xenc11PrefixNS = XMLString::replicate(prefix);

}

void XSECEnv::setXKMSNSPrefix(const XMLCh * prefix) {

	if (mp_xkmsPrefixNS != NULL)
		XSEC_RELEASE_XMLCH(mp_xkmsPrefixNS);

	mp_xkmsPrefixNS = XMLString::replicate(prefix);

}

// --------------------------------------------------------------------------------
//           Id Attribute Names Handling
// --------------------------------------------------------------------------------

void XSECEnv::setIdByAttributeName(bool flag) {

	m_idByAttributeNameFlag = flag;

}

bool XSECEnv::getIdByAttributeName(void) const {

	return m_idByAttributeNameFlag;

}

bool XSECEnv::isRegisteredIdAttributeName(const XMLCh * name) const {

	int sz = (int) m_idAttributeNameList.size();

	for (int i = 0; i < sz; ++i) {
		if (!m_idAttributeNameList[i]->m_useNamespace &&
			strEquals(m_idAttributeNameList[i]->mp_name, name))
			return true;
	}

	return false;

}

void XSECEnv::registerIdAttributeName(const XMLCh * name) {

	if (isRegisteredIdAttributeName(name))
		return;

	IdAttributeType * iat;

	iat = new IdAttributeType;
	m_idAttributeNameList.push_back(iat);

	iat->m_useNamespace = false;
	iat->mp_namespace = NULL;
	iat->mp_name = XMLString::replicate(name);

}

bool XSECEnv::deregisterIdAttributeName(const XMLCh * name) {

	IdNameVectorType::iterator it;

	for (it = m_idAttributeNameList.begin(); it != m_idAttributeNameList.end(); it++) {
		if (!((*it)->m_useNamespace) && strEquals((*it)->mp_name, name)) {

			// Remove this item
			XSEC_RELEASE_XMLCH(((*it)->mp_name));
			delete *it;
			m_idAttributeNameList.erase(it);
			return true;
		}
	}

	return false;
}

bool XSECEnv::isRegisteredIdAttributeNameNS(const XMLCh * ns, const XMLCh * name) const {

	int sz = (int) m_idAttributeNameList.size();

	for (int i = 0; i < sz; ++i) {
		if (m_idAttributeNameList[i]->m_useNamespace &&
			strEquals(m_idAttributeNameList[i]->mp_namespace, ns) &&
			strEquals(m_idAttributeNameList[i]->mp_name, name))
			return true;
	}

	return false;

}

void XSECEnv::registerIdAttributeNameNS(const XMLCh * ns, const XMLCh * name) {

	if (isRegisteredIdAttributeNameNS(ns, name))
		return;

	IdAttributeType * iat;

	iat = new IdAttributeType;
	m_idAttributeNameList.push_back(iat);

	iat->m_useNamespace = true;
	iat->mp_namespace = XMLString::replicate(ns);;
	iat->mp_name = XMLString::replicate(name);

}

bool XSECEnv::deregisterIdAttributeNameNS(const XMLCh * ns, const XMLCh * name) {

	IdNameVectorType::iterator it;

	for (it = m_idAttributeNameList.begin(); it != m_idAttributeNameList.end(); it++) {
		if (((*it)->m_useNamespace) &&
			strEquals((*it)->mp_namespace, ns) &&
			strEquals((*it)->mp_name, name)) {

			// Remove this item
			XSEC_RELEASE_XMLCH(((*it)->mp_name));
			delete *it;
			m_idAttributeNameList.erase(it);
			return true;
		}
	}

	return false;
}

int XSECEnv::getIdAttributeNameListSize() const {

	return (int) m_idAttributeNameList.size();

}

const XMLCh * XSECEnv::getIdAttributeNameListItem(int index) const {

	if (index >= 0 && index < (int) m_idAttributeNameList.size())
		return m_idAttributeNameList[index]->mp_name;

	return NULL;

}

const XMLCh * XSECEnv::getIdAttributeNameListItemNS(int index) const {

	if (index >= 0 && index < (int) m_idAttributeNameList.size())
		return m_idAttributeNameList[index]->mp_namespace;

	return NULL;

}

bool XSECEnv::getIdAttributeNameListItemIsNS(int index) const {

	if (index >= 0 && index < (int) m_idAttributeNameList.size())
		return m_idAttributeNameList[index]->m_useNamespace;

	return false;

}

// --------------------------------------------------------------------------------
//           Set and Get Resolvers
// --------------------------------------------------------------------------------

void XSECEnv::doPrettyPrint(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * node) const {

	// Very simple
	if (m_prettyPrintFlag)
		node->appendChild(mp_doc->createTextNode(DSIGConstants::s_unicodeStrNL));

}

<|endoftext|>


<commit_before>//===---- CapturePropagation.cpp - Propagate closure capture constants ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "capture-prop"
#include "swift/SILPasses/Passes.h"
#include "swift/Basic/Demangle.h"
#include "swift/SIL/Mangle.h"
#include "swift/SIL/SILCloner.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SILAnalysis/ColdBlockInfo.h"
#include "swift/SILAnalysis/DominanceAnalysis.h"
#include "swift/SILPasses/Transforms.h"
#include "swift/SILPasses/Utils/Local.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"

using namespace swift;

STATISTIC(NumCapturesPropagated, "Number of constant captures propagated");

namespace {
/// Propagate constants through closure captures by specializing the partially
/// applied function.
class CapturePropagation : public SILModuleTransform
{
public:
  void run() override;

  StringRef getName() override { return "Captured Constant Propagation"; }

protected:
  bool optimizePartialApply(PartialApplyInst *PAI);
  SILFunction *specializeConstClosure(PartialApplyInst *PAI,
                                      SILFunction *SubstF);
  void rewritePartialApply(PartialApplyInst *PAI, SILFunction *SpecialF);
};
} // namespace

static LiteralInst *getConstant(SILValue V) {
  if (auto I = dyn_cast<ThinToThickFunctionInst>(V))
    return getConstant(I->getOperand());
  return dyn_cast<LiteralInst>(V);
}

static bool isOptimizableConstant(SILValue V) {
  // We do not optimize string literals of length > 32 since we would need to
  // encode them into the symbol name for uniqueness.
  if (auto *SLI = dyn_cast<StringLiteralInst>(V))
    return SLI->getValue().size() <= 32;
  return true;
}

static bool isConstant(SILValue V) {
  V = getConstant(V);
  return V && isOptimizableConstant(V);
}

static llvm::SmallString<64> getClonedName(PartialApplyInst *PAI,
                                           SILFunction *F) {
  llvm::SmallString<64> ClonedName;

  llvm::raw_svector_ostream buffer(ClonedName);
  Mangle::Mangler M(buffer);
  auto P = Mangle::SpecializationPass::CapturePropagation;
  Mangle::FunctionSignatureSpecializationMangler Mangler(P, M, F);

  // We know that all arguments are literal insts.
  auto Args = PAI->getArguments();
  for (unsigned i : indices(Args))
    Mangler.setArgumentConstantProp(i, getConstant(Args[i]));
  Mangler.mangle();

  return ClonedName;
}

namespace {
/// Clone the partially applied function, replacing incoming arguments with
/// literal constants.
///
/// The cloned literals will retain the SILLocation from the partial apply's
/// caller, so the cloned function will have a mix of locations from different
/// functions.
class CapturePropagationCloner
  : public SILClonerWithScopes<CapturePropagationCloner> {
  using SuperTy = SILClonerWithScopes<CapturePropagationCloner>;
  friend class SILVisitor<CapturePropagationCloner>;
  friend class SILCloner<CapturePropagationCloner>;

  SILFunction *OrigF;
  bool IsCloningConstant;
public:
  CapturePropagationCloner(SILFunction *OrigF, SILFunction *NewF)
    : SuperTy(*NewF), OrigF(OrigF), IsCloningConstant(false) {}

  void cloneBlocks(OperandValueArrayRef Args);

protected:
  /// Literals cloned from the caller drop their location so the debug line
  /// tables don't senselessly jump around. As a placeholder give them the
  /// location of the newly cloned function.
  SILLocation remapLocation(SILLocation InLoc) {
    if (IsCloningConstant)
      return getBuilder().getFunction().getLocation();
    return InLoc;
  }

  /// Literals cloned from the caller take on the new function's debug scope.
  void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
    assert(IsCloningConstant == (Orig->getFunction() != OrigF) &&
           "Expect only cloned constants from the caller function.");
    SILClonerWithScopes<CapturePropagationCloner>::postProcess(Orig, Cloned);
  }

  const SILDebugScope *remapScope(const SILDebugScope *DS) {
    if (IsCloningConstant)
      return getBuilder().getFunction().getDebugScope();
    else
      return SILClonerWithScopes<CapturePropagationCloner>::remapScope(DS);
  }

  void cloneConstValue(SILValue Const);
};
} // namespace

/// Clone a constant value. Recursively walk the operand chain through cast
/// instructions to ensure that all dependents are cloned. Note that the
/// original value may not belong to the same function as the one being cloned
/// by cloneBlocks() (they may be from the partial apply caller).
void CapturePropagationCloner::cloneConstValue(SILValue Val) {
  assert(IsCloningConstant && "incorrect mode");

  auto Inst = dyn_cast<SILInstruction>(Val);
  if (!Inst)
    return;

  auto II = InstructionMap.find(Inst);
  if (II != InstructionMap.end())
    return;

  if (Inst->getNumOperands() > 0) {
    // Only handle single operands for simple recursion without a worklist.
    assert(Inst->getNumOperands() == 1 && "expected single-operand cast");
    cloneConstValue(Inst->getOperand(0));
  }
  visit(Inst);
}

/// Clone the original partially applied function into the new specialized
/// function, replacing some arguments with literals.
void CapturePropagationCloner::cloneBlocks(
  OperandValueArrayRef PartialApplyArgs) {

  SILFunction &CloneF = getBuilder().getFunction();
  SILModule &M = CloneF.getModule();

  // Create the entry basic block with the function arguments.
  SILBasicBlock *OrigEntryBB = &*OrigF->begin();
  SILBasicBlock *ClonedEntryBB = new (M) SILBasicBlock(&CloneF);
  CanSILFunctionType CloneFTy = CloneF.getLoweredFunctionType();

  // Only clone the arguments that remain in the new function type. The trailing
  // arguments are now propagated through the partial apply.
  assert(!IsCloningConstant && "incorrect mode");
  unsigned ParamIdx = 0;
  for (unsigned NewParamEnd = CloneFTy->getParameters().size();
       ParamIdx != NewParamEnd; ++ParamIdx) {

    SILArgument *Arg = OrigEntryBB->getBBArg(ParamIdx);

    SILValue MappedValue = new (M)
        SILArgument(ClonedEntryBB, remapType(Arg->getType()), Arg->getDecl());
    ValueMap.insert(std::make_pair(Arg, MappedValue));
  }
  assert(OrigEntryBB->bbarg_size() - ParamIdx == PartialApplyArgs.size()
         && "unexpected number of partial apply arguments");

  // Replace the rest of the old arguments with constants.
  BBMap.insert(std::make_pair(OrigEntryBB, ClonedEntryBB));
  getBuilder().setInsertionPoint(ClonedEntryBB);
  IsCloningConstant = true;
  for (SILValue PartialApplyArg : PartialApplyArgs) {
    assert(isConstant(PartialApplyArg) &&
           "expected a constant arg to partial apply");

    cloneConstValue(PartialApplyArg);

    // The PartialApplyArg from the caller is now mapped to its cloned
    // instruction.  Also map the original argument to the cloned instruction.
    SILArgument *InArg = OrigEntryBB->getBBArg(ParamIdx);
    ValueMap.insert(std::make_pair(InArg, remapValue(PartialApplyArg)));
    ++ParamIdx;
  }
  IsCloningConstant = false;
  // Recursively visit original BBs in depth-first preorder, starting with the
  // entry block, cloning all instructions other than terminators.
  visitSILBasicBlock(OrigEntryBB);

  // Now iterate over the BBs and fix up the terminators.
  for (auto BI = BBMap.begin(), BE = BBMap.end(); BI != BE; ++BI) {
    getBuilder().setInsertionPoint(BI->second);
    visit(BI->first->getTerminator());
  }
}

/// Given a partial_apply instruction, create a specialized callee by removing
/// all constant arguments and adding constant literals to the specialized
/// function body.
SILFunction *CapturePropagation::specializeConstClosure(PartialApplyInst *PAI,
                                                        SILFunction *OrigF) {
  llvm::SmallString<64> Name = getClonedName(PAI, OrigF);

  // See if we already have a version of this function in the module. If so,
  // just return it.
  if (auto *NewF = OrigF->getModule().lookUpFunction(Name.str())) {
    DEBUG(llvm::dbgs() << "  Found an already specialized version of the callee: ";
          NewF->printName(llvm::dbgs()); llvm::dbgs() << "\n");
    return NewF;
  }

  // The new partial_apply will no longer take any arguments--they are all
  // expressed as literals. So its callee signature will be the same as its
  // return signature.
  CanSILFunctionType NewFTy =
    Lowering::adjustFunctionType(PAI->getType().castTo<SILFunctionType>(),
                                 SILFunctionType::Representation::Thin);
  SILFunction *NewF = getModule()->getOrCreateFunction(
      SILLinkage::Shared, Name, NewFTy,
      /*contextGenericParams*/ nullptr, OrigF->getLocation(), OrigF->isBare(),
      OrigF->isTransparent(), OrigF->isFragile(), OrigF->isThunk(),
      OrigF->getClassVisibility(), OrigF->getInlineStrategy(),
      OrigF->getEffectsKind(),
      /*InsertBefore*/ OrigF, OrigF->getDebugScope(), OrigF->getDeclContext());
  NewF->setDeclCtx(OrigF->getDeclContext());
  DEBUG(llvm::dbgs() << "  Specialize callee as ";
        NewF->printName(llvm::dbgs()); llvm::dbgs() << " " << NewFTy << "\n");

  CapturePropagationCloner cloner(OrigF, NewF);
  cloner.cloneBlocks(PAI->getArguments());
  assert(OrigF->getDebugScope()->SILFn != NewF->getDebugScope()->SILFn);
  return NewF;
}

void CapturePropagation::rewritePartialApply(PartialApplyInst *OrigPAI,
                                             SILFunction *SpecialF) {
  SILBuilderWithScope Builder(OrigPAI);
  auto FuncRef = Builder.createFunctionRef(OrigPAI->getLoc(), SpecialF);
  auto NewPAI = Builder.createPartialApply(OrigPAI->getLoc(),
                                           FuncRef,
                                           SpecialF->getLoweredType(),
                                           ArrayRef<Substitution>(),
                                           ArrayRef<SILValue>(),
                                           OrigPAI->getType());
  OrigPAI->replaceAllUsesWith(NewPAI);
  recursivelyDeleteTriviallyDeadInstructions(OrigPAI, true);
  DEBUG(llvm::dbgs() << "  Rewrote caller:\n" << *NewPAI);
}

/// For now, we conservative only specialize if doing so can eliminate dynamic
/// dispatch.
///
/// TODO: Check for other profitable constant propagation, like builtin compare.
static bool isProfitable(SILFunction *Callee) {
  SILBasicBlock *EntryBB = &*Callee->begin();
  for (auto *Arg : EntryBB->getBBArgs()) {
    for (auto *Operand : Arg->getUses()) {
      if (auto *AI = dyn_cast<ApplyInst>(Operand->getUser())) {
        if (AI->getCallee() == Operand->get())
          return true;
      }
    }
  }
  return false;
}

bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
  // Check if the partial_apply has generic substitutions.
  // FIXME: We could handle generic thunks if it's worthwhile.
  if (PAI->hasSubstitutions())
    return false;

  auto *FRI = dyn_cast<FunctionRefInst>(PAI->getCallee());
  if (!FRI)
    return false;

  assert(!FRI->getFunctionType()->isPolymorphic() &&
         "cannot specialize generic partial apply");

  for (auto Arg : PAI->getArguments()) {
    if (!isConstant(Arg))
      return false;
  }
  SILFunction *SubstF = FRI->getReferencedFunction();
  if (SubstF->isExternalDeclaration() || !isProfitable(SubstF))
    return false;

  DEBUG(llvm::dbgs() << "Specializing closure for constant arguments:\n"
        << "  " << SubstF->getName() << "\n" << *PAI);
  ++NumCapturesPropagated;
  SILFunction *NewF = specializeConstClosure(PAI, SubstF);
  rewritePartialApply(PAI, NewF);
  return true;
}

void CapturePropagation::run() {
  DominanceAnalysis *DA = PM->getAnalysis<DominanceAnalysis>();
  bool HasChanged = false;
  for (auto &F : *getModule()) {

    // Don't optimize functions that are marked with the opt.never attribute.
    if (!F.shouldOptimize())
      continue;

    // Cache cold blocks per function.
    ColdBlockInfo ColdBlocks(DA);
    for (auto &BB : F) {
      if (ColdBlocks.isCold(&BB))
        continue;

      auto I = BB.begin();
      while (I != BB.end()) {
        SILInstruction *Inst = &*I;
        ++I;
        if (PartialApplyInst *PAI = dyn_cast<PartialApplyInst>(Inst))
          HasChanged |= optimizePartialApply(PAI);
      }
    }
  }

  if (HasChanged) {
    invalidateAnalysis(SILAnalysis::InvalidationKind::Everything);
  }
}

SILTransform *swift::createCapturePropagation() {
  return new CapturePropagation();
}
<commit_msg>Fix 80-column violation.<commit_after>//===---- CapturePropagation.cpp - Propagate closure capture constants ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "capture-prop"
#include "swift/SILPasses/Passes.h"
#include "swift/Basic/Demangle.h"
#include "swift/SIL/Mangle.h"
#include "swift/SIL/SILCloner.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SILAnalysis/ColdBlockInfo.h"
#include "swift/SILAnalysis/DominanceAnalysis.h"
#include "swift/SILPasses/Transforms.h"
#include "swift/SILPasses/Utils/Local.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"

using namespace swift;

STATISTIC(NumCapturesPropagated, "Number of constant captures propagated");

namespace {
/// Propagate constants through closure captures by specializing the partially
/// applied function.
class CapturePropagation : public SILModuleTransform
{
public:
  void run() override;

  StringRef getName() override { return "Captured Constant Propagation"; }

protected:
  bool optimizePartialApply(PartialApplyInst *PAI);
  SILFunction *specializeConstClosure(PartialApplyInst *PAI,
                                      SILFunction *SubstF);
  void rewritePartialApply(PartialApplyInst *PAI, SILFunction *SpecialF);
};
} // namespace

static LiteralInst *getConstant(SILValue V) {
  if (auto I = dyn_cast<ThinToThickFunctionInst>(V))
    return getConstant(I->getOperand());
  return dyn_cast<LiteralInst>(V);
}

static bool isOptimizableConstant(SILValue V) {
  // We do not optimize string literals of length > 32 since we would need to
  // encode them into the symbol name for uniqueness.
  if (auto *SLI = dyn_cast<StringLiteralInst>(V))
    return SLI->getValue().size() <= 32;
  return true;
}

static bool isConstant(SILValue V) {
  V = getConstant(V);
  return V && isOptimizableConstant(V);
}

static llvm::SmallString<64> getClonedName(PartialApplyInst *PAI,
                                           SILFunction *F) {
  llvm::SmallString<64> ClonedName;

  llvm::raw_svector_ostream buffer(ClonedName);
  Mangle::Mangler M(buffer);
  auto P = Mangle::SpecializationPass::CapturePropagation;
  Mangle::FunctionSignatureSpecializationMangler Mangler(P, M, F);

  // We know that all arguments are literal insts.
  auto Args = PAI->getArguments();
  for (unsigned i : indices(Args))
    Mangler.setArgumentConstantProp(i, getConstant(Args[i]));
  Mangler.mangle();

  return ClonedName;
}

namespace {
/// Clone the partially applied function, replacing incoming arguments with
/// literal constants.
///
/// The cloned literals will retain the SILLocation from the partial apply's
/// caller, so the cloned function will have a mix of locations from different
/// functions.
class CapturePropagationCloner
  : public SILClonerWithScopes<CapturePropagationCloner> {
  using SuperTy = SILClonerWithScopes<CapturePropagationCloner>;
  friend class SILVisitor<CapturePropagationCloner>;
  friend class SILCloner<CapturePropagationCloner>;

  SILFunction *OrigF;
  bool IsCloningConstant;
public:
  CapturePropagationCloner(SILFunction *OrigF, SILFunction *NewF)
    : SuperTy(*NewF), OrigF(OrigF), IsCloningConstant(false) {}

  void cloneBlocks(OperandValueArrayRef Args);

protected:
  /// Literals cloned from the caller drop their location so the debug line
  /// tables don't senselessly jump around. As a placeholder give them the
  /// location of the newly cloned function.
  SILLocation remapLocation(SILLocation InLoc) {
    if (IsCloningConstant)
      return getBuilder().getFunction().getLocation();
    return InLoc;
  }

  /// Literals cloned from the caller take on the new function's debug scope.
  void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
    assert(IsCloningConstant == (Orig->getFunction() != OrigF) &&
           "Expect only cloned constants from the caller function.");
    SILClonerWithScopes<CapturePropagationCloner>::postProcess(Orig, Cloned);
  }

  const SILDebugScope *remapScope(const SILDebugScope *DS) {
    if (IsCloningConstant)
      return getBuilder().getFunction().getDebugScope();
    else
      return SILClonerWithScopes<CapturePropagationCloner>::remapScope(DS);
  }

  void cloneConstValue(SILValue Const);
};
} // namespace

/// Clone a constant value. Recursively walk the operand chain through cast
/// instructions to ensure that all dependents are cloned. Note that the
/// original value may not belong to the same function as the one being cloned
/// by cloneBlocks() (they may be from the partial apply caller).
void CapturePropagationCloner::cloneConstValue(SILValue Val) {
  assert(IsCloningConstant && "incorrect mode");

  auto Inst = dyn_cast<SILInstruction>(Val);
  if (!Inst)
    return;

  auto II = InstructionMap.find(Inst);
  if (II != InstructionMap.end())
    return;

  if (Inst->getNumOperands() > 0) {
    // Only handle single operands for simple recursion without a worklist.
    assert(Inst->getNumOperands() == 1 && "expected single-operand cast");
    cloneConstValue(Inst->getOperand(0));
  }
  visit(Inst);
}

/// Clone the original partially applied function into the new specialized
/// function, replacing some arguments with literals.
void CapturePropagationCloner::cloneBlocks(
  OperandValueArrayRef PartialApplyArgs) {

  SILFunction &CloneF = getBuilder().getFunction();
  SILModule &M = CloneF.getModule();

  // Create the entry basic block with the function arguments.
  SILBasicBlock *OrigEntryBB = &*OrigF->begin();
  SILBasicBlock *ClonedEntryBB = new (M) SILBasicBlock(&CloneF);
  CanSILFunctionType CloneFTy = CloneF.getLoweredFunctionType();

  // Only clone the arguments that remain in the new function type. The trailing
  // arguments are now propagated through the partial apply.
  assert(!IsCloningConstant && "incorrect mode");
  unsigned ParamIdx = 0;
  for (unsigned NewParamEnd = CloneFTy->getParameters().size();
       ParamIdx != NewParamEnd; ++ParamIdx) {

    SILArgument *Arg = OrigEntryBB->getBBArg(ParamIdx);

    SILValue MappedValue = new (M)
        SILArgument(ClonedEntryBB, remapType(Arg->getType()), Arg->getDecl());
    ValueMap.insert(std::make_pair(Arg, MappedValue));
  }
  assert(OrigEntryBB->bbarg_size() - ParamIdx == PartialApplyArgs.size()
         && "unexpected number of partial apply arguments");

  // Replace the rest of the old arguments with constants.
  BBMap.insert(std::make_pair(OrigEntryBB, ClonedEntryBB));
  getBuilder().setInsertionPoint(ClonedEntryBB);
  IsCloningConstant = true;
  for (SILValue PartialApplyArg : PartialApplyArgs) {
    assert(isConstant(PartialApplyArg) &&
           "expected a constant arg to partial apply");

    cloneConstValue(PartialApplyArg);

    // The PartialApplyArg from the caller is now mapped to its cloned
    // instruction.  Also map the original argument to the cloned instruction.
    SILArgument *InArg = OrigEntryBB->getBBArg(ParamIdx);
    ValueMap.insert(std::make_pair(InArg, remapValue(PartialApplyArg)));
    ++ParamIdx;
  }
  IsCloningConstant = false;
  // Recursively visit original BBs in depth-first preorder, starting with the
  // entry block, cloning all instructions other than terminators.
  visitSILBasicBlock(OrigEntryBB);

  // Now iterate over the BBs and fix up the terminators.
  for (auto BI = BBMap.begin(), BE = BBMap.end(); BI != BE; ++BI) {
    getBuilder().setInsertionPoint(BI->second);
    visit(BI->first->getTerminator());
  }
}

/// Given a partial_apply instruction, create a specialized callee by removing
/// all constant arguments and adding constant literals to the specialized
/// function body.
SILFunction *CapturePropagation::specializeConstClosure(PartialApplyInst *PAI,
                                                        SILFunction *OrigF) {
  llvm::SmallString<64> Name = getClonedName(PAI, OrigF);

  // See if we already have a version of this function in the module. If so,
  // just return it.
  if (auto *NewF = OrigF->getModule().lookUpFunction(Name.str())) {
    DEBUG(llvm::dbgs()
              << "  Found an already specialized version of the callee: ";
          NewF->printName(llvm::dbgs()); llvm::dbgs() << "\n");
    return NewF;
  }

  // The new partial_apply will no longer take any arguments--they are all
  // expressed as literals. So its callee signature will be the same as its
  // return signature.
  CanSILFunctionType NewFTy =
    Lowering::adjustFunctionType(PAI->getType().castTo<SILFunctionType>(),
                                 SILFunctionType::Representation::Thin);
  SILFunction *NewF = getModule()->getOrCreateFunction(
      SILLinkage::Shared, Name, NewFTy,
      /*contextGenericParams*/ nullptr, OrigF->getLocation(), OrigF->isBare(),
      OrigF->isTransparent(), OrigF->isFragile(), OrigF->isThunk(),
      OrigF->getClassVisibility(), OrigF->getInlineStrategy(),
      OrigF->getEffectsKind(),
      /*InsertBefore*/ OrigF, OrigF->getDebugScope(), OrigF->getDeclContext());
  NewF->setDeclCtx(OrigF->getDeclContext());
  DEBUG(llvm::dbgs() << "  Specialize callee as ";
        NewF->printName(llvm::dbgs()); llvm::dbgs() << " " << NewFTy << "\n");

  CapturePropagationCloner cloner(OrigF, NewF);
  cloner.cloneBlocks(PAI->getArguments());
  assert(OrigF->getDebugScope()->SILFn != NewF->getDebugScope()->SILFn);
  return NewF;
}

void CapturePropagation::rewritePartialApply(PartialApplyInst *OrigPAI,
                                             SILFunction *SpecialF) {
  SILBuilderWithScope Builder(OrigPAI);
  auto FuncRef = Builder.createFunctionRef(OrigPAI->getLoc(), SpecialF);
  auto NewPAI = Builder.createPartialApply(OrigPAI->getLoc(),
                                           FuncRef,
                                           SpecialF->getLoweredType(),
                                           ArrayRef<Substitution>(),
                                           ArrayRef<SILValue>(),
                                           OrigPAI->getType());
  OrigPAI->replaceAllUsesWith(NewPAI);
  recursivelyDeleteTriviallyDeadInstructions(OrigPAI, true);
  DEBUG(llvm::dbgs() << "  Rewrote caller:\n" << *NewPAI);
}

/// For now, we conservative only specialize if doing so can eliminate dynamic
/// dispatch.
///
/// TODO: Check for other profitable constant propagation, like builtin compare.
static bool isProfitable(SILFunction *Callee) {
  SILBasicBlock *EntryBB = &*Callee->begin();
  for (auto *Arg : EntryBB->getBBArgs()) {
    for (auto *Operand : Arg->getUses()) {
      if (auto *AI = dyn_cast<ApplyInst>(Operand->getUser())) {
        if (AI->getCallee() == Operand->get())
          return true;
      }
    }
  }
  return false;
}

bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
  // Check if the partial_apply has generic substitutions.
  // FIXME: We could handle generic thunks if it's worthwhile.
  if (PAI->hasSubstitutions())
    return false;

  auto *FRI = dyn_cast<FunctionRefInst>(PAI->getCallee());
  if (!FRI)
    return false;

  assert(!FRI->getFunctionType()->isPolymorphic() &&
         "cannot specialize generic partial apply");

  for (auto Arg : PAI->getArguments()) {
    if (!isConstant(Arg))
      return false;
  }
  SILFunction *SubstF = FRI->getReferencedFunction();
  if (SubstF->isExternalDeclaration() || !isProfitable(SubstF))
    return false;

  DEBUG(llvm::dbgs() << "Specializing closure for constant arguments:\n"
        << "  " << SubstF->getName() << "\n" << *PAI);
  ++NumCapturesPropagated;
  SILFunction *NewF = specializeConstClosure(PAI, SubstF);
  rewritePartialApply(PAI, NewF);
  return true;
}

void CapturePropagation::run() {
  DominanceAnalysis *DA = PM->getAnalysis<DominanceAnalysis>();
  bool HasChanged = false;
  for (auto &F : *getModule()) {

    // Don't optimize functions that are marked with the opt.never attribute.
    if (!F.shouldOptimize())
      continue;

    // Cache cold blocks per function.
    ColdBlockInfo ColdBlocks(DA);
    for (auto &BB : F) {
      if (ColdBlocks.isCold(&BB))
        continue;

      auto I = BB.begin();
      while (I != BB.end()) {
        SILInstruction *Inst = &*I;
        ++I;
        if (PartialApplyInst *PAI = dyn_cast<PartialApplyInst>(Inst))
          HasChanged |= optimizePartialApply(PAI);
      }
    }
  }

  if (HasChanged) {
    invalidateAnalysis(SILAnalysis::InvalidationKind::Everything);
  }
}

SILTransform *swift::createCapturePropagation() {
  return new CapturePropagation();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DIndexPage.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 07:04:21 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_DBASE_INDEXPAGE_HXX_
#define _CONNECTIVITY_DBASE_INDEXPAGE_HXX_

//#ifndef _REF_HXX
//#include <tools/ref.hxx>
//#endif
#ifndef _VOS_REF_HXX_
#include <vos/ref.hxx>
#endif
#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif
#ifndef _VECTOR_
#include <vector>
#endif
//#ifndef _CONNECTIVITY_FILE_FCODE_HXX_
//#include "file/fcode.hxx"
//#endif
//#ifndef _CONNECTIVITY_DBASE_INDEXNODE_HXX_
//#include "dbase/dindexnode.hxx"
//#endif

#if 0
namespace connectivity
{
    namespace dbase
    {
        //==================================================================
        // Index Seitenverweis
        //==================================================================
        //  SV_DECL_REF(ONDXPage); // Basisklasse da weitere Informationen gehalten werden muessen

        class ONDXPage;
        typedef vos::ORef<ONDXPage>         ONDXPagePtr_BASE;

        class ONDXPagePtr : public ONDXPagePtr_BASE //ONDXPageRef
        {
            friend  SvStream& operator << (SvStream &rStream, const ONDXPagePtr&);
            friend  SvStream& operator >> (SvStream &rStream, ONDXPagePtr&);

            UINT32  nPagePos;       // Position in der Indexdatei

        public:
            ONDXPagePtr(UINT32 nPos = 0):nPagePos(nPos){}
            ONDXPagePtr(const ONDXPagePtr& rRef);
            ONDXPagePtr(ONDXPage* pRefPage);

            ONDXPagePtr& operator=(const ONDXPagePtr& rRef);
            ONDXPagePtr& operator=(ONDXPage* pPageRef);

            UINT32 GetPagePos() const {return nPagePos;}
            BOOL HasPage() const {return nPagePos != 0;}
            sal_Bool Is() const { return isValid(); }
            void Clear()
            {
                unbind();
            }
        };

        SvStream& operator << (SvStream &rStream, const ONDXPagePtr&);
        SvStream& operator >> (SvStream &rStream, ONDXPagePtr&);
    }
}
#endif
#endif // _CONNECTIVITY_DBASE_INDEXPAGE_HXX_

<commit_msg>INTEGRATION: CWS changefileheader (1.2.372); FILE MERGED 2008/04/01 15:09:10 thb 1.2.372.2: #i85898# Stripping all external header guards 2008/03/28 15:24:18 rt 1.2.372.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: DIndexPage.hxx,v $
 * $Revision: 1.3 $
 *
 * 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.
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_DBASE_INDEXPAGE_HXX_
#define _CONNECTIVITY_DBASE_INDEXPAGE_HXX_

//#ifndef _REF_HXX
//#include <tools/ref.hxx>
//#endif
#include <vos/ref.hxx>
#include <tools/stream.hxx>
#ifndef _VECTOR_
#include <vector>
#endif
//#ifndef _CONNECTIVITY_FILE_FCODE_HXX_
//#include "file/fcode.hxx"
//#endif
//#ifndef _CONNECTIVITY_DBASE_INDEXNODE_HXX_
//#include "dbase/dindexnode.hxx"
//#endif

#if 0
namespace connectivity
{
    namespace dbase
    {
        //==================================================================
        // Index Seitenverweis
        //==================================================================
        //  SV_DECL_REF(ONDXPage); // Basisklasse da weitere Informationen gehalten werden muessen

        class ONDXPage;
        typedef vos::ORef<ONDXPage>         ONDXPagePtr_BASE;

        class ONDXPagePtr : public ONDXPagePtr_BASE //ONDXPageRef
        {
            friend  SvStream& operator << (SvStream &rStream, const ONDXPagePtr&);
            friend  SvStream& operator >> (SvStream &rStream, ONDXPagePtr&);

            UINT32  nPagePos;       // Position in der Indexdatei

        public:
            ONDXPagePtr(UINT32 nPos = 0):nPagePos(nPos){}
            ONDXPagePtr(const ONDXPagePtr& rRef);
            ONDXPagePtr(ONDXPage* pRefPage);

            ONDXPagePtr& operator=(const ONDXPagePtr& rRef);
            ONDXPagePtr& operator=(ONDXPage* pPageRef);

            UINT32 GetPagePos() const {return nPagePos;}
            BOOL HasPage() const {return nPagePos != 0;}
            sal_Bool Is() const { return isValid(); }
            void Clear()
            {
                unbind();
            }
        };

        SvStream& operator << (SvStream &rStream, const ONDXPagePtr&);
        SvStream& operator >> (SvStream &rStream, ONDXPagePtr&);
    }
}
#endif
#endif // _CONNECTIVITY_DBASE_INDEXPAGE_HXX_

<|endoftext|>