<commit_before>// Very messy hack to get the defines for different bio operations. Should be
// changed to something more palatable if possible.

#include <endian.h>

#include <cassert>
#include <cstring>

#include <fstream>
#include <ios>
#include <iostream>
#include <memory>
#include <random>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "utils.h"
#include "utils_c.h"

namespace fs_testing {
namespace utils {
using std::endl;
using std::ifstream;
using std::ios;
using std::memcpy;
using std::mt19937;
using std::ofstream;
using std::ostream;
using std::pair;
using std::shared_ptr;
using std::tie;
using std::uniform_int_distribution;
using std::vector;

bool disk_write::is_async_write() {
  return c_is_async_write(&metadata);
}

bool disk_write::is_barrier_write() {
  return c_is_barrier_write(&metadata);
}

bool disk_write::is_meta() {
  return c_is_meta(&metadata);
}

bool disk_write::is_checkpoint() {
  return c_is_checkpoint(&metadata);
}

disk_write::disk_write(const struct disk_write_op_meta& m,
    const char *d) {
  metadata = m;
  if (metadata.size > 0 && d != NULL) {
    data = shared_ptr<char>(new char[metadata.size],
        [](char* c) {delete[] c;});
    memcpy(data.get(), d, metadata.size);
  }
}

disk_write::disk_write(const disk_write& other) {
  metadata = other.metadata;
  data = other.data;
}

void disk_write::operator=(const disk_write& other) {
  metadata = other.metadata;
  data = other.data;
}

bool operator==(const disk_write& a, const disk_write& b) {
  if (tie(a.metadata.bi_flags, a.metadata.bi_rw, a.metadata.write_sector,
        a.metadata.size) ==
      tie(b.metadata.bi_flags, b.metadata.bi_rw, b.metadata.write_sector,
        b.metadata.size)) {
    if ((a.data.get() == NULL && b.data.get() != NULL) ||
        (a.data.get() != NULL && b.data.get() == NULL)) {
      return false;
    } else if (a.data.get() == NULL && b.data.get() == NULL) {
      return true;
    }
    if (memcmp(a.data.get(), b.data.get(), a.metadata.size) == 0) {
      return true;
    }
  }
  return false;
}

bool operator!=(const disk_write& a, const disk_write& b) {
  return !(a == b);
}

// Assumes binary file stream provided.
void disk_write::serialize(std::ofstream& fs, const disk_write& dw) {
  const int buf_size = 4096;
  char buffer[buf_size];
  memset(buffer, 0, buf_size);
  // Working all in little endian...

  // Write out the metadata for this log entry.
  unsigned int buf_offset = 0;
  const unsigned long long write_flags = htobe64(dw.metadata.bi_flags);
  const unsigned long long write_rw = htobe64(dw.metadata.bi_rw);
  const unsigned long long write_write_sector = htobe64(dw.metadata.write_sector);
  const unsigned long long write_size = htobe64(dw.metadata.size);
  memcpy(buffer + buf_offset, &write_flags, 8);
  buf_offset += 8;
  memcpy(buffer + buf_offset, &write_rw, 8);
  buf_offset += 8;
  memcpy(buffer + buf_offset, &write_write_sector, 8);
  buf_offset += 8;
  memcpy(buffer + buf_offset, &write_size, 8);
  fs.write(buffer, buf_size);
  if (!fs.good()) {
    std::cerr << "some error writing to file" << std::endl;
    return;
  }

  // Write out the actual data for this log entry. Data could be larger than
  // buf_size so loop through this.
  const char *data = (char *) dw.data.get();
  for (unsigned int i = 0; i < dw.metadata.size; i += buf_size) {
    const unsigned int copy_amount =
      ((i + buf_size) > dw.metadata.size)
        ? (dw.metadata.size - i)
        : buf_size;
    memset(buffer, 0, buf_size);
    memcpy(buffer, data + i, copy_amount);
    fs.write(buffer, buf_size);
    if (!fs.good()) {
      std::cerr << "some error writing to file" << std::endl;
      return;
    }
  }
}

// TODO(ashmrtn): Greatly refactor this so that it is much more flexible and
// complete. Think about removing whitespace between fields and just checking
// for newlines? But then what happens if your data is all newlines?
disk_write disk_write::deserialize(ifstream& is) {
  disk_write_op_meta meta;
  ios prev_format(NULL);
  prev_format.copyfmt(is);
  is >> std::skipws;
  is >> std::hex;
  is >> meta.bi_flags
    >> meta.bi_rw
    >> meta.write_sector
    >> meta.size;

  char nl;
  // Eat single space between size of data and data.
  is.get(nl);
  assert(nl == ' ');
  char *data = new char[meta.size];
  is.read(data, meta.size);
  // Make sure that the meta.size field matches the actual data size in the log.
  is.get(nl);
  assert(nl == '\n');
  is.copyfmt(prev_format);
  disk_write res(meta, data);
  delete[] data;
  return res;
}

/*
 * Output all data for a single object on a single line.
 */
ofstream& operator<<(ofstream& fs, const disk_write& dw) {
  fs << dw.metadata.bi_flags << " "
    << dw.metadata.bi_rw << " "
    << dw.metadata.write_sector << " "
    << dw.metadata.size << " "
    << dw.data;
  return fs;
}

ostream& operator<<(ostream& os, const disk_write& dw) {
  os << std::hex << std::showbase << dw.metadata.bi_rw << std::noshowbase
    << std::dec;
  return os;
}

bool disk_write::has_write_flag() {
  return c_has_write_flag(&metadata);
}

bool disk_write::has_flush_flag() {
  return c_has_flush_flag(&metadata);
}

bool disk_write::has_flush_seq_flag() {
  return c_has_flush_seq_flag(&metadata);
}

bool disk_write::has_FUA_flag() {
  return c_has_FUA_flag(&metadata);
}

void disk_write::set_flush_flag() {
  c_set_flush_flag(&metadata);
}

void disk_write::set_flush_seq_flag() {
  c_set_flush_seq_flag(&metadata);
}

void disk_write::clear_flush_flag() {
  c_clear_flush_flag(&metadata);
}

void disk_write::clear_flush_seq_flag() {
  c_clear_flush_seq_flag(&metadata);
}

shared_ptr<char> disk_write::set_data(const char *d) {
  if (metadata.size > 0 && d != NULL) {
    data = shared_ptr<char>(new char[metadata.size]);
    memcpy(data.get(), d, metadata.size);
  }
  return data;
}

shared_ptr<char> disk_write::get_data() {
  return data;
}

}  // namespace utils
}  // namespace fs_testing
<commit_msg>fixed deserialize/-r flag<commit_after>// Very messy hack to get the defines for different bio operations. Should be
// changed to something more palatable if possible.

#include <endian.h>

#include <cassert>
#include <cstring>

#include <fstream>
#include <ios>
#include <iostream>
#include <memory>
#include <random>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "utils.h"
#include "utils_c.h"

namespace fs_testing {
namespace utils {
using std::endl;
using std::ifstream;
using std::ios;
using std::memcpy;
using std::mt19937;
using std::ofstream;
using std::ostream;
using std::pair;
using std::shared_ptr;
using std::tie;
using std::uniform_int_distribution;
using std::vector;

bool disk_write::is_async_write() {
  return c_is_async_write(&metadata);
}

bool disk_write::is_barrier_write() {
  return c_is_barrier_write(&metadata);
}

bool disk_write::is_meta() {
  return c_is_meta(&metadata);
}

bool disk_write::is_checkpoint() {
  return c_is_checkpoint(&metadata);
}

disk_write::disk_write(const struct disk_write_op_meta& m,
    const char *d) {
  metadata = m;
  if (metadata.size > 0 && d != NULL) {
    data = shared_ptr<char>(new char[metadata.size],
        [](char* c) {delete[] c;});
    memcpy(data.get(), d, metadata.size);
  }
}

disk_write::disk_write(const disk_write& other) {
  metadata = other.metadata;
  data = other.data;
}

void disk_write::operator=(const disk_write& other) {
  metadata = other.metadata;
  data = other.data;
}

bool operator==(const disk_write& a, const disk_write& b) {
  if (tie(a.metadata.bi_flags, a.metadata.bi_rw, a.metadata.write_sector,
        a.metadata.size) ==
      tie(b.metadata.bi_flags, b.metadata.bi_rw, b.metadata.write_sector,
        b.metadata.size)) {
    if ((a.data.get() == NULL && b.data.get() != NULL) ||
        (a.data.get() != NULL && b.data.get() == NULL)) {
      return false;
    } else if (a.data.get() == NULL && b.data.get() == NULL) {
      return true;
    }
    if (memcmp(a.data.get(), b.data.get(), a.metadata.size) == 0) {
      return true;
    }
  }
  return false;
}

bool operator!=(const disk_write& a, const disk_write& b) {
  return !(a == b);
}

// Assumes binary file stream provided.
void disk_write::serialize(std::ofstream& fs, const disk_write& dw) {
  const int buf_size = 4096;
  char buffer[buf_size];
  memset(buffer, 0, buf_size);
  // Working all in little endian...

  // Write out the metadata for this log entry.
  unsigned int buf_offset = 0;
  const unsigned long long write_flags = htobe64(dw.metadata.bi_flags);
  const unsigned long long write_rw = htobe64(dw.metadata.bi_rw);
  const unsigned long long write_write_sector = htobe64(dw.metadata.write_sector);
  const unsigned long long write_size = htobe64(dw.metadata.size);
  memcpy(buffer + buf_offset, &write_flags, 8);
  buf_offset += 8;
  memcpy(buffer + buf_offset, &write_rw, 8);
  buf_offset += 8;
  memcpy(buffer + buf_offset, &write_write_sector, 8);
  buf_offset += 8;
  memcpy(buffer + buf_offset, &write_size, 8);
  buf_offset += 8;
  fs.write(buffer, buf_size);
  if (!fs.good()) {
    std::cerr << "some error writing to file" << std::endl;
    return;
  }

  // Write out the actual data for this log entry. Data could be larger than
  // buf_size so loop through this.
  const char *data = (char *) dw.data.get();
  for (unsigned int i = 0; i < dw.metadata.size; i += buf_size) {
    const unsigned int copy_amount =
      ((i + buf_size) > dw.metadata.size)
        ? (dw.metadata.size - i)
        : buf_size;
    memset(buffer, 0, buf_size);
    memcpy(buffer, data + i, copy_amount);
    fs.write(buffer, buf_size);
    if (!fs.good()) {
      std::cerr << "some error writing to file" << std::endl;
      return;
    }
  }
}

disk_write disk_write::deserialize(ifstream& is) {
  const int buf_size = 4096;
  char buffer[buf_size];
  memset(buffer, 0, buf_size);

  is.read(buffer, buf_size);
  // check if read was successful
  assert(is);

  unsigned int buf_offset = 0;
  unsigned long long write_flags, write_rw, write_write_sector, write_size;
  memcpy(&write_flags, buffer + buf_offset, 8);
  buf_offset += 8;
  memcpy(&write_rw, buffer + buf_offset, 8);
  buf_offset += 8;
  memcpy(&write_write_sector, buffer + buf_offset, 8);
  buf_offset += 8;
  memcpy(&write_size, buffer + buf_offset, 8);
  buf_offset += 8;

  disk_write_op_meta meta;

  meta.bi_flags = be64toh(write_flags);
  meta.bi_rw = be64toh(write_rw);
  meta.write_sector = be64toh(write_write_sector);
  meta.size = be64toh(write_size);

  char *data = new char[meta.size];
  for (unsigned int i = 0; i < meta.size; i += buf_size) {
    const unsigned int read_amount =
      ((i + buf_size) > meta.size)
        ? (meta.size - i)
        : buf_size;
    is.read(buffer, buf_size);
    // check if read was successful
    assert(is);
    memcpy(data + i, buffer, read_amount);
  }

  disk_write res(meta, data);
  delete[] data;
  return res;
}

/*
 * Output all data for a single object on a single line.
 */
ofstream& operator<<(ofstream& fs, const disk_write& dw) {
  fs << dw.metadata.bi_flags << " "
    << dw.metadata.bi_rw << " "
    << dw.metadata.write_sector << " "
    << dw.metadata.size << " "
    << dw.data;
  return fs;
}

ostream& operator<<(ostream& os, const disk_write& dw) {
  os << std::hex << std::showbase << dw.metadata.bi_rw << std::noshowbase
    << std::dec;
  return os;
}

bool disk_write::has_write_flag() {
  return c_has_write_flag(&metadata);
}

bool disk_write::has_flush_flag() {
  return c_has_flush_flag(&metadata);
}

bool disk_write::has_flush_seq_flag() {
  return c_has_flush_seq_flag(&metadata);
}

bool disk_write::has_FUA_flag() {
  return c_has_FUA_flag(&metadata);
}

void disk_write::set_flush_flag() {
  c_set_flush_flag(&metadata);
}

void disk_write::set_flush_seq_flag() {
  c_set_flush_seq_flag(&metadata);
}

void disk_write::clear_flush_flag() {
  c_clear_flush_flag(&metadata);
}

void disk_write::clear_flush_seq_flag() {
  c_clear_flush_seq_flag(&metadata);
}

shared_ptr<char> disk_write::set_data(const char *d) {
  if (metadata.size > 0 && d != NULL) {
    data = shared_ptr<char>(new char[metadata.size]);
    memcpy(data.get(), d, metadata.size);
  }
  return data;
}

shared_ptr<char> disk_write::get_data() {
  return data;
}

}  // namespace utils
}  // namespace fs_testing
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.4  2003/05/16 21:36:55  knoaman
 * Memory manager implementation: Modify constructors to pass in the memory manager.
 *
 * Revision 1.3  2002/11/04 15:00:21  tng
 * C++ Namespace Support.
 *
 * Revision 1.2  2002/02/20 18:17:01  tng
 * [Bug 5977] Warnings on generating apiDocs.
 *
 * Revision 1.1.1.1  2002/02/01 22:21:50  peiyongz
 * sane_include
 *
 * Revision 1.6  2000/12/14 18:49:54  tng
 * Fix API document generation warning: "Warning: end of member group without matching begin"
 *
 * Revision 1.5  2000/02/24 20:00:22  abagchi
 * Swat for removing Log from API docs
 *
 * Revision 1.4  2000/02/15 23:59:06  roddey
 * More updated documentation of Framework classes.
 *
 * Revision 1.3  2000/02/15 01:21:30  roddey
 * Some initial documentation improvements. More to come...
 *
 * Revision 1.2  2000/02/06 07:47:46  rahulj
 * Year 2K copyright swat.
 *
 * Revision 1.1  2000/01/12 00:13:26  roddey
 * These were moved from internal/ to framework/, which was something that should have
 * happened long ago. They are really framework type of classes.
 *
 * Revision 1.1.1.1  1999/11/09 01:08:10  twl
 * Initial checkin
 *
 * Revision 1.2  1999/11/08 20:44:43  rahul
 * Swat for adding in Product name and CVS comment log variable.
 *
 */

#if !defined(MEMBUFINPUTSOURCE_HPP)
#define MEMBUFINPUTSOURCE_HPP

#include <xercesc/sax/InputSource.hpp>

XERCES_CPP_NAMESPACE_BEGIN

class BinInputStream;

/**
 *  This class is a derivative of the standard InputSource class. It provides
 *  for the parser access to data stored in a memory buffer. The type of
 *  buffer and its host specific attributes are of little concern here. The
 *  only real requirement is that the memory be readable by the current
 *  process.
 *
 *  Note that the memory buffer size is expressed in bytes, not in
 *  characters. If you pass it text data, you must account for the bytes
 *  per character when indicating the buffer size.
 *
 *  As with all InputSource derivatives. The primary objective of an input
 *  source is to create an input stream via which the parser can spool in
 *  data from the referenced source. In this case, there are two options
 *  available.
 *
 *  The passed buffer can be adopted or merely referenced. If it is adopted,
 *  then it must be dynamically allocated and will be destroyed when the
 *  input source is destroyed (no reference counting!.) If not adopted, the
 *  caller must insure that it remains valid until the input source object
 *  is destroyed.
 *
 *  The other option indicates whether each stream created for this input
 *  source should get its own copy of the data, or whether it should just
 *  stream the data directly from this object's copy of the data. The same
 *  rules apply here, in that the buffer must either be copied by the
 *  stream or it must remain valid until the stream is destroyed.
 */
class XMLPARSER_EXPORT MemBufInputSource : public InputSource
{
public :
    // -----------------------------------------------------------------------
    //  Constructors and Destructor
    // -----------------------------------------------------------------------

    /** @name Constructors */
    //@{

    /**
      * A memory buffer input source is constructed from a buffer of byte
      * data, and the count of bytes in that buffer. The parser will parse
      * from this memory buffer until it has eaten the indicated number of
      * bytes.
      *
      * Note that the system id provided serves two purposes. Firstly it is
      * going to be displayed in error messages as the source of the error.
      * And secondly, any entities which are refered to from this entity
      * via relative paths/URLs will be relative to this fake system id.
      *
      * @param  srcDocBytes     The actual data buffer to be parsed from.
      * @param  byteCount       The count of bytes (not characters, bytes!)
      *                         in the buffer.
      * @param  bufId           A fake system id for the buffer.
      * @param  adoptBuffer     Indicates whether this object should adopt
      *                         the buffer (i.e. make a copy of it) or just
      *                         use it in place.
      */
    MemBufInputSource
    (
        const   XMLByte* const  srcDocBytes
        , const unsigned int    byteCount
        , const XMLCh* const    bufId
        , const bool            adoptBuffer// = false
        , MemoryManager* const  manager = XMLPlatformUtils::fgMemoryManager
    );

    /**
      * This constructor is identical to the previous one, except that it takes
      * the fake system id in local code page form and transcodes it internally.
      */
    MemBufInputSource
    (
        const   XMLByte* const  srcDocBytes
        , const unsigned int    byteCount
        , const char* const     bufId
        , const bool            adoptBuffer = false
        , MemoryManager* const  manager = XMLPlatformUtils::fgMemoryManager
    );
    //@}

    /** @name Destructor */
    //@{
    /**
      * If the buffer was adopted, the copy made during construction is deleted
      * at this point.
      */
    ~MemBufInputSource();
    //@}

    // -----------------------------------------------------------------------
    //  Virtual input source interface
    // -----------------------------------------------------------------------

    /** @name Virtual methods */
    //@{

    /**
      * This method will return a binary input stream derivative that will
      * parse from the memory buffer. If setCopyBufToStream() has been set,
      * then the stream will make its own copy. Otherwise, it will use the
      * buffer as is (in which case it must remain valid until the stream
      * is no longer in use, i.e. the parse completes.)
      *
      * @return A dynamically allocated binary input stream derivative that
      *         can parse from the memory buffer.
      */
    BinInputStream* makeStream() const;

    //@}

    // -----------------------------------------------------------------------
    //  Setter methods
    // -----------------------------------------------------------------------

    /** @name Setter methods */

    //@{

    /**
      * By default, for safety's sake, each newly created stream from this
      * input source will make its own copy of the buffer to stream from. This
      * avoids having to deal with aliasing of the buffer for simple work. But,
      * for higher performance applications or for large buffers, this is
      * obviously not optimal.
      *
      * In such cases, you can call this method to turn off that default
      * action. Once turned off, the streams will just get a pointer to the
      * buffer and parse directly from that. In this case, you must insure that
      * the buffer remains valid for as long as any parse events are still
      * using it.
      *
      * @param  newState    The new boolean flag state to set.
      */
    void setCopyBufToStream(const bool newState);

    //@}

private :
    // -----------------------------------------------------------------------
    //  Private data members
    //
    //  fAdopted
    //      Indicates whether the buffer is adopted or not. If so, then it
    //      is destroyed when the input source is destroyed.
    //
    //  fByteCount
    //      The size of the source document.
    //
    //  fCopyBufToStream
    //      This defaults to true (the safe option), which causes it to
    //      give a copy of the buffer to any streams it creates. If you set
    //      it to false, it will allow the streams to just reference the
    //      buffer (in which case this input source must stay alive as long
    //      as the buffer is in use by the stream.)
    //
    //  fSrcBytes
    //      The source memory buffer that is being spooled from. Whether it
    //      belongs to the this input source or not is controlled by the
    //      fAdopted flag.
    // -----------------------------------------------------------------------
    bool            fAdopted;
    unsigned int    fByteCount;
    bool            fCopyBufToStream;
    const XMLByte*  fSrcBytes;
};

inline void MemBufInputSource::setCopyBufToStream(const bool newState)
{
    fCopyBufToStream = newState;
}

XERCES_CPP_NAMESPACE_END

#endif
<commit_msg>Allow default value<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.5  2003/07/30 14:48:38  peiyongz
 * Allow default value
 *
 * Revision 1.4  2003/05/16 21:36:55  knoaman
 * Memory manager implementation: Modify constructors to pass in the memory manager.
 *
 * Revision 1.3  2002/11/04 15:00:21  tng
 * C++ Namespace Support.
 *
 * Revision 1.2  2002/02/20 18:17:01  tng
 * [Bug 5977] Warnings on generating apiDocs.
 *
 * Revision 1.1.1.1  2002/02/01 22:21:50  peiyongz
 * sane_include
 *
 * Revision 1.6  2000/12/14 18:49:54  tng
 * Fix API document generation warning: "Warning: end of member group without matching begin"
 *
 * Revision 1.5  2000/02/24 20:00:22  abagchi
 * Swat for removing Log from API docs
 *
 * Revision 1.4  2000/02/15 23:59:06  roddey
 * More updated documentation of Framework classes.
 *
 * Revision 1.3  2000/02/15 01:21:30  roddey
 * Some initial documentation improvements. More to come...
 *
 * Revision 1.2  2000/02/06 07:47:46  rahulj
 * Year 2K copyright swat.
 *
 * Revision 1.1  2000/01/12 00:13:26  roddey
 * These were moved from internal/ to framework/, which was something that should have
 * happened long ago. They are really framework type of classes.
 *
 * Revision 1.1.1.1  1999/11/09 01:08:10  twl
 * Initial checkin
 *
 * Revision 1.2  1999/11/08 20:44:43  rahul
 * Swat for adding in Product name and CVS comment log variable.
 *
 */

#if !defined(MEMBUFINPUTSOURCE_HPP)
#define MEMBUFINPUTSOURCE_HPP

#include <xercesc/sax/InputSource.hpp>

XERCES_CPP_NAMESPACE_BEGIN

class BinInputStream;

/**
 *  This class is a derivative of the standard InputSource class. It provides
 *  for the parser access to data stored in a memory buffer. The type of
 *  buffer and its host specific attributes are of little concern here. The
 *  only real requirement is that the memory be readable by the current
 *  process.
 *
 *  Note that the memory buffer size is expressed in bytes, not in
 *  characters. If you pass it text data, you must account for the bytes
 *  per character when indicating the buffer size.
 *
 *  As with all InputSource derivatives. The primary objective of an input
 *  source is to create an input stream via which the parser can spool in
 *  data from the referenced source. In this case, there are two options
 *  available.
 *
 *  The passed buffer can be adopted or merely referenced. If it is adopted,
 *  then it must be dynamically allocated and will be destroyed when the
 *  input source is destroyed (no reference counting!.) If not adopted, the
 *  caller must insure that it remains valid until the input source object
 *  is destroyed.
 *
 *  The other option indicates whether each stream created for this input
 *  source should get its own copy of the data, or whether it should just
 *  stream the data directly from this object's copy of the data. The same
 *  rules apply here, in that the buffer must either be copied by the
 *  stream or it must remain valid until the stream is destroyed.
 */
class XMLPARSER_EXPORT MemBufInputSource : public InputSource
{
public :
    // -----------------------------------------------------------------------
    //  Constructors and Destructor
    // -----------------------------------------------------------------------

    /** @name Constructors */
    //@{

    /**
      * A memory buffer input source is constructed from a buffer of byte
      * data, and the count of bytes in that buffer. The parser will parse
      * from this memory buffer until it has eaten the indicated number of
      * bytes.
      *
      * Note that the system id provided serves two purposes. Firstly it is
      * going to be displayed in error messages as the source of the error.
      * And secondly, any entities which are refered to from this entity
      * via relative paths/URLs will be relative to this fake system id.
      *
      * @param  srcDocBytes     The actual data buffer to be parsed from.
      * @param  byteCount       The count of bytes (not characters, bytes!)
      *                         in the buffer.
      * @param  bufId           A fake system id for the buffer.
      * @param  adoptBuffer     Indicates whether this object should adopt
      *                         the buffer (i.e. make a copy of it) or just
      *                         use it in place.
      */
    MemBufInputSource
    (
        const   XMLByte* const  srcDocBytes
        , const unsigned int    byteCount
        , const XMLCh* const    bufId
        , const bool            adoptBuffer = false
        , MemoryManager* const  manager = XMLPlatformUtils::fgMemoryManager
    );

    /**
      * This constructor is identical to the previous one, except that it takes
      * the fake system id in local code page form and transcodes it internally.
      */
    MemBufInputSource
    (
        const   XMLByte* const  srcDocBytes
        , const unsigned int    byteCount
        , const char* const     bufId
        , const bool            adoptBuffer = false
        , MemoryManager* const  manager = XMLPlatformUtils::fgMemoryManager
    );
    //@}

    /** @name Destructor */
    //@{
    /**
      * If the buffer was adopted, the copy made during construction is deleted
      * at this point.
      */
    ~MemBufInputSource();
    //@}

    // -----------------------------------------------------------------------
    //  Virtual input source interface
    // -----------------------------------------------------------------------

    /** @name Virtual methods */
    //@{

    /**
      * This method will return a binary input stream derivative that will
      * parse from the memory buffer. If setCopyBufToStream() has been set,
      * then the stream will make its own copy. Otherwise, it will use the
      * buffer as is (in which case it must remain valid until the stream
      * is no longer in use, i.e. the parse completes.)
      *
      * @return A dynamically allocated binary input stream derivative that
      *         can parse from the memory buffer.
      */
    BinInputStream* makeStream() const;

    //@}

    // -----------------------------------------------------------------------
    //  Setter methods
    // -----------------------------------------------------------------------

    /** @name Setter methods */

    //@{

    /**
      * By default, for safety's sake, each newly created stream from this
      * input source will make its own copy of the buffer to stream from. This
      * avoids having to deal with aliasing of the buffer for simple work. But,
      * for higher performance applications or for large buffers, this is
      * obviously not optimal.
      *
      * In such cases, you can call this method to turn off that default
      * action. Once turned off, the streams will just get a pointer to the
      * buffer and parse directly from that. In this case, you must insure that
      * the buffer remains valid for as long as any parse events are still
      * using it.
      *
      * @param  newState    The new boolean flag state to set.
      */
    void setCopyBufToStream(const bool newState);

    //@}

private :
    // -----------------------------------------------------------------------
    //  Private data members
    //
    //  fAdopted
    //      Indicates whether the buffer is adopted or not. If so, then it
    //      is destroyed when the input source is destroyed.
    //
    //  fByteCount
    //      The size of the source document.
    //
    //  fCopyBufToStream
    //      This defaults to true (the safe option), which causes it to
    //      give a copy of the buffer to any streams it creates. If you set
    //      it to false, it will allow the streams to just reference the
    //      buffer (in which case this input source must stay alive as long
    //      as the buffer is in use by the stream.)
    //
    //  fSrcBytes
    //      The source memory buffer that is being spooled from. Whether it
    //      belongs to the this input source or not is controlled by the
    //      fAdopted flag.
    // -----------------------------------------------------------------------
    bool            fAdopted;
    unsigned int    fByteCount;
    bool            fCopyBufToStream;
    const XMLByte*  fSrcBytes;
};

inline void MemBufInputSource::setCopyBufToStream(const bool newState)
{
    fCopyBufToStream = newState;
}

XERCES_CPP_NAMESPACE_END

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/net/http/HttpHeader.h"
#include "db/util/StringTools.h"

using namespace std;
using namespace db::net::http;
using namespace db::util;

// define CRLF
const char* HttpHeader::CRLF = "\r\n";

HttpHeader::HttpHeader()
{
}

HttpHeader::~HttpHeader()
{
   for(map<const char*, string, FieldComparator>::iterator i =
       mFields.begin(); i != mFields.end(); i++)
   {
      free((char*)i->first);
   }
}

bool HttpHeader::parseStartLine(const char* str, unsigned int length)
{
   // no start line
   return true;
}

void HttpHeader::getStartLine(std::string& line)
{
   // no start line
   line.erase();
}

void HttpHeader::setField(const char* name, long long value)
{
   char temp[25];
   sprintf(temp, "%lli", value);
   setField(name, temp);
}

void HttpHeader::setField(const char* name, const std::string& value)
{
   // clear old field
   map<const char*, std::string, FieldComparator>::iterator i =
      mFields.find(name);
   if(i != mFields.end())
   {
      free((char*)i->first);
      mFields.erase(i);
   }

   // set new field
   mFields.insert(make_pair(strdup(name), value));
}

void HttpHeader::addField(const char* name, const std::string& value)
{
   // get existing value
   string existing;
   getField(name, existing);

   // append new value
   existing.append(", ");
   existing.append(value);
   setField(name, existing);
}

void HttpHeader::removeField(const char* name)
{
   // erase field
   mFields.erase(name);
}

void HttpHeader::clearFields()
{
   for(map<const char*, string, FieldComparator>::iterator i =
       mFields.begin(); i != mFields.end(); i++)
   {
      free((char*)i->first);
   }

   mFields.clear();
}

bool HttpHeader::getField(const char* name, long long& value)
{
   bool rval = false;

   string str;
   if(getField(name, str))
   {
      char* endptr = NULL;
      value = strtoll(str.c_str(), &endptr, 10);
      rval = endptr != str.c_str() && *endptr == '\0';
   }

   return rval;
}

bool HttpHeader::getField(const char* name, string& value)
{
   bool rval = false;

   // find field entry
   map<const char*, string, FieldComparator>::iterator i =
      mFields.find(name);
   if(i != mFields.end())
   {
      // get value
      value = i->second;
      rval = true;
   }

   return rval;
}

bool HttpHeader::hasField(const char* name)
{
   bool rval = false;

   // find field entry
   map<const char*, string, FieldComparator>::iterator i =
      mFields.find(name);
   if(i != mFields.end())
   {
      rval = true;
   }

   return rval;
}

bool HttpHeader::parse(const string& str)
{
   bool rval = false;

   // clear fields
   clearFields();

   bool startLine = true;
   const char* start = str.c_str();
   char* cr;
   char* colon;
   while((cr = strchr(start, '\r')) != NULL)
   {
      // look for CRLF
      if(strchr(cr, '\n') == cr + 1)
      {
         if(startLine)
         {
            rval = parseStartLine(start, cr - start);
            startLine = false;
         }
         else
         {
            // found a CRLF, now find colon
            if((colon = strchr(start, ':')) != NULL && colon < cr)
            {
               // get field name
               char* name = (char*)malloc((colon - start) + 1);
               memcpy(name, start, colon - start);
               name[colon - start] = 0;

               // skip whitespace
               colon++;
               for(; *colon == ' ' && colon < cr; colon++);

               // get field value
               char value[cr - colon + 1];
               strncpy(value, colon, cr - colon);
               value[(cr - colon)] = 0;

               // clear old field
               map<const char*, std::string, FieldComparator>::iterator i =
                  mFields.find(name);
               if(i != mFields.end())
               {
                  free((char*)i->first);
                  mFields.erase(i);
               }

               // set field
               mFields.insert(make_pair(name, value));
            }
         }

         start = cr + 2;
      }
      else
      {
         start = cr + 1;
      }
   }

   return rval;
}

string& HttpHeader::toString(string& str)
{
   str.erase();

   // append the start line, if one exists, and CRLF
   getStartLine(str);
   if(str.length() > 0)
   {
      str.append(CRLF);
   }

   // append all fields
   for(map<const char*, string, FieldComparator>::iterator i =
       mFields.begin(); i != mFields.end(); i++)
   {
      // get field name and bicapitalize it
      char name[strlen(i->first) + 1];
      strcpy(name, i->first);
      biCapitalize(name);

      // append name and value
      str.append(name);
      str.append(": ");
      str.append(i->second);
      str.append(CRLF);
   }

   // add CRLF
   str.append(CRLF);

   return str;
}

void HttpHeader::setDate(Date* date)
{
   // get GMT time zone
   TimeZone gmt = TimeZone::getTimeZone("GMT");
   string str;
   string format = "%a, %d %b %Y %H:%M:%S GMT";

   if(date == NULL)
   {
      // get current date
      Date now;
      now.format(str, format, "c", &gmt);
   }
   else
   {
      date->format(str, format, "c", &gmt);
   }

   // set date field
   setField("Date", str);
}

bool HttpHeader::getDate(Date& date)
{
   bool rval = false;

   string str;
   if(getField("Date", str))
   {
      // get GMT time zone
      TimeZone gmt = TimeZone::getTimeZone("GMT");
      rval = date.parse(str, "%a, %d %b %Y %H:%M:%S", "c", &gmt);
   }

   return rval;
}

void HttpHeader::biCapitalize(char* name)
{
   // 97 = 'a', 122 = 'z'
   if(*name > 96 && *name < 123)
   {
      // capitalize letter
      *name -= 32;
   }

   // capitalize letters after hyphens, decapitalize other letters
   name++;
   for(; *name != 0; name++)
   {
      if(*(name - 1) == '-')
      {
         if(*name > 96 && *name < 123)
         {
            // capitalize
            *name -= 32;
         }
      }
      else
      {
         // 65 = 'A', 90 = 'Z'
         if(*name > 64 && *name < 90)
         {
            // decapitalize
            *name += 32;
         }
      }
   }
}
<commit_msg>Fixed bug in addField() where if an existing header was not found, a comma was still prepended.<commit_after>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/net/http/HttpHeader.h"
#include "db/util/StringTools.h"

using namespace std;
using namespace db::net::http;
using namespace db::util;

// define CRLF
const char* HttpHeader::CRLF = "\r\n";

HttpHeader::HttpHeader()
{
}

HttpHeader::~HttpHeader()
{
   for(map<const char*, string, FieldComparator>::iterator i =
       mFields.begin(); i != mFields.end(); i++)
   {
      free((char*)i->first);
   }
}

bool HttpHeader::parseStartLine(const char* str, unsigned int length)
{
   // no start line
   return true;
}

void HttpHeader::getStartLine(std::string& line)
{
   // no start line
   line.erase();
}

void HttpHeader::setField(const char* name, long long value)
{
   char temp[25];
   sprintf(temp, "%lli", value);
   setField(name, temp);
}

void HttpHeader::setField(const char* name, const std::string& value)
{
   // clear old field
   map<const char*, std::string, FieldComparator>::iterator i =
      mFields.find(name);
   if(i != mFields.end())
   {
      free((char*)i->first);
      mFields.erase(i);
   }

   // set new field
   mFields.insert(make_pair(strdup(name), value));
}

void HttpHeader::addField(const char* name, const std::string& value)
{
   // get existing value
   string existing;
   if(getField(name, existing))
   {
      // append to existing value
      existing.append(", ");
   }

   existing.append(value);
   setField(name, existing);
}

void HttpHeader::removeField(const char* name)
{
   // erase field
   mFields.erase(name);
}

void HttpHeader::clearFields()
{
   for(map<const char*, string, FieldComparator>::iterator i =
       mFields.begin(); i != mFields.end(); i++)
   {
      free((char*)i->first);
   }

   mFields.clear();
}

bool HttpHeader::getField(const char* name, long long& value)
{
   bool rval = false;

   string str;
   if(getField(name, str))
   {
      char* endptr = NULL;
      value = strtoll(str.c_str(), &endptr, 10);
      rval = endptr != str.c_str() && *endptr == '\0';
   }

   return rval;
}

bool HttpHeader::getField(const char* name, string& value)
{
   bool rval = false;

   // find field entry
   map<const char*, string, FieldComparator>::iterator i =
      mFields.find(name);
   if(i != mFields.end())
   {
      // get value
      value = i->second;
      rval = true;
   }

   return rval;
}

bool HttpHeader::hasField(const char* name)
{
   bool rval = false;

   // find field entry
   map<const char*, string, FieldComparator>::iterator i =
      mFields.find(name);
   if(i != mFields.end())
   {
      rval = true;
   }

   return rval;
}

bool HttpHeader::parse(const string& str)
{
   bool rval = false;

   // clear fields
   clearFields();

   bool startLine = true;
   const char* start = str.c_str();
   char* cr;
   char* colon;
   while((cr = strchr(start, '\r')) != NULL)
   {
      // look for CRLF
      if(strchr(cr, '\n') == cr + 1)
      {
         if(startLine)
         {
            rval = parseStartLine(start, cr - start);
            startLine = false;
         }
         else
         {
            // found a CRLF, now find colon
            if((colon = strchr(start, ':')) != NULL && colon < cr)
            {
               // get field name
               char* name = (char*)malloc((colon - start) + 1);
               memcpy(name, start, colon - start);
               name[colon - start] = 0;

               // skip whitespace
               colon++;
               for(; *colon == ' ' && colon < cr; colon++);

               // get field value
               char value[cr - colon + 1];
               strncpy(value, colon, cr - colon);
               value[(cr - colon)] = 0;

               // clear old field
               map<const char*, std::string, FieldComparator>::iterator i =
                  mFields.find(name);
               if(i != mFields.end())
               {
                  free((char*)i->first);
                  mFields.erase(i);
               }

               // set field
               mFields.insert(make_pair(name, value));
            }
         }

         start = cr + 2;
      }
      else
      {
         start = cr + 1;
      }
   }

   return rval;
}

string& HttpHeader::toString(string& str)
{
   str.erase();

   // append the start line, if one exists, and CRLF
   getStartLine(str);
   if(str.length() > 0)
   {
      str.append(CRLF);
   }

   // append all fields
   for(map<const char*, string, FieldComparator>::iterator i =
       mFields.begin(); i != mFields.end(); i++)
   {
      // get field name and bicapitalize it
      char name[strlen(i->first) + 1];
      strcpy(name, i->first);
      biCapitalize(name);

      // append name and value
      str.append(name);
      str.append(": ");
      str.append(i->second);
      str.append(CRLF);
   }

   // add CRLF
   str.append(CRLF);

   return str;
}

void HttpHeader::setDate(Date* date)
{
   // get GMT time zone
   TimeZone gmt = TimeZone::getTimeZone("GMT");
   string str;
   string format = "%a, %d %b %Y %H:%M:%S GMT";

   if(date == NULL)
   {
      // get current date
      Date now;
      now.format(str, format, "c", &gmt);
   }
   else
   {
      date->format(str, format, "c", &gmt);
   }

   // set date field
   setField("Date", str);
}

bool HttpHeader::getDate(Date& date)
{
   bool rval = false;

   string str;
   if(getField("Date", str))
   {
      // get GMT time zone
      TimeZone gmt = TimeZone::getTimeZone("GMT");
      rval = date.parse(str, "%a, %d %b %Y %H:%M:%S", "c", &gmt);
   }

   return rval;
}

void HttpHeader::biCapitalize(char* name)
{
   // 97 = 'a', 122 = 'z'
   if(*name > 96 && *name < 123)
   {
      // capitalize letter
      *name -= 32;
   }

   // capitalize letters after hyphens, decapitalize other letters
   name++;
   for(; *name != 0; name++)
   {
      if(*(name - 1) == '-')
      {
         if(*name > 96 && *name < 123)
         {
            // capitalize
            *name -= 32;
         }
      }
      else
      {
         // 65 = 'A', 90 = 'Z'
         if(*name > 64 && *name < 90)
         {
            // decapitalize
            *name += 32;
         }
      }
   }
}
<|endoftext|>


<commit_before>// $Id$

/***********************************************************************
Moses - factored phrase-based language decoder
Copyright (C) 2006 University of Edinburgh

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
***********************************************************************/

#include "assert.h"
#include <algorithm>
#include <sstream>
#include <string>
#include "memory.h"
#include "FactorCollection.h"
#include "Phrase.h"
#include "Util.h"

using namespace std;

// std::vector<mempool*> Phrase::s_memPool;

Phrase::Phrase(const Phrase &copy)
:m_direction(copy.m_direction)
,m_phraseSize(copy.m_phraseSize)
,m_arraySize(copy.m_arraySize)
,m_memPoolIndex(copy.m_memPoolIndex)
{
	m_factorArray = (FactorArray*) s_memPool[m_memPoolIndex]->alloc();
	memcpy(m_factorArray, copy.m_factorArray, m_phraseSize * sizeof(FactorArray));
}

Phrase::Phrase(FactorDirection direction)
	: m_direction(direction)
	, m_phraseSize(0)
	, m_arraySize(ARRAY_SIZE_INCR)
	, m_memPoolIndex(0)
{
	m_factorArray = (FactorArray*) s_memPool[m_memPoolIndex]->alloc();
}

Phrase::Phrase(FactorDirection direction, const vector< const Word* > &mergeWords)
:m_direction(direction)
,m_phraseSize(mergeWords.size())
{
	m_memPoolIndex	= (m_phraseSize + ARRAY_SIZE_INCR - 1) / ARRAY_SIZE_INCR  - 1;
	m_arraySize 		= (m_memPoolIndex + 1) * ARRAY_SIZE_INCR;
	m_factorArray 	= (FactorArray*) s_memPool[m_memPoolIndex]->alloc();

	for (size_t currPos = 0 ; currPos < m_phraseSize ; currPos++)
	{
		FactorArray &thisWord				= m_factorArray[currPos];
		const Word &mergeWord				= *mergeWords[currPos];

		for (unsigned int currFactor = 0 ; currFactor < NUM_FACTORS ; currFactor++)
		{
			FactorType factorType = static_cast<FactorType>(currFactor);
			thisWord[currFactor] = mergeWord.GetFactor(factorType);
		}
	}
}

Phrase::~Phrase()
{
	s_memPool[m_memPoolIndex]->free((char*)m_factorArray);
}

void Phrase::MergeFactors(const Phrase &copy)
{
	assert(GetSize() == copy.GetSize());
	size_t size = GetSize();
	for (size_t currPos = 0 ; currPos < size ; currPos++)
	{
		for (unsigned int currFactor = 0 ; currFactor < NUM_FACTORS ; currFactor++)
		{
			FactorType factorType = static_cast<FactorType>(currFactor);
			const Factor *factor = copy.GetFactor(currPos, factorType);
			if (factor != NULL)
				SetFactor(currPos, factorType, factor);
		}
	}
}

Phrase Phrase::GetSubString(const WordsRange &wordsRange) const
{
	Phrase retPhrase(m_direction);

	for (size_t currPos = wordsRange.GetStartPos() ; currPos <= wordsRange.GetEndPos() ; currPos++)
	{
		FactorArray &newWord = retPhrase.AddWord();
		Word::Copy(newWord, GetFactorArray(currPos));
	}

	return retPhrase;
}

std::string Phrase::GetStringRep(const WordsRange &wordsRange)
{
	std::stringstream phrase_string("");
	for (size_t currPos = wordsRange.GetStartPos() ; currPos <= wordsRange.GetEndPos() ; currPos++)
	{
		phrase_string << " " << Word::ToString(GetFactorArray(currPos));
	}
	return phrase_string.str();
}

FactorArray &Phrase::AddWord()
{
	if ((m_phraseSize+1) % ARRAY_SIZE_INCR == 0)
	{ // need to expand array
		FactorArray *newArray = (FactorArray*) s_memPool[m_memPoolIndex+1]->alloc();
		memcpy(newArray, m_factorArray, m_phraseSize * sizeof(FactorArray));
		s_memPool[m_memPoolIndex]->free((char*)m_factorArray);

		m_memPoolIndex++;
		m_arraySize += ARRAY_SIZE_INCR;
		m_factorArray = newArray;
	}

	FactorArray &factorArray = m_factorArray[m_phraseSize];
	Word::Initialize(factorArray);

	m_phraseSize++;

	return factorArray;
}

vector< vector<string> > Phrase::Parse(const std::string &phraseString)
{
		// parse
	vector< vector<string> > phraseVector;
	vector<string> annotatedWordVector = Tokenize(phraseString);
	// KOMMA|none ART|Def.Z NN|Neut.NotGen.Sg VVFIN|none
	//		to
	// "KOMMA|none" "ART|Def.Z" "NN|Neut.NotGen.Sg" "VVFIN|none"

	for (size_t phrasePos = 0 ; phrasePos < annotatedWordVector.size() ; phrasePos++)
	{
		string &annotatedWord = annotatedWordVector[phrasePos];
		vector<string> factorStrVector = Tokenize(annotatedWord, "|");
		// KOMMA|none
		//    to
		// "KOMMA" "none"
		phraseVector.push_back(factorStrVector);
	}
	return phraseVector;
}

void Phrase::CreateFromString(const std::vector<FactorType> &factorOrder
															, const vector< vector<string> > &phraseVector
															, FactorCollection &factorCollection)
{
	for (size_t phrasePos = 0 ; phrasePos < phraseVector.size() ; phrasePos++)
	{
		// add word this phrase
		FactorArray &factorArray = AddWord();
		for (size_t currFactorIndex= 0 ; currFactorIndex < factorOrder.size() ; currFactorIndex++)
		{
			FactorType factorType = factorOrder[currFactorIndex];
			const string &factorStr = phraseVector[phrasePos][currFactorIndex];
			const Factor *factor = factorCollection.AddFactor(m_direction, factorType, factorStr);
			factorArray[factorType] = factor;
		}
	}
}

void Phrase::CreateFromString(const std::vector<FactorType> &factorOrder
															, const string &phraseString
															, FactorCollection &factorCollection)
{
	vector< vector<string> > phraseVector = Parse(phraseString);
	CreateFromString(factorOrder, phraseVector, factorCollection);
}

bool Phrase::operator < (const Phrase &compare) const
{
#ifdef min
#undef min
#endif
	size_t thisSize			= GetSize()
				,compareSize	= compare.GetSize();

	// decide by using length. quick decision
	if (thisSize != compareSize)
	{
		return thisSize < compareSize;
	}
	else
	{
		size_t minSize = std::min( thisSize , compareSize );

		// taken from word.Compare()
		for (size_t i = 0 ; i < NUM_FACTORS ; i++)
		{
			FactorType factorType = static_cast<FactorType>(i);

			for (size_t currPos = 0 ; currPos < minSize ; currPos++)
			{
				const Factor *thisFactor		= GetFactor(currPos, factorType)
										,*compareFactor	= compare.GetFactor(currPos, factorType);

				if (thisFactor != NULL && compareFactor != NULL)
				{
					const int result = thisFactor->Compare(*compareFactor);
					if (result == 0)
					{
						continue;
					}
					else
					{
						return (result < 0);
					}
				}
			}
		}

		// identical
		return false;
	}
}

bool Phrase::Contains(const vector< vector<string> > &subPhraseVector
										, const vector<FactorType> &inputFactor) const
{
	const size_t subSize = subPhraseVector.size()
							,thisSize= GetSize();
	if (subSize > thisSize)
		return false;

	// try to match word-for-word
	for (size_t currStartPos = 0 ; currStartPos < (thisSize - subSize + 1) ; currStartPos++)
	{
		bool match = true;

		for (size_t currFactorIndex = 0 ; currFactorIndex < inputFactor.size() ; currFactorIndex++)
		{
			FactorType factorType = inputFactor[currFactorIndex];
			for (size_t currSubPos = 0 ; currSubPos < subSize ; currSubPos++)
			{
				size_t currThisPos = currSubPos + currStartPos;
				const string &subStr	= subPhraseVector[currSubPos][currFactorIndex]
										,&thisStr	= GetFactor(currThisPos, factorType)->GetString();
				if (subStr != thisStr)
				{
					match = false;
					break;
				}
			}
			if (!match)
				break;
		}

		if (match)
			return true;
	}
	return false;
}

bool Phrase::IsCompatible(const Phrase &inputPhrase) const
{
	if (inputPhrase.GetSize() != GetSize())
	{
		return false;
	}

	const size_t size = GetSize();

	for (size_t currPos = 0 ; currPos < size ; currPos++)
	{
		for (unsigned int currFactor = 0 ; currFactor < NUM_FACTORS ; currFactor++)
		{
			FactorType factorType = static_cast<FactorType>(currFactor);
			const Factor *thisFactor 		= GetFactor(currPos, factorType)
									,*inputFactor	= inputPhrase.GetFactor(currPos, factorType);
			if (thisFactor != NULL && inputFactor != NULL && thisFactor != inputFactor)
				return false;
		}
	}
	return true;

}

void Phrase::InitializeMemPool()
{
	s_memPool.push_back( new mempool(1 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 50000 ));
	s_memPool.push_back( new mempool(2 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 1000 ));
	s_memPool.push_back( new mempool(3 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 1000 ));
	s_memPool.push_back( new mempool(4 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 100 ));
	s_memPool.push_back( new mempool(5 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 10 ));
	s_memPool.push_back( new mempool(6 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 10 ));
	s_memPool.push_back( new mempool(7 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 10 ));

	for (size_t i = 8 ; i < 30 ; ++i)
		s_memPool.push_back( new mempool(i * ARRAY_SIZE_INCR * sizeof(FactorArray) , 2 ));
}

void Phrase::FinalizeMemPool()
{
#if 0
	std::vector<mempool*>::iterator iter;
	for (iter = s_memPool.begin() ; iter != s_memPool.end() ; ++iter)
	{
		delete *iter;
	}
#endif
}

TO_STRING_BODY(Phrase);

// friend
ostream& operator<<(ostream& out, const Phrase& phrase)
{
//	out << "(size " << phrase.GetSize() << ") ";
	for (size_t pos = 0 ; pos < phrase.GetSize() ; pos++)
	{
		const FactorArray &factorArray = phrase.GetFactorArray(pos);
		out << Word::ToString(factorArray);
	}
	return out;
}

<commit_msg>using mem pool. needs to be more finely tweaked to give good results<commit_after>// $Id$

/***********************************************************************
Moses - factored phrase-based language decoder
Copyright (C) 2006 University of Edinburgh

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
***********************************************************************/

#include "assert.h"
#include <algorithm>
#include <sstream>
#include <string>
#include "memory.h"
#include "FactorCollection.h"
#include "Phrase.h"
#include "Util.h"

using namespace std;

std::vector<mempool*> Phrase::s_memPool;

Phrase::Phrase(const Phrase &copy)
:m_direction(copy.m_direction)
,m_phraseSize(copy.m_phraseSize)
,m_arraySize(copy.m_arraySize)
,m_memPoolIndex(copy.m_memPoolIndex)
{
	m_factorArray = (FactorArray*) s_memPool[m_memPoolIndex]->alloc();
	memcpy(m_factorArray, copy.m_factorArray, m_phraseSize * sizeof(FactorArray));
}

Phrase::Phrase(FactorDirection direction)
	: m_direction(direction)
	, m_phraseSize(0)
	, m_arraySize(ARRAY_SIZE_INCR)
	, m_memPoolIndex(0)
{
	m_factorArray = (FactorArray*) s_memPool[m_memPoolIndex]->alloc();
}

Phrase::Phrase(FactorDirection direction, const vector< const Word* > &mergeWords)
:m_direction(direction)
,m_phraseSize(mergeWords.size())
{
	m_memPoolIndex	= (m_phraseSize + ARRAY_SIZE_INCR - 1) / ARRAY_SIZE_INCR  - 1;
	m_arraySize 		= (m_memPoolIndex + 1) * ARRAY_SIZE_INCR;
	m_factorArray 	= (FactorArray*) s_memPool[m_memPoolIndex]->alloc();

	for (size_t currPos = 0 ; currPos < m_phraseSize ; currPos++)
	{
		FactorArray &thisWord				= m_factorArray[currPos];
		const Word &mergeWord				= *mergeWords[currPos];

		for (unsigned int currFactor = 0 ; currFactor < NUM_FACTORS ; currFactor++)
		{
			FactorType factorType = static_cast<FactorType>(currFactor);
			thisWord[currFactor] = mergeWord.GetFactor(factorType);
		}
	}
}

Phrase::~Phrase()
{
	s_memPool[m_memPoolIndex]->free((char*)m_factorArray);
}

void Phrase::MergeFactors(const Phrase &copy)
{
	assert(GetSize() == copy.GetSize());
	size_t size = GetSize();
	for (size_t currPos = 0 ; currPos < size ; currPos++)
	{
		for (unsigned int currFactor = 0 ; currFactor < NUM_FACTORS ; currFactor++)
		{
			FactorType factorType = static_cast<FactorType>(currFactor);
			const Factor *factor = copy.GetFactor(currPos, factorType);
			if (factor != NULL)
				SetFactor(currPos, factorType, factor);
		}
	}
}

Phrase Phrase::GetSubString(const WordsRange &wordsRange) const
{
	Phrase retPhrase(m_direction);

	for (size_t currPos = wordsRange.GetStartPos() ; currPos <= wordsRange.GetEndPos() ; currPos++)
	{
		FactorArray &newWord = retPhrase.AddWord();
		Word::Copy(newWord, GetFactorArray(currPos));
	}

	return retPhrase;
}

std::string Phrase::GetStringRep(const WordsRange &wordsRange)
{
	std::stringstream phrase_string("");
	for (size_t currPos = wordsRange.GetStartPos() ; currPos <= wordsRange.GetEndPos() ; currPos++)
	{
		phrase_string << " " << Word::ToString(GetFactorArray(currPos));
	}
	return phrase_string.str();
}

FactorArray &Phrase::AddWord()
{
	if ((m_phraseSize+1) % ARRAY_SIZE_INCR == 0)
	{ // need to expand array
		FactorArray *newArray = (FactorArray*) s_memPool[m_memPoolIndex+1]->alloc();
		memcpy(newArray, m_factorArray, m_phraseSize * sizeof(FactorArray));
		s_memPool[m_memPoolIndex]->free((char*)m_factorArray);

		m_memPoolIndex++;
		m_arraySize += ARRAY_SIZE_INCR;
		m_factorArray = newArray;
	}

	FactorArray &factorArray = m_factorArray[m_phraseSize];
	Word::Initialize(factorArray);

	m_phraseSize++;

	return factorArray;
}

vector< vector<string> > Phrase::Parse(const std::string &phraseString)
{
		// parse
	vector< vector<string> > phraseVector;
	vector<string> annotatedWordVector = Tokenize(phraseString);
	// KOMMA|none ART|Def.Z NN|Neut.NotGen.Sg VVFIN|none
	//		to
	// "KOMMA|none" "ART|Def.Z" "NN|Neut.NotGen.Sg" "VVFIN|none"

	for (size_t phrasePos = 0 ; phrasePos < annotatedWordVector.size() ; phrasePos++)
	{
		string &annotatedWord = annotatedWordVector[phrasePos];
		vector<string> factorStrVector = Tokenize(annotatedWord, "|");
		// KOMMA|none
		//    to
		// "KOMMA" "none"
		phraseVector.push_back(factorStrVector);
	}
	return phraseVector;
}

void Phrase::CreateFromString(const std::vector<FactorType> &factorOrder
															, const vector< vector<string> > &phraseVector
															, FactorCollection &factorCollection)
{
	for (size_t phrasePos = 0 ; phrasePos < phraseVector.size() ; phrasePos++)
	{
		// add word this phrase
		FactorArray &factorArray = AddWord();
		for (size_t currFactorIndex= 0 ; currFactorIndex < factorOrder.size() ; currFactorIndex++)
		{
			FactorType factorType = factorOrder[currFactorIndex];
			const string &factorStr = phraseVector[phrasePos][currFactorIndex];
			const Factor *factor = factorCollection.AddFactor(m_direction, factorType, factorStr);
			factorArray[factorType] = factor;
		}
	}
}

void Phrase::CreateFromString(const std::vector<FactorType> &factorOrder
															, const string &phraseString
															, FactorCollection &factorCollection)
{
	vector< vector<string> > phraseVector = Parse(phraseString);
	CreateFromString(factorOrder, phraseVector, factorCollection);
}

bool Phrase::operator < (const Phrase &compare) const
{
#ifdef min
#undef min
#endif
	size_t thisSize			= GetSize()
				,compareSize	= compare.GetSize();

	// decide by using length. quick decision
	if (thisSize != compareSize)
	{
		return thisSize < compareSize;
	}
	else
	{
		size_t minSize = std::min( thisSize , compareSize );

		// taken from word.Compare()
		for (size_t i = 0 ; i < NUM_FACTORS ; i++)
		{
			FactorType factorType = static_cast<FactorType>(i);

			for (size_t currPos = 0 ; currPos < minSize ; currPos++)
			{
				const Factor *thisFactor		= GetFactor(currPos, factorType)
										,*compareFactor	= compare.GetFactor(currPos, factorType);

				if (thisFactor != NULL && compareFactor != NULL)
				{
					const int result = thisFactor->Compare(*compareFactor);
					if (result == 0)
					{
						continue;
					}
					else
					{
						return (result < 0);
					}
				}
			}
		}

		// identical
		return false;
	}
}

bool Phrase::Contains(const vector< vector<string> > &subPhraseVector
										, const vector<FactorType> &inputFactor) const
{
	const size_t subSize = subPhraseVector.size()
							,thisSize= GetSize();
	if (subSize > thisSize)
		return false;

	// try to match word-for-word
	for (size_t currStartPos = 0 ; currStartPos < (thisSize - subSize + 1) ; currStartPos++)
	{
		bool match = true;

		for (size_t currFactorIndex = 0 ; currFactorIndex < inputFactor.size() ; currFactorIndex++)
		{
			FactorType factorType = inputFactor[currFactorIndex];
			for (size_t currSubPos = 0 ; currSubPos < subSize ; currSubPos++)
			{
				size_t currThisPos = currSubPos + currStartPos;
				const string &subStr	= subPhraseVector[currSubPos][currFactorIndex]
										,&thisStr	= GetFactor(currThisPos, factorType)->GetString();
				if (subStr != thisStr)
				{
					match = false;
					break;
				}
			}
			if (!match)
				break;
		}

		if (match)
			return true;
	}
	return false;
}

bool Phrase::IsCompatible(const Phrase &inputPhrase) const
{
	if (inputPhrase.GetSize() != GetSize())
	{
		return false;
	}

	const size_t size = GetSize();

	for (size_t currPos = 0 ; currPos < size ; currPos++)
	{
		for (unsigned int currFactor = 0 ; currFactor < NUM_FACTORS ; currFactor++)
		{
			FactorType factorType = static_cast<FactorType>(currFactor);
			const Factor *thisFactor 		= GetFactor(currPos, factorType)
									,*inputFactor	= inputPhrase.GetFactor(currPos, factorType);
			if (thisFactor != NULL && inputFactor != NULL && thisFactor != inputFactor)
				return false;
		}
	}
	return true;

}

void Phrase::InitializeMemPool()
{
	s_memPool.push_back( new mempool(1 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 50000 ));
	s_memPool.push_back( new mempool(2 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 1000 ));
	s_memPool.push_back( new mempool(3 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 1000 ));
	s_memPool.push_back( new mempool(4 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 100 ));
	s_memPool.push_back( new mempool(5 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 10 ));
	s_memPool.push_back( new mempool(6 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 10 ));
	s_memPool.push_back( new mempool(7 * ARRAY_SIZE_INCR * sizeof(FactorArray) , 10 ));

	for (size_t i = 8 ; i < 30 ; ++i)
		s_memPool.push_back( new mempool(i * ARRAY_SIZE_INCR * sizeof(FactorArray) , 2 ));
}

void Phrase::FinalizeMemPool()
{
#if 0
	std::vector<mempool*>::iterator iter;
	for (iter = s_memPool.begin() ; iter != s_memPool.end() ; ++iter)
	{
		delete *iter;
	}
#endif
}

TO_STRING_BODY(Phrase);

// friend
ostream& operator<<(ostream& out, const Phrase& phrase)
{
//	out << "(size " << phrase.GetSize() << ") ";
	for (size_t pos = 0 ; pos < phrase.GetSize() ; pos++)
	{
		const FactorArray &factorArray = phrase.GetFactorArray(pos);
		out << Word::ToString(factorArray);
	}
	return out;
}

<|endoftext|>


<commit_before><commit_msg>Gui: automatically activate the DlgExpressionInput dialog; fixes #4384<commit_after><|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include "ROOT/RHist.hxx"
#include "ROOT/RHistDrawable.hxx"
#include "ROOT/RCanvas.hxx"
#include "ROOT/RColor.hxx"
#include "ROOT/RFile.hxx"

#include <TApplication.h>

using namespace ROOT::Experimental;

int myArgc = 2;
const char* myArgv[] = {"app", "-b", nullptr};
TApplication theApp("iotest", &myArgc, const_cast<char**>(myArgv));

// Test drawing of histograms.
TEST(IOTest, OneD)
{
   TClass::GetClass("ROOT::Experimental::Detail::RHistImpl<ROOT::Experimental::Detail::RHistData<1,double,std::vector<double>,ROOT::Experimental::RHistStatContent,ROOT::Experimental::RHistStatUncertainty>,ROOT::Experimental::RAxisEquidistant>")->GetClassInfo();

   RAxisConfig xaxis{10, 0., 1.};
   RH1D h(xaxis);
   auto file = TFile::Recreate("IOTestOneD.root");
   file->Write("h", h);
}

// Drawing options:
TEST(IOTest, OneDOpts)
{
   RAxisConfig xaxis{10, 0., 1.};
   auto h = std::make_unique<RH1D>(xaxis);
   RCanvas canv;
   auto optsPtr = canv.Draw(std::move(h));
   optsPtr->Line().SetColor(RColor::kRed);

   auto file = RFile::Recreate("IOTestOneDOpts.root");
   file->Write("canv", canv);
}
<commit_msg>v7 tests: TFile -> RFile<commit_after>#include "gtest/gtest.h"
#include "ROOT/RHist.hxx"
#include "ROOT/RHistDrawable.hxx"
#include "ROOT/RCanvas.hxx"
#include "ROOT/RColor.hxx"
#include "ROOT/RFile.hxx"

#include <TApplication.h>

using namespace ROOT::Experimental;

int myArgc = 2;
const char* myArgv[] = {"app", "-b", nullptr};
TApplication theApp("iotest", &myArgc, const_cast<char**>(myArgv));

// Test drawing of histograms.
TEST(IOTest, OneD)
{
   TClass::GetClass("ROOT::Experimental::Detail::RHistImpl<ROOT::Experimental::Detail::RHistData<1,double,std::vector<double>,ROOT::Experimental::RHistStatContent,ROOT::Experimental::RHistStatUncertainty>,ROOT::Experimental::RAxisEquidistant>")->GetClassInfo();

   RAxisConfig xaxis{10, 0., 1.};
   RH1D h(xaxis);
   auto file = RFile::Recreate("IOTestOneD.root");
   file->Write("h", h);
}

// Drawing options:
TEST(IOTest, OneDOpts)
{
   RAxisConfig xaxis{10, 0., 1.};
   auto h = std::make_unique<RH1D>(xaxis);
   RCanvas canv;
   auto optsPtr = canv.Draw(std::move(h));
   optsPtr->Line().SetColor(RColor::kRed);

   auto file = RFile::Recreate("IOTestOneDOpts.root");
   file->Write("canv", canv);
}
<|endoftext|>


<commit_before>// $Id: parameterSection.C,v 1.2 2000/02/15 18:15:52 oliver Exp $
//

#include <BALL/FORMAT/parameterSection.h>
#include <BALL/FORMAT/parameters.h>

using namespace std;

namespace BALL
{

	ParameterSection::ParameterSection()
	{
		number_of_variables_ = 0;

		entries_ = 0;
		version_ = 0;

		valid_ = false;
	}

	ParameterSection::~ParameterSection()
	{
		destroy();
	}

	void ParameterSection::destroy()
	{
		// destroy all hash maps
		section_entries_.destroy();
		variable_names_.destroy();

		// clear all allocated entries
		delete [] entries_;
		entries_ = 0;

		// delete the version array
		delete [] version_;
		version_ = 0;

		// clear the number of entries/variables
		number_of_variables_ = 0;

		// tag this instance as invalid
		valid_ = false;
	}

	bool ParameterSection::extractSection(Parameters& parameters, const String& section_name)
 	{
		if (!parameters.isValid())
		{
			return false;
		}

		// this instance should be valid only if extractSection didn`t fail
		valid_ = false;

		// check for the existence of the required section
		if (!parameters.getParameterFile().hasSection(section_name))
		{
			return false;
		}

		// store the section name
		section_name_ = section_name;

		// count non-comment lines only
		int	number_of_lines = 0;
		String line;
		Position i;

		INIFile&	ini_file = parameters.getParameterFile();

		// loop over all lines and store the format line
		// skip all comment and options lines
		// and count the number of non-comment lines
		Size first_line = ini_file.getSectionFirstLine(section_name);
		Size last_line = ini_file.getSectionLastLine(section_name);

		for (i = first_line; i <= last_line; i++)
		{
			// get the line and remove leading white spaces
			line = *ini_file.getLine(i);
			line.trimLeft();

			// comment lines start with "!" or ";" or "#"
			// option lines start with "@"
			if (line.size() > 0)
			{
				if ((line[0] != ';') && (line[0] != '!') && (line[0] != '#') && (line[0] != '@'))
				{
					// extract format line: the first non-comment/non-option line
					if (number_of_lines == 0)
					{
						format_line_ = line;
					}

					// count non-comment lines
					number_of_lines++;
				}
			}
		}

		//
		// interpret the format line
		//

		// f contains the field resulting from a split format line
		String	f[ParameterSection::MAX_FIELDS];
		Size number_of_fields = format_line_.split(f, ParameterSection::MAX_FIELDS, String::CHARACTER_CLASS__WHITESPACE);

		if ((number_of_fields == 0) || (number_of_fields > ParameterSection::MAX_FIELDS))
		{
			Log.level(LogStream::ERROR) << "Error reading section " << section_name
				<< " of file " << ini_file.getFilename() << ": wrong number of fields in the format line: " << number_of_fields << endl;
			Log.level(LogStream::ERROR) << "FORMAT: " << format_line_ << endl;

			return false;
		}

		// keys is an array containing the fields that will we assembled to the line key
		Index	keys[ParameterSection::MAX_FIELDS];
		Size	number_of_keys = 0;

		// variables is an array containing the fields that represent variables
		Index	variables[ParameterSection::MAX_FIELDS];
		Size	number_of_variables = 0;

		// check every field definition

		// true, if each line contains version information
		// indicated by a variable definition named "ver"
		bool check_version;
		check_version = false;

		for (i = 0; i < (Position)number_of_fields; i++)
		{
			if (f[i].hasPrefix("key:"))
			{
				keys[number_of_keys++] = (Index)i;
			} else if (f[i].hasPrefix("value:"))
			{
				variable_names_[f[i].after(":", 0)] = (Index)number_of_variables;
				variables[number_of_variables++] = (Index)i;
			}
		}

		check_version = variable_names_.has("ver");

		// store for faster access
		number_of_variables_ = variable_names_.size();

		if ((number_of_keys == 0) || (number_of_keys == ParameterSection::MAX_FIELDS))
		{
			return false;
		}

		// allocate space for all entries
		entries_ = new String[number_of_lines * number_of_variables];

		// clear all former contest of the keys_ array
		keys_.clear();
		section_entries_.clear();

		// now extract all non-comment lines
		bool ignore_entry;
		number_of_lines = -1; // skip format line
		for (i = ini_file.getSectionFirstLine(section_name); i <= ini_file.getSectionLastLine(section_name); i++)
		{
			line = *ini_file.getLine(i);
			line.trimLeft();
			if (line.size() > 0)
			{
				if ((line[0] != ';') && (line[0] != '!') && (line[0] != '#') && (line[0] != '@'))
				{
					number_of_lines++;
					// skip format line
					if (number_of_lines > 0)
					{
						// now split the line...
						number_of_fields = line.split(f, ParameterSection::MAX_FIELDS, String::CHARACTER_CLASS__WHITESPACE);

						// assemble the keys
						Size	j;	// loop variable
						String	key = "";
						for (j = 0; j < number_of_keys; j++)
						{
							key.append(f[keys[j]]);
							if (j != number_of_keys - 1)
							{
								key.append(" ");
							}
						}

						// if another entry with higher version number has already been read,
						// ignore_entry is set to true.
						ignore_entry = false;

						if (check_version)
						{
							// check whether we have already read this key
							if (section_entries_.has(key))
							{
								// yes, we do - compare version numbers
								float old_version = entries_[section_entries_[key]
																						* number_of_variables_
																						+ variable_names_["ver"]].toFloat();
								float new_version = f[variables[variable_names_["ver"]]].toFloat();
								if (old_version > new_version)
								{
									ignore_entry = true;
								} else {
									if (old_version == new_version)
									{
										Log.warn() << "ParameterSection: repeated entry with same version number in line " << number_of_lines
															 << " of section [" << section_name << "] " << endl;
										Log.warn() << "  in file " << ini_file.getFilename() << ":" << endl;
										Log.warn() << " > " << line << endl;
										ignore_entry = true;
									}
								}
							}
						}

						if (!ignore_entry)
						{
							// if this key is new, remember it!
							if (!section_entries_.has(key))
							{
								// add the key to the array of keys
								keys_.push_back(key);

								// insert the key into the hash map
								section_entries_[key] = number_of_lines;
							}

							// copy all variable fields to the corresponding array
							for (j = 0; j < (Position)number_of_variables; j++)
							{
								entries_[number_of_lines * number_of_variables_ + j] = f[variables[j]];
							}
						}
					}
				} else if (line[0] == '@')
				{
					// we found an option.
					// options are of the form "@option=value"

					// remove the leading '@'
					line.erase(0, 1);

					// insert the option
					String option_key		= line.before("=");
					String option_value = line.after("=");
					options.set(option_key, option_value);
				}
			}
		}

		// mark as valid
		valid_ = true;

		return true;
	}

	bool ParameterSection::has(const String& key, const String& variable) const
	{
		return section_entries_.has(key) && variable_names_.has(variable);
	}

	bool ParameterSection::has(const String& key) const
	{
		return section_entries_.has(key);
	}

	const String& ParameterSection::getValue(const String& key, const String& variable) const
	{
		// define a dummy value returned, if a undefined key/variable
		// pair is requested
		static const String undefined("(undefined)");

		// check whether the entry exists
		if (!section_entries_.has(key) || !variable_names_.has(variable))
		{
			return undefined;
		}

		// return the value
		return entries_[section_entries_[key] * number_of_variables_ + variable_names_[variable]];
	}

	const String& ParameterSection::getValue(Size key_index, Size variable_index) const
	{
		// define a dummy value returned, if a undefined key/variable
		// pair is requested
		static const String undefined("(undefined)");

		// check whether the entry exists
		if ((key_index < keys_.size())
				&& (variable_index < number_of_variables_))
		{
			// return the section entry corresponding to the key
			return entries_[(section_entries_[keys_[key_index]]) * number_of_variables_ + variable_index];
		} else {
			return undefined;
		}
	}

	const String& ParameterSection::getKey(Position key_index) const
	{
		// define a dummy value returned, if an undefined key/variable
		// pair is requested
		static const String undefined("(undefined)");

		// check whether the entry exists
		if ((key_index >= section_entries_.size()))
		{
			return undefined;
		}

		// return the value
		return keys_[key_index];
	}

	Size ParameterSection::getNumberOfKeys() const
	{
		return keys_.size();
	}

	Size ParameterSection::getNumberOfVariables() const
	{
		return number_of_variables_;
	}

	bool ParameterSection::hasVariable(const String& variable) const
	{
		return variable_names_.has(variable);
	}

	Position ParameterSection::getColumnIndex(const String& variable) const
	{
		if (variable_names_.has(variable))
		{
			return variable_names_[variable];
		} else {
			return 0;
		}
	}

	bool ParameterSection::isValid() const
	{
		return valid_;
	}

} // namespace BALL
<commit_msg>added: additional error detection for duplicate variable names and missing variable names 	in the format line of a section<commit_after>// $Id: parameterSection.C,v 1.3 2000/08/28 08:10:26 oliver Exp $
//

#include <BALL/FORMAT/parameterSection.h>
#include <BALL/FORMAT/parameters.h>

using namespace std;

namespace BALL
{

	ParameterSection::ParameterSection()
	{
		number_of_variables_ = 0;

		entries_ = 0;
		version_ = 0;

		valid_ = false;
	}

	ParameterSection::~ParameterSection()
	{
		destroy();
	}

	void ParameterSection::destroy()
	{
		// destroy all hash maps
		section_entries_.destroy();
		variable_names_.destroy();

		// clear all allocated entries
		delete [] entries_;
		entries_ = 0;

		// delete the version array
		delete [] version_;
		version_ = 0;

		// clear the number of entries/variables
		number_of_variables_ = 0;

		// tag this instance as invalid
		valid_ = false;
	}

	bool ParameterSection::extractSection(Parameters& parameters, const String& section_name)
 	{
		if (!parameters.isValid())
		{
			return false;
		}

		// this instance should be valid only if extractSection didn`t fail
		valid_ = false;

		// check for the existence of the required section
		if (!parameters.getParameterFile().hasSection(section_name))
		{
			return false;
		}

		// store the section name
		section_name_ = section_name;

		// count non-comment lines only
		int	number_of_lines = 0;
		String line;
		Position i;

		INIFile&	ini_file = parameters.getParameterFile();

		// loop over all lines and store the format line
		// skip all comment and options lines
		// and count the number of non-comment lines
		Size first_line = ini_file.getSectionFirstLine(section_name);
		Size last_line = ini_file.getSectionLastLine(section_name);

		for (i = first_line; i <= last_line; i++)
		{
			// get the line and remove leading white spaces
			line = *ini_file.getLine(i);
			line.trimLeft();

			// comment lines start with "!" or ";" or "#"
			// option lines start with "@"
			if (line.size() > 0)
			{
				if ((line[0] != ';') && (line[0] != '!') && (line[0] != '#') && (line[0] != '@'))
				{
					// extract format line: the first non-comment/non-option line
					if (number_of_lines == 0)
					{
						format_line_ = line;
					}

					// count non-comment lines
					number_of_lines++;
				}
			}
		}

		//
		// interpret the format line
		//

		// f contains the field resulting from a split format line
		String	f[ParameterSection::MAX_FIELDS];
		Size number_of_fields = format_line_.split(f, ParameterSection::MAX_FIELDS, String::CHARACTER_CLASS__WHITESPACE);

		if ((number_of_fields == 0) || (number_of_fields > ParameterSection::MAX_FIELDS))
		{
			Log.error() << "ParameterSection::extractSection: error reading section " << section_name
				<< " of file " << ini_file.getFilename() << ": wrong number of fields in the format line: " << number_of_fields << endl;
			Log.error() << "FORMAT: " << format_line_ << endl;

			return false;
		}

		// keys is an array containing the fields that will we assembled to the line key
		Index	keys[ParameterSection::MAX_FIELDS];
		Size	number_of_keys = 0;

		// variables is an array containing the fields that represent variables
		Index	variables[ParameterSection::MAX_FIELDS];
		Size	number_of_variables = 0;

		// check every field definition

		// true, if each line contains version information
		// indicated by a variable definition named "ver"
		bool check_version;
		check_version = false;

		for (i = 0; i < (Position)number_of_fields; i++)
		{
			if (f[i].hasPrefix("key:"))
			{
				keys[number_of_keys++] = (Index)i;
			}
			else if (f[i].hasPrefix("value:"))
			{
				// check whether a  variable name was given
				String variable_name = f[i].after(":", 0);
				if (variable_name == "")
				{
					Log.error() << "ParameterSection::extractSection: error while reading section "
							<< section_name << ": empty variable name: " << f[i] << endl;
				}
				else if (variable_names_.has(variable_name))
				{
					Log.error() << "ParameterSection::extractSection: error while reading section "
							<< section_name << ": duplicate variable name: " << f[i] << endl;
				}
				else
				{
					// correct definition: store it.
					variable_names_[variable_name] = (Index)number_of_variables;
					variables[number_of_variables++] = (Index)i;
				}
			}
		}

		check_version = variable_names_.has("ver");

		// store for faster access
		number_of_variables_ = variable_names_.size();

		if ((number_of_keys == 0) || (number_of_keys == ParameterSection::MAX_FIELDS))
		{
			return false;
		}

		// allocate space for all entries
		entries_ = new String[number_of_lines * number_of_variables];

		// clear all former contest of the keys_ array
		keys_.clear();
		section_entries_.clear();

		// now extract all non-comment lines
		bool ignore_entry;
		number_of_lines = -1; // skip format line
		for (i = ini_file.getSectionFirstLine(section_name); i <= ini_file.getSectionLastLine(section_name); i++)
		{
			line = *ini_file.getLine(i);
			line.trimLeft();
			if (line.size() > 0)
			{
				if ((line[0] != ';') && (line[0] != '!') && (line[0] != '#') && (line[0] != '@'))
				{
					number_of_lines++;
					// skip format line
					if (number_of_lines > 0)
					{
						// now split the line...
						number_of_fields = line.split(f, ParameterSection::MAX_FIELDS, String::CHARACTER_CLASS__WHITESPACE);

						// assemble the keys
						Size	j;	// loop variable
						String	key = "";
						for (j = 0; j < number_of_keys; j++)
						{
							key.append(f[keys[j]]);
							if (j != number_of_keys - 1)
							{
								key.append(" ");
							}
						}

						// if another entry with higher version number has already been read,
						// ignore_entry is set to true.
						ignore_entry = false;

						if (check_version)
						{
							// check whether we have already read this key
							if (section_entries_.has(key))
							{
								// yes, we do - compare version numbers
								float old_version = entries_[section_entries_[key]
																						* number_of_variables_
																						+ variable_names_["ver"]].toFloat();
								float new_version = f[variables[variable_names_["ver"]]].toFloat();
								if (old_version > new_version)
								{
									ignore_entry = true;
								} else {
									if (old_version == new_version)
									{
										Log.warn() << "ParameterSection: repeated entry with same version number in line " << number_of_lines
															 << " of section [" << section_name << "] " << endl;
										Log.warn() << "  in file " << ini_file.getFilename() << ":" << endl;
										Log.warn() << " > " << line << endl;
										ignore_entry = true;
									}
								}
							}
						}

						if (!ignore_entry)
						{
							// if this key is new, remember it!
							if (!section_entries_.has(key))
							{
								// add the key to the array of keys
								keys_.push_back(key);

								// insert the key into the hash map
								section_entries_[key] = number_of_lines;
							}

							// copy all variable fields to the corresponding array
							for (j = 0; j < (Position)number_of_variables; j++)
							{
								entries_[number_of_lines * number_of_variables_ + j] = f[variables[j]];
							}
						}
					}
				} else if (line[0] == '@')
				{
					// we found an option.
					// options are of the form "@option=value"

					// remove the leading '@'
					line.erase(0, 1);

					// insert the option
					String option_key		= line.before("=");
					String option_value = line.after("=");
					options.set(option_key, option_value);
				}
			}
		}

		// mark as valid
		valid_ = true;

		return true;
	}

	bool ParameterSection::has(const String& key, const String& variable) const
	{
		return section_entries_.has(key) && variable_names_.has(variable);
	}

	bool ParameterSection::has(const String& key) const
	{
		return section_entries_.has(key);
	}

	const String& ParameterSection::getValue(const String& key, const String& variable) const
	{
		// define a dummy value returned, if a undefined key/variable
		// pair is requested
		static const String undefined("(undefined)");

		// check whether the entry exists
		if (!section_entries_.has(key) || !variable_names_.has(variable))
		{
			return undefined;
		}

		// return the value
		return entries_[section_entries_[key] * number_of_variables_ + variable_names_[variable]];
	}

	const String& ParameterSection::getValue(Size key_index, Size variable_index) const
	{
		// define a dummy value returned, if a undefined key/variable
		// pair is requested
		static const String undefined("(undefined)");

		// check whether the entry exists
		if ((key_index < keys_.size())
				&& (variable_index < number_of_variables_))
		{
			// return the section entry corresponding to the key
			return entries_[(section_entries_[keys_[key_index]]) * number_of_variables_ + variable_index];
		} else {
			return undefined;
		}
	}

	const String& ParameterSection::getKey(Position key_index) const
	{
		// define a dummy value returned, if an undefined key/variable
		// pair is requested
		static const String undefined("(undefined)");

		// check whether the entry exists
		if ((key_index >= section_entries_.size()))
		{
			return undefined;
		}

		// return the value
		return keys_[key_index];
	}

	Size ParameterSection::getNumberOfKeys() const
	{
		return keys_.size();
	}

	Size ParameterSection::getNumberOfVariables() const
	{
		return number_of_variables_;
	}

	bool ParameterSection::hasVariable(const String& variable) const
	{
		return variable_names_.has(variable);
	}

	Position ParameterSection::getColumnIndex(const String& variable) const
	{
		if (variable_names_.has(variable))
		{
			return variable_names_[variable];
		} else {
			return 0;
		}
	}

	bool ParameterSection::isValid() const
	{
		return valid_;
	}

} // namespace BALL
<|endoftext|>


<commit_before>// $Id: analyticalSES.C,v 1.8 2000/06/27 08:27:21 oliver Exp $
// $Id: analyticalSES.C,v 1.8 2000/06/27 08:27:21 oliver Exp $

#include <BALL/STRUCTURE/analyticalSES.h>
#include <BALL/KERNEL/atom.h>
#include <BALL/KERNEL/baseFragment.h>

namespace BALL
{

	extern int connolly_ (int number_of_atoms, float* coordinates, float* radius,
												float& volume, float& area, float probe, float exclude_radius, float* atom_areas);

	float calculateSESArea
		(const BaseFragment& fragment, float probe_radius)
	{
		// extract all atoms: iterate over all composites and
		// check whether they are Atoms
		vector<Atom*>	atoms;
		AtomIterator	it = fragment.beginAtom();
		for (; +it; ++it)
		{
			if (it->getRadius() > 0.0)
			{
				atoms.push_back(&*it);
			}
		}

		// if no atoms are found, return zero
		if (atoms.size() == 0)
		{
			return 0;
		}

		// create the field required by nsc and fill it with the atom coordinates
		float* coordinates = new float[atoms.size() * 3];
		float* radii = new float[atoms.size()];
		float* atom_areas = new float[atoms.size()];
		for (Size i = 0; i < atoms.size(); i++)
		{
			float tmp[3];
			atoms[i]->getPosition().get(tmp);
			coordinates[i * 3]			= tmp[0];
			coordinates[i * 3 + 1]	= tmp[1];
			coordinates[i * 3 + 2]	= tmp[2];
			radii[i] = atoms[i]->getRadius();
		}

		float area;
		float volume;
		int number_of_atoms = (int)atoms.size();

		// call connolly_
		connolly_(number_of_atoms, coordinates, radii, volume,
							area, probe_radius, 0.0, atom_areas);

		// free the input fields
		delete [] coordinates;
		delete [] radii;
		delete [] atom_areas;

		return area;
	}

  float calculateSESAtomAreas
		(const BaseFragment& fragment, HashMap<Atom*,float>& atom_areas, float probe_radius)
	{
		// extract all atoms: iterate over all composites and
		// check whether they are Atoms
		vector<Atom*>	atoms;
		AtomIterator	it = fragment.beginAtom();
		for (; +it; ++it)
		{
			if (it->getRadius() > 0.0)
			{
				atoms.push_back(&*it);
			}
		}

		// if no atoms are found, return zero
		if (atoms.size() == 0)
		{
			return 0;
		}

		// create the field required by nsc and fill it with the atom coordinates
		float* coordinates = new float[atoms.size() * 3];
		float* radii = new float[atoms.size()];
		float* tmp_atom_areas = new float[atoms.size()];
		for (Size i = 0; i < atoms.size(); i++)
		{
			float tmp[3];
			atoms[i]->getPosition().get(tmp);
			coordinates[i * 3]			= tmp[0];
			coordinates[i * 3 + 1]	= tmp[1];
			coordinates[i * 3 + 2]	= tmp[2];
			radii[i] = atoms[i]->getRadius();
		}

		float area;
		float volume;
		int number_of_atoms = (int)atoms.size();

		// call connolly_
		connolly_(number_of_atoms, coordinates, radii, volume,
							area, probe_radius, 0.0, tmp_atom_areas);

		// extract the atom areas and store them in the hash map
		atom_areas.clear();
		for (Position i = 0; i < atoms.size(); ++i)
		{
			atom_areas.insert(pair<Atom*, float>(atoms[i], tmp_atom_areas[i]));
		}

		// free the input fields
		delete [] coordinates;
		delete [] radii;
		delete [] tmp_atom_areas;

		return area;
	}

	float calculateSESVolume
		(const BaseFragment& fragment, float probe_radius)
	{
		// extract all atoms: iterate over all composites and
		// check whether they are Atoms
		vector<Atom*>	atoms;
		AtomIterator	it = fragment.beginAtom();
		for (; +it; ++it)
		{
			if (it->getRadius() > 0.0)
			{
				atoms.push_back(&*it);
			}
		}

		// if no atoms are found, return zero
		if (atoms.size() == 0)
		{
			return 0;
		}

		// create the field required by nsc and fill it with the atom coordinates
		float* coordinates = new float[atoms.size() * 3];
		float* radii = new float[atoms.size()];
		float* tmp_atom_areas = new float[atoms.size()];
		for (Size i = 0; i < atoms.size(); i++)
		{
			float tmp[3];
			atoms[i]->getPosition().get(tmp);
			coordinates[i * 3]			= tmp[0];
			coordinates[i * 3 + 1]	= tmp[1];
			coordinates[i * 3 + 2]	= tmp[2];
			radii[i] = atoms[i]->getRadius();
		}

		float area;
		float volume;
		int number_of_atoms = (int)atoms.size();

		// call connolly_
		connolly_(number_of_atoms, coordinates, radii, volume,
							area, probe_radius, 0.0, tmp_atom_areas);

		// free the input fields
		delete [] coordinates;
		delete [] radii;
		delete [] tmp_atom_areas;

		return volume;
	}

} // namespace BALL
<commit_msg>fixed: incorrect parameters for call to connolly_<commit_after>// $Id: analyticalSES.C,v 1.9 2000/06/27 11:08:44 oliver Exp $
// $Id: analyticalSES.C,v 1.9 2000/06/27 11:08:44 oliver Exp $

#include <BALL/STRUCTURE/analyticalSES.h>
#include <BALL/KERNEL/atom.h>
#include <BALL/KERNEL/baseFragment.h>

namespace BALL
{

  extern int connolly_ (int number_of_atoms, double *coordinates, double *radius,
												double *volume, double *area, double probe, double exclude, double* atom_areas);

	float calculateSESArea
		(const BaseFragment& fragment, float probe_radius)
	{
		// extract all atoms: iterate over all composites and
		// check whether they are Atoms
		vector<Atom*>	atoms;
		AtomIterator	it = fragment.beginAtom();
		for (; +it; ++it)
		{
			if (it->getRadius() > 0.0)
			{
				atoms.push_back(&*it);
			}
		}

		// if no atoms are found, return zero
		if (atoms.size() == 0)
		{
			return 0;
		}

		// create the field required by nsc and fill it with the atom coordinates
		double* coordinates = new double[atoms.size() * 3];
		double* radii = new double[atoms.size()];
		double* atom_areas = new double[atoms.size()];
		for (Size i = 0; i < atoms.size(); i++)
		{
			float tmp[3];
			atoms[i]->getPosition().get(tmp);
			coordinates[i * 3]			= tmp[0];
			coordinates[i * 3 + 1]	= tmp[1];
			coordinates[i * 3 + 2]	= tmp[2];
			radii[i] = atoms[i]->getRadius();
		}

		double area;
		double volume;
		int number_of_atoms = (int)atoms.size();

		// int connolly_ (int number_of_atoms, double *coordinates, double *radius,
		//								double *volume, double *area, double probe, double exclude, double* atom_areas);
		// call connolly_
		connolly_(number_of_atoms, coordinates, radii,
							&volume, &area, probe_radius, 0.0, atom_areas);

		// free the input fields
		delete [] coordinates;
		delete [] radii;
		delete [] atom_areas;

		return area;
	}

  float calculateSESAtomAreas
		(const BaseFragment& fragment, HashMap<Atom*,float>& atom_areas, float probe_radius)
	{
		// extract all atoms: iterate over all composites and
		// check whether they are Atoms
		vector<Atom*>	atoms;
		AtomIterator	it = fragment.beginAtom();
		for (; +it; ++it)
		{
			if (it->getRadius() > 0.0)
			{
				atoms.push_back(&*it);
			}
		}

		// if no atoms are found, return zero
		if (atoms.size() == 0)
		{
			return 0;
		}

		// create the field required by nsc and fill it with the atom coordinates
		double* coordinates = new double[atoms.size() * 3];
		double* radii = new double[atoms.size()];
		double* tmp_atom_areas = new double[atoms.size()];
		for (Size i = 0; i < atoms.size(); i++)
		{
			float tmp[3];
			atoms[i]->getPosition().get(tmp);
			coordinates[i * 3]			= tmp[0];
			coordinates[i * 3 + 1]	= tmp[1];
			coordinates[i * 3 + 2]	= tmp[2];
			radii[i] = atoms[i]->getRadius();
		}

		double area;
		double volume;
		int number_of_atoms = (int)atoms.size();

		// call connolly_
		connolly_(number_of_atoms, coordinates, radii,
							&volume, &area, probe_radius, 0.0, tmp_atom_areas);

		// extract the atom areas and store them in the hash map
		atom_areas.clear();
		for (Position i = 0; i < atoms.size(); ++i)
		{
			atom_areas.insert(pair<Atom*, float>(atoms[i], tmp_atom_areas[i]));
		}

		// free the input fields
		delete [] coordinates;
		delete [] radii;
		delete [] tmp_atom_areas;

		return area;
	}

	float calculateSESVolume
		(const BaseFragment& fragment, float probe_radius)
	{
		// extract all atoms: iterate over all composites and
		// check whether they are Atoms
		vector<Atom*>	atoms;
		AtomIterator	it = fragment.beginAtom();
		for (; +it; ++it)
		{
			if (it->getRadius() > 0.0)
			{
				atoms.push_back(&*it);
			}
		}

		// if no atoms are found, return zero
		if (atoms.size() == 0)
		{
			return 0;
		}

		// create the field required by nsc and fill it with the atom coordinates
		double* coordinates = new double[atoms.size() * 3];
		double* radii = new double[atoms.size()];
		double* tmp_atom_areas = new double[atoms.size()];
		for (Size i = 0; i < atoms.size(); i++)
		{
			float tmp[3];
			atoms[i]->getPosition().get(tmp);
			coordinates[i * 3]			= tmp[0];
			coordinates[i * 3 + 1]	= tmp[1];
			coordinates[i * 3 + 2]	= tmp[2];
			radii[i] = atoms[i]->getRadius();
		}

		double area;
		double volume;
		int number_of_atoms = (int)atoms.size();

		// call connolly_
		connolly_(number_of_atoms, coordinates, radii,
							&volume, &area, probe_radius, 0.0, tmp_atom_areas);

		// free the input fields
		delete [] coordinates;
		delete [] radii;
		delete [] tmp_atom_areas;

		return volume;
	}

} // namespace BALL
<|endoftext|>