<commit_before>#include <algorithm>
#include <iostream>

#include <tiramisu/debug.h>
#include <Halide.h>

using namespace Halide;
using namespace Halide::Internal;

using std::string;
using std::map;
using std::vector;

namespace tiramisu
{

namespace
{

string stmt_to_string(const string &str, const Stmt &s)
{
    std::ostringstream stream;
    stream << str << s << "\n";
    return stream.str();
}

} // anonymous namespace

Module lower_halide_pipeline(const string &pipeline_name,
                             const Target &t,
                             const vector<Argument> &args,
                             const Internal::LoweredFunc::LinkageType linkage_type,
                             Stmt s)
{
    Module result_module(pipeline_name, t);

    // TODO(tiramisu): Compute the env (function DAG). This is needed for
    // the sliding window and storage folding passes.
    map<string, Function> env;

    std::cout << "Lower halide pipeline...\n" << s << "\n";

    DEBUG(3, tiramisu::str_dump("Performing sliding window optimization...\n"));
    s = sliding_window(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after sliding window:\n", s)));

    DEBUG(3, tiramisu::str_dump("Removing code that depends on undef values...\n"));
    s = remove_undef(s);
    DEBUG(4, tiramisu::str_dump(
              stmt_to_string("Lowering after removing code that depends on undef values:\n", s)));

    // This uniquifies the variable names, so we're good to simplify
    // after this point. This lets later passes assume syntactic
    // equivalence means semantic equivalence.
    DEBUG(3, tiramisu::str_dump("Uniquifying variable names...\n"));
    s = uniquify_variable_names(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after uniquifying variable names:\n", s)));

    DEBUG(3, tiramisu::str_dump("Simplifying...\n")); // without removing dead lets, because storage flattening needs the strides
    s = simplify(s, false);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after simplification:\n", s)));

    DEBUG(3, tiramisu::str_dump("Performing storage folding optimization...\n"));
    s = storage_folding(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after storage folding:\n", s)));

    DEBUG(3, tiramisu::str_dump("Simplifying...\n")); // without removing dead lets, because storage flattening needs the strides
    s = simplify(s, false);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after simplification:\n", s)));

/*    DEBUG(3, tiramisu::str_dump("Injecting prefetches...\n"));
    s = inject_prefetch(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting prefetches:\n", s)));
*/
    DEBUG(3, tiramisu::str_dump("Destructuring tuple-valued realizations...\n"));
    s = split_tuples(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after destructuring tuple-valued realizations:\n", s)));
    DEBUG(3, tiramisu::str_dump("\n\n"));

    // TODO(tiramisu): This pass is important to figure out all the buffer symbols.
    // Maybe we should put it somewhere else instead of here.
    DEBUG(3, tiramisu::str_dump("Unpacking buffer arguments...\n"));
    s = unpack_buffers(s);
    DEBUG(0, tiramisu::str_dump(stmt_to_string("Lowering after unpacking buffer arguments:\n", s)));

    if (t.has_gpu_feature() ||
        t.has_feature(Target::OpenGLCompute) ||
        t.has_feature(Target::OpenGL) ||
        (t.arch != Target::Hexagon && (t.features_any_of({Target::HVX_64, Target::HVX_128})))) {
        DEBUG(3, tiramisu::str_dump("Selecting a GPU API for GPU loops...\n"));
        s = select_gpu_api(s, t);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after selecting a GPU API:\n", s)));

        DEBUG(3, tiramisu::str_dump("Injecting host <-> dev buffer copies...\n"));
        s = inject_host_dev_buffer_copies(s, t);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting host <-> dev buffer copies:\n",
                                    s)));
    }

    if (t.has_feature(Target::OpenGL))
    {
        DEBUG(3, tiramisu::str_dump("Injecting OpenGL texture intrinsics...\n"));
        s = inject_opengl_intrinsics(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after OpenGL intrinsics:\n", s)));
    }

    if (t.has_gpu_feature() ||
            t.has_feature(Target::OpenGLCompute))
    {
        DEBUG(3, tiramisu::str_dump("Injecting per-block gpu synchronization...\n"));
        s = fuse_gpu_thread_loops(s);
        DEBUG(4, tiramisu::str_dump(
                  stmt_to_string("Lowering after injecting per-block gpu synchronization:\n", s)));
    }

    DEBUG(3, tiramisu::str_dump("Simplifying...\n"));
    s = simplify(s);
    s = unify_duplicate_lets(s);
    s = remove_trivial_for_loops(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after second simplifcation:\n", s)));

    DEBUG(3, tiramisu::str_dump("Reduce prefetch dimension...\n"));
    s = reduce_prefetch_dimension(s, t);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after reduce prefetch dimension:\n", s)));

    DEBUG(3, tiramisu::str_dump("Unrolling...\n"));
    s = unroll_loops(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after unrolling:\n", s)));

    DEBUG(3, tiramisu::str_dump("Vectorizing...\n"));
    s = vectorize_loops(s, t);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after vectorizing:\n", s)));

    DEBUG(3, tiramisu::str_dump("Detecting vector interleavings...\n"));
    s = rewrite_interleavings(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after rewriting vector interleavings:\n", s)));

    DEBUG(3, tiramisu::str_dump("Partitioning loops to simplify boundary conditions...\n"));
    s = partition_loops(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after partitioning loops:\n", s)));

    DEBUG(3, tiramisu::str_dump("Trimming loops to the region over which they do something...\n"));
    s = trim_no_ops(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after loop trimming:\n", s)));

    DEBUG(3, tiramisu::str_dump("Injecting early frees...\n"));
    s = inject_early_frees(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting early frees:\n", s)));

    if (t.has_feature(Target::FuzzFloatStores))
    {
        DEBUG(3, tiramisu::str_dump("Fuzzing floating point stores...\n"));
        s = fuzz_float_stores(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after fuzzing floating point stores:\n", s)));
    }

    DEBUG(3, tiramisu::str_dump("Simplifying...\n"));
    s = common_subexpression_elimination(s);

    if (t.has_feature(Target::OpenGL))
    {
        DEBUG(3, tiramisu::str_dump("Detecting varying attributes...\n"));
        s = find_linear_expressions(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after detecting varying attributes:\n", s)));

        DEBUG(3, tiramisu::str_dump("Moving varying attribute expressions out of the shader...\n"));
        s = setup_gpu_vertex_buffer(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after removing varying attributes:\n", s)));
    }

    s = remove_dead_allocations(s);
    s = remove_trivial_for_loops(s);
    s = simplify(s);
    // s = loop_invariant_code_motion(s);
    std::cout << "Lowering after final simplification:\n" << s << "\n";

    DEBUG(3, tiramisu::str_dump("Splitting off Hexagon offload...\n"));
    s = inject_hexagon_rpc(s, t, result_module);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after splitting off Hexagon offload:\n", s)));

    vector<Argument> public_args = args;

    // We're about to drop the environment and outputs vector, which
    // contain the only strong refs to Functions that may still be
    // pointed to by the IR. So make those refs strong.
    class StrengthenRefs : public IRMutator {
        using IRMutator::visit;
        void visit(const Call *c) {
            IRMutator::visit(c);
            c = expr.as<Call>();
            //internal_assert(c);
            if (c->func.defined()) {
                FunctionPtr ptr = c->func;
                ptr.strengthen();
                expr = Call::make(c->type, c->name, c->args, c->call_type,
                                  ptr, c->value_index,
                                  c->image, c->param);
            }
        }
    };
    s = StrengthenRefs().mutate(s);

    LoweredFunc main_func(pipeline_name, public_args, s, linkage_type);

    result_module.append(main_func);

    // Append a wrapper for this pipeline that accepts old buffer_ts
    // and upgrades them. It will use the same name, so it will
    // require C++ linkage. We don't need it when jitting.
    if (!t.has_feature(Target::JIT)) {
        add_legacy_wrapper(result_module, main_func);
    }

    // Also append any wrappers for extern stages that expect the old buffer_t
    wrap_legacy_extern_stages(result_module);

    return result_module;
}

}
<commit_msg>fix debugging info<commit_after>#include <algorithm>
#include <iostream>

#include <tiramisu/debug.h>
#include <Halide.h>

using namespace Halide;
using namespace Halide::Internal;

using std::string;
using std::map;
using std::vector;

namespace tiramisu
{

namespace
{

string stmt_to_string(const string &str, const Stmt &s)
{
    std::ostringstream stream;
    stream << str << s << "\n";
    return stream.str();
}

} // anonymous namespace

Module lower_halide_pipeline(const string &pipeline_name,
                             const Target &t,
                             const vector<Argument> &args,
                             const Internal::LoweredFunc::LinkageType linkage_type,
                             Stmt s)
{
    Module result_module(pipeline_name, t);

    // TODO(tiramisu): Compute the env (function DAG). This is needed for
    // the sliding window and storage folding passes.
    map<string, Function> env;

    if (ENABLE_DEBUG)
    {
    	std::cout << "Lower halide pipeline...\n" << s << "\n";
	std::flush(std::cout);
    }

    DEBUG(3, tiramisu::str_dump("Performing sliding window optimization...\n"));
    s = sliding_window(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after sliding window:\n", s)));

    DEBUG(3, tiramisu::str_dump("Removing code that depends on undef values...\n"));
    s = remove_undef(s);
    DEBUG(4, tiramisu::str_dump(
              stmt_to_string("Lowering after removing code that depends on undef values:\n", s)));

    // This uniquifies the variable names, so we're good to simplify
    // after this point. This lets later passes assume syntactic
    // equivalence means semantic equivalence.
    DEBUG(3, tiramisu::str_dump("Uniquifying variable names...\n"));
    s = uniquify_variable_names(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after uniquifying variable names:\n", s)));

    DEBUG(3, tiramisu::str_dump("Simplifying...\n")); // without removing dead lets, because storage flattening needs the strides
    s = simplify(s, false);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after simplification:\n", s)));

    DEBUG(3, tiramisu::str_dump("Performing storage folding optimization...\n"));
    s = storage_folding(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after storage folding:\n", s)));

    DEBUG(3, tiramisu::str_dump("Simplifying...\n")); // without removing dead lets, because storage flattening needs the strides
    s = simplify(s, false);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after simplification:\n", s)));

/*    DEBUG(3, tiramisu::str_dump("Injecting prefetches...\n"));
    s = inject_prefetch(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting prefetches:\n", s)));
*/
    DEBUG(3, tiramisu::str_dump("Destructuring tuple-valued realizations...\n"));
    s = split_tuples(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after destructuring tuple-valued realizations:\n", s)));
    DEBUG(3, tiramisu::str_dump("\n\n"));

    // TODO(tiramisu): This pass is important to figure out all the buffer symbols.
    // Maybe we should put it somewhere else instead of here.
    DEBUG(3, tiramisu::str_dump("Unpacking buffer arguments...\n"));
    s = unpack_buffers(s);
    DEBUG(0, tiramisu::str_dump(stmt_to_string("Lowering after unpacking buffer arguments:\n", s)));

    if (t.has_gpu_feature() ||
        t.has_feature(Target::OpenGLCompute) ||
        t.has_feature(Target::OpenGL) ||
        (t.arch != Target::Hexagon && (t.features_any_of({Target::HVX_64, Target::HVX_128})))) {
        DEBUG(3, tiramisu::str_dump("Selecting a GPU API for GPU loops...\n"));
        s = select_gpu_api(s, t);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after selecting a GPU API:\n", s)));

        DEBUG(3, tiramisu::str_dump("Injecting host <-> dev buffer copies...\n"));
        s = inject_host_dev_buffer_copies(s, t);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting host <-> dev buffer copies:\n",
                                    s)));
    }

    if (t.has_feature(Target::OpenGL))
    {
        DEBUG(3, tiramisu::str_dump("Injecting OpenGL texture intrinsics...\n"));
        s = inject_opengl_intrinsics(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after OpenGL intrinsics:\n", s)));
    }

    if (t.has_gpu_feature() ||
            t.has_feature(Target::OpenGLCompute))
    {
        DEBUG(3, tiramisu::str_dump("Injecting per-block gpu synchronization...\n"));
        s = fuse_gpu_thread_loops(s);
        DEBUG(4, tiramisu::str_dump(
                  stmt_to_string("Lowering after injecting per-block gpu synchronization:\n", s)));
    }

    DEBUG(3, tiramisu::str_dump("Simplifying...\n"));
    s = simplify(s);
    s = unify_duplicate_lets(s);
    s = remove_trivial_for_loops(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after second simplifcation:\n", s)));

    DEBUG(3, tiramisu::str_dump("Reduce prefetch dimension...\n"));
    s = reduce_prefetch_dimension(s, t);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after reduce prefetch dimension:\n", s)));

    DEBUG(3, tiramisu::str_dump("Unrolling...\n"));
    s = unroll_loops(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after unrolling:\n", s)));

    DEBUG(3, tiramisu::str_dump("Vectorizing...\n"));
    s = vectorize_loops(s, t);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after vectorizing:\n", s)));

    DEBUG(3, tiramisu::str_dump("Detecting vector interleavings...\n"));
    s = rewrite_interleavings(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after rewriting vector interleavings:\n", s)));

    DEBUG(3, tiramisu::str_dump("Partitioning loops to simplify boundary conditions...\n"));
    s = partition_loops(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after partitioning loops:\n", s)));

    DEBUG(3, tiramisu::str_dump("Trimming loops to the region over which they do something...\n"));
    s = trim_no_ops(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after loop trimming:\n", s)));

    DEBUG(3, tiramisu::str_dump("Injecting early frees...\n"));
    s = inject_early_frees(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting early frees:\n", s)));

    if (t.has_feature(Target::FuzzFloatStores))
    {
        DEBUG(3, tiramisu::str_dump("Fuzzing floating point stores...\n"));
        s = fuzz_float_stores(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after fuzzing floating point stores:\n", s)));
    }

    DEBUG(3, tiramisu::str_dump("Simplifying...\n"));
    s = common_subexpression_elimination(s);

    if (t.has_feature(Target::OpenGL))
    {
        DEBUG(3, tiramisu::str_dump("Detecting varying attributes...\n"));
        s = find_linear_expressions(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after detecting varying attributes:\n", s)));

        DEBUG(3, tiramisu::str_dump("Moving varying attribute expressions out of the shader...\n"));
        s = setup_gpu_vertex_buffer(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after removing varying attributes:\n", s)));
    }

    s = remove_dead_allocations(s);
    s = remove_trivial_for_loops(s);
    s = simplify(s);
    // s = loop_invariant_code_motion(s);
    if (ENABLE_DEBUG)
    {
    	std::cout << "Lowering after final simplification:\n" << s << "\n";
	std::flush(std::cout);
    }

    DEBUG(3, tiramisu::str_dump("Splitting off Hexagon offload...\n"));
    s = inject_hexagon_rpc(s, t, result_module);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after splitting off Hexagon offload:\n", s)));

    vector<Argument> public_args = args;

    // We're about to drop the environment and outputs vector, which
    // contain the only strong refs to Functions that may still be
    // pointed to by the IR. So make those refs strong.
    class StrengthenRefs : public IRMutator {
        using IRMutator::visit;
        void visit(const Call *c) {
            IRMutator::visit(c);
            c = expr.as<Call>();
            //internal_assert(c);
            if (c->func.defined()) {
                FunctionPtr ptr = c->func;
                ptr.strengthen();
                expr = Call::make(c->type, c->name, c->args, c->call_type,
                                  ptr, c->value_index,
                                  c->image, c->param);
            }
        }
    };
    s = StrengthenRefs().mutate(s);

    LoweredFunc main_func(pipeline_name, public_args, s, linkage_type);

    result_module.append(main_func);

    // Append a wrapper for this pipeline that accepts old buffer_ts
    // and upgrades them. It will use the same name, so it will
    // require C++ linkage. We don't need it when jitting.
    if (!t.has_feature(Target::JIT)) {
        add_legacy_wrapper(result_module, main_func);
    }

    // Also append any wrappers for extern stages that expect the old buffer_t
    wrap_legacy_extern_stages(result_module);

    return result_module;
}

}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2002 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.2  2002/02/27 16:49:40  tng
 * Fix: AttributeList::getName should attach prefix if present
 *
 * Revision 1.1.1.1  2002/02/01 22:21:58  peiyongz
 * sane_include
 *
 * Revision 1.6  2000/11/02 01:14:07  andyh
 * SAX bug fix:  Attribute lists were throwing exceptions rather than returning
 * null when an attribute could not be found by name.  Fixed by Tinny Ng.
 *
 * Revision 1.5  2000/03/13 20:19:11  rahulj
 * Fixed #54. Changed self-assignment to now use the parameter value.
 * Reported by Helmut Eiken <H.Eiken@cli.de>
 *
 * Revision 1.4  2000/03/02 19:54:29  roddey
 * This checkin includes many changes done while waiting for the
 * 1.1.0 code to be finished. I can't list them all here, but a list is
 * available elsewhere.
 *
 * Revision 1.3  2000/02/06 07:47:53  rahulj
 * Year 2K copyright swat.
 *
 * Revision 1.2  1999/12/15 19:49:37  roddey
 * Added second getValue() method which takes a short name for the attribute
 * to get the value for. Just a convenience method.
 *
 * Revision 1.1.1.1  1999/11/09 01:08:19  twl
 * Initial checkin
 *
 * Revision 1.2  1999/11/08 20:44:44  rahul
 * Swat for adding in Product name and CVS comment log variable.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/Janitor.hpp>
#include <xercesc/internal/VecAttrListImpl.hpp>

// ---------------------------------------------------------------------------
//  Constructors and Destructor
// ---------------------------------------------------------------------------
VecAttrListImpl::VecAttrListImpl() :

    fAdopt(false)
    , fCount(0)
    , fVector(0)
{
}

VecAttrListImpl::~VecAttrListImpl()
{
    //
    //  Note that some compilers can't deal with the fact that the pointer
    //  is to a const object, so we have to cast off the const'ness here!
    //
    if (fAdopt)
        delete (RefVectorOf<XMLAttr>*)fVector;
}

// ---------------------------------------------------------------------------
//  Implementation of the attribute list interface
// ---------------------------------------------------------------------------
unsigned int VecAttrListImpl::getLength() const
{
    return fCount;
}

const XMLCh* VecAttrListImpl::getName(const unsigned int index) const
{
    if (index >= fCount) {
        return 0;
    }
    return fVector->elementAt(index)->getQName();
}

const XMLCh* VecAttrListImpl::getType(const unsigned int index) const
{
    if (index >= fCount) {
        return 0;
    }
    return XMLAttDef::getAttTypeString(fVector->elementAt(index)->getType());
}

const XMLCh* VecAttrListImpl::getValue(const unsigned int index) const
{
    if (index >= fCount) {
        return 0;
    }
    return fVector->elementAt(index)->getValue();
}

const XMLCh* VecAttrListImpl::getType(const XMLCh* const name) const
{
    //
    //  Search the vector for the attribute with the given name and return
    //  its type.
    //
    for (unsigned int index = 0; index < fCount; index++)
    {
        const XMLAttr* curElem = fVector->elementAt(index);

        if (!XMLString::compareString(curElem->getName(), name))
            return XMLAttDef::getAttTypeString(curElem->getType());
    }
    return 0;
}

const XMLCh* VecAttrListImpl::getValue(const XMLCh* const name) const
{
    //
    //  Search the vector for the attribute with the given name and return
    //  its type.
    //
    for (unsigned int index = 0; index < fCount; index++)
    {
        const XMLAttr* curElem = fVector->elementAt(index);

        if (!XMLString::compareString(curElem->getName(), name))
            return curElem->getValue();
    }
    return 0;
}

const XMLCh* VecAttrListImpl::getValue(const char* const name) const
{
    // Temporarily transcode the name for lookup
    XMLCh* wideName = XMLString::transcode(name);
    ArrayJanitor<XMLCh> janName(wideName);

    //
    //  Search the vector for the attribute with the given name and return
    //  its type.
    //
    for (unsigned int index = 0; index < fCount; index++)
    {
        const XMLAttr* curElem = fVector->elementAt(index);

        if (!XMLString::compareString(curElem->getName(), wideName))
            return curElem->getValue();
    }
    return 0;
}

// ---------------------------------------------------------------------------
//  Setter methods
// ---------------------------------------------------------------------------
void VecAttrListImpl::setVector(const   RefVectorOf<XMLAttr>* const srcVec
                                , const unsigned int                count
                                , const bool                        adopt)
{
    //
    //  Delete the previous vector (if any) if we are adopting. Note that some
    //  compilers can't deal with the fact that the pointer is to a const
    //  object, so we have to cast off the const'ness here!
    //
    if (fAdopt)
        delete (RefVectorOf<XMLAttr>*)fVector;

    fAdopt = adopt;
    fCount = count;
    fVector = srcVec;
}
<commit_msg>[Bug 9788] VecAttrListImpl::getValue skips prefix if SAX namespace validation is on.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2002 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.3  2002/07/05 20:12:35  tng
 * [Bug 9788] VecAttrListImpl::getValue skips prefix if SAX namespace validation is on.
 *
 * Revision 1.2  2002/02/27 16:49:40  tng
 * Fix: AttributeList::getName should attach prefix if present
 *
 * Revision 1.1.1.1  2002/02/01 22:21:58  peiyongz
 * sane_include
 *
 * Revision 1.6  2000/11/02 01:14:07  andyh
 * SAX bug fix:  Attribute lists were throwing exceptions rather than returning
 * null when an attribute could not be found by name.  Fixed by Tinny Ng.
 *
 * Revision 1.5  2000/03/13 20:19:11  rahulj
 * Fixed #54. Changed self-assignment to now use the parameter value.
 * Reported by Helmut Eiken <H.Eiken@cli.de>
 *
 * Revision 1.4  2000/03/02 19:54:29  roddey
 * This checkin includes many changes done while waiting for the
 * 1.1.0 code to be finished. I can't list them all here, but a list is
 * available elsewhere.
 *
 * Revision 1.3  2000/02/06 07:47:53  rahulj
 * Year 2K copyright swat.
 *
 * Revision 1.2  1999/12/15 19:49:37  roddey
 * Added second getValue() method which takes a short name for the attribute
 * to get the value for. Just a convenience method.
 *
 * Revision 1.1.1.1  1999/11/09 01:08:19  twl
 * Initial checkin
 *
 * Revision 1.2  1999/11/08 20:44:44  rahul
 * Swat for adding in Product name and CVS comment log variable.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/Janitor.hpp>
#include <xercesc/internal/VecAttrListImpl.hpp>

// ---------------------------------------------------------------------------
//  Constructors and Destructor
// ---------------------------------------------------------------------------
VecAttrListImpl::VecAttrListImpl() :

    fAdopt(false)
    , fCount(0)
    , fVector(0)
{
}

VecAttrListImpl::~VecAttrListImpl()
{
    //
    //  Note that some compilers can't deal with the fact that the pointer
    //  is to a const object, so we have to cast off the const'ness here!
    //
    if (fAdopt)
        delete (RefVectorOf<XMLAttr>*)fVector;
}

// ---------------------------------------------------------------------------
//  Implementation of the attribute list interface
// ---------------------------------------------------------------------------
unsigned int VecAttrListImpl::getLength() const
{
    return fCount;
}

const XMLCh* VecAttrListImpl::getName(const unsigned int index) const
{
    if (index >= fCount) {
        return 0;
    }
    return fVector->elementAt(index)->getQName();
}

const XMLCh* VecAttrListImpl::getType(const unsigned int index) const
{
    if (index >= fCount) {
        return 0;
    }
    return XMLAttDef::getAttTypeString(fVector->elementAt(index)->getType());
}

const XMLCh* VecAttrListImpl::getValue(const unsigned int index) const
{
    if (index >= fCount) {
        return 0;
    }
    return fVector->elementAt(index)->getValue();
}

const XMLCh* VecAttrListImpl::getType(const XMLCh* const name) const
{
    //
    //  Search the vector for the attribute with the given name and return
    //  its type.
    //
    for (unsigned int index = 0; index < fCount; index++)
    {
        const XMLAttr* curElem = fVector->elementAt(index);

        if (!XMLString::compareString(curElem->getQName(), name))
            return XMLAttDef::getAttTypeString(curElem->getType());
    }
    return 0;
}

const XMLCh* VecAttrListImpl::getValue(const XMLCh* const name) const
{
    //
    //  Search the vector for the attribute with the given name and return
    //  its type.
    //
    for (unsigned int index = 0; index < fCount; index++)
    {
        const XMLAttr* curElem = fVector->elementAt(index);

        if (!XMLString::compareString(curElem->getQName(), name))
            return curElem->getValue();
    }
    return 0;
}

const XMLCh* VecAttrListImpl::getValue(const char* const name) const
{
    // Temporarily transcode the name for lookup
    XMLCh* wideName = XMLString::transcode(name);
    ArrayJanitor<XMLCh> janName(wideName);

    //
    //  Search the vector for the attribute with the given name and return
    //  its type.
    //
    for (unsigned int index = 0; index < fCount; index++)
    {
        const XMLAttr* curElem = fVector->elementAt(index);

        if (!XMLString::compareString(curElem->getQName(), wideName))
            return curElem->getValue();
    }
    return 0;
}

// ---------------------------------------------------------------------------
//  Setter methods
// ---------------------------------------------------------------------------
void VecAttrListImpl::setVector(const   RefVectorOf<XMLAttr>* const srcVec
                                , const unsigned int                count
                                , const bool                        adopt)
{
    //
    //  Delete the previous vector (if any) if we are adopting. Note that some
    //  compilers can't deal with the fact that the pointer is to a const
    //  object, so we have to cast off the const'ness here!
    //
    if (fAdopt)
        delete (RefVectorOf<XMLAttr>*)fVector;

    fAdopt = adopt;
    fCount = count;
    fVector = srcVec;
}
<|endoftext|>


<commit_before>// This file is part of the "x0" project, http://github.com/christianparpart/x0>
//   (c) 2009-2017 Christian Parpart <christian@parpart.family>
//
// Licensed under the MIT License (the "License"); you may not use this
// file except in compliance with the License. You may obtain a copy of
// the License at: http://opensource.org/licenses/MIT

#include <xzero/http/client/Http1Connection.h>
#include <xzero/http/BadMessage.h>
#include <xzero/http/HttpRequestInfo.h>
#include <xzero/http/HttpRequestInfo.h>
#include <xzero/net/TcpEndPoint.h>
#include <xzero/logging.h>
#include <xzero/HugeBuffer.h>
#include <xzero/Buffer.h>

namespace xzero {
namespace http {
namespace client {

#if 0 //!defined(NDEBUG)
#define TRACE(msg...) logTrace("http.client.Http1Connection: " msg)
#else
#define TRACE(msg...) do {} while (0)
#endif

Http1Connection::Http1Connection(HttpListener* channel,
                                 TcpEndPoint* endpoint,
                                 Executor* executor)
    : TcpConnection(endpoint, executor),
      channel_(channel),
      onComplete_(),
      writer_(),
      generator_(&writer_),
      parser_(http1::Parser::RESPONSE, this),
      inputBuffer_(),
      inputOffset_(0),
      expectsBody_(true),
      responseComplete_(false),
      keepAliveCount_(0) {
  inputBuffer_.reserve(4096);
}

Http1Connection::~Http1Connection() {
}

void Http1Connection::setListener(HttpListener* channel) {
  channel_ = channel;
}

static void removeConnectionHeaders(HeaderFieldList& headers) { // {{{
  // filter out disruptive connection-level headers
  headers.remove("Connection");
  headers.remove("Content-Length");
  headers.remove("Expect");
  headers.remove("Trailer");
  headers.remove("Transfer-Encoding");
  headers.remove("Upgrade");
} // }}}

void Http1Connection::send(const HttpRequestInfo& requestInfo,
                           CompletionHandler onComplete) {
  HttpRequestInfo req(requestInfo);
  removeConnectionHeaders(req.headers());

  setCompleter(onComplete);
  responseComplete_ = false;
  expectsBody_ = req.method() != HttpMethod::HEAD;
  generator_.generateRequest(req);
  wantWrite();
}

void Http1Connection::send(const HttpRequestInfo& requestInfo,
                           const BufferRef& chunk,
                           CompletionHandler onComplete) {
  HttpRequestInfo req(requestInfo);
  removeConnectionHeaders(req.headers());

  setCompleter(onComplete);
  responseComplete_ = false;
  expectsBody_ = req.method() != HttpMethod::HEAD;
  generator_.generateRequest(req, chunk);
  wantWrite();
}

void Http1Connection::send(const HttpRequestInfo& requestInfo,
                           Buffer&& chunk,
                           CompletionHandler onComplete) {
  HttpRequestInfo req(requestInfo);
  removeConnectionHeaders(req.headers());

  setCompleter(onComplete);
  responseComplete_ = false;
  expectsBody_ = req.method() != HttpMethod::HEAD;
  generator_.generateRequest(req, chunk);
  wantWrite();
}

void Http1Connection::send(const HttpRequestInfo& requestInfo,
                           FileView&& chunk,
                           CompletionHandler onComplete) {
  HttpRequestInfo req(requestInfo);
  removeConnectionHeaders(req.headers());

  setCompleter(onComplete);
  responseComplete_ = false;
  expectsBody_ = req.method() != HttpMethod::HEAD;
  generator_.generateRequest(req, std::move(chunk));
  wantWrite();
}

void Http1Connection::send(const HttpRequestInfo& requestInfo,
                           HugeBuffer&& chunk,
                           CompletionHandler onComplete) {
  HttpRequestInfo req(requestInfo);
  removeConnectionHeaders(req.headers());

  setCompleter(onComplete);
  responseComplete_ = false;
  expectsBody_ = req.method() != HttpMethod::HEAD;
  generator_.generateRequest(req, std::move(chunk));
  wantWrite();
}

void Http1Connection::send(const BufferRef& chunk, CompletionHandler onComplete) {
  setCompleter(onComplete);
  generator_.generateBody(std::move(chunk));
  wantWrite();
}

void Http1Connection::send(Buffer&& chunk, CompletionHandler onComplete) {
  setCompleter(onComplete);
  generator_.generateBody(std::move(chunk));
  wantWrite();
}

void Http1Connection::send(FileView&& chunk, CompletionHandler onComplete) {
  setCompleter(onComplete_);
  generator_.generateBody(std::move(chunk));
  wantWrite();
}

void Http1Connection::send(HugeBuffer&& chunk, CompletionHandler onComplete) {
  if (chunk.isBuffered()) {
    send(chunk.takeBuffer(), onComplete);
  } else {
    send(chunk.takeFileView(), onComplete);
  }
}

void Http1Connection::completed() {
  if (!generator_.isChunked() && generator_.remainingContentLength() > 0)
    throw InvalidState{"Request not fully written but completed() invoked."};

  setCompleter(std::bind(&Http1Connection::onRequestComplete, this,
                         std::placeholders::_1));

  //generator_.generateTrailer(channel_->requestInfo()->trailers());
  wantWrite();
}

void Http1Connection::onRequestComplete(bool success) {
  TRACE("onRequestComplete($0)", success ? "success" : "failed");
  if (success) {
    wantRead();
  }
}

void Http1Connection::onResponseComplete(bool success) {
  // channel_->responseEnd();

  if (!keepAliveCount_) {
    close();
  }
}

void Http1Connection::abort() {
  close();
}

void Http1Connection::onReadable() {
  TRACE("onReadable()");

  size_t n = endpoint()->read(&inputBuffer_);

  if (n == 0) {
    abort();
    return;
  }

  parseFragment();

  if (!responseComplete_) {
    wantRead();
  }
}

void Http1Connection::parseFragment() {
  size_t n = parser_.parseFragment(inputBuffer_.ref(inputOffset_));
  inputOffset_ += n;
}

void Http1Connection::onWriteable() {
  TRACE("onWriteable()");
  const bool complete = writer_.flushTo(endpoint());
  TRACE("onWriteable: $0", complete ? "completed" : "needs-more-to-flush");

  if (!complete) {
    wantWrite();
  } else {
    notifySuccess();
  }
}

void Http1Connection::onInterestFailure(const std::exception& error) {
  //TODO logError("http.client.Http1Connection", error, "Unhandled exception caught in I/O loop");

  notifyFailure(); // notify the callback that we failed doing something wrt. I/O.
  abort();
}

void Http1Connection::setCompleter(CompletionHandler onComplete) {
  if (onComplete && onComplete_)
    throw InvalidState{"There is still another completion hook."};

  onComplete_ = std::move(onComplete);
}

void Http1Connection::invokeCompleter(bool success) {
  if (onComplete_) {
    auto cb = std::move(onComplete_);
    onComplete_ = nullptr;
    cb(success);
  }
}

// {{{ HttpListener overrides
void Http1Connection::onMessageBegin(HttpVersion version,
                                     HttpStatus status,
                                     const BufferRef& text) {
  expectsBody_ = !isContentForbidden(status);
  channel_->onMessageBegin(version, status, text);
}

void Http1Connection::onMessageHeader(const BufferRef& name,
                                      const BufferRef& value) {
  channel_->onMessageHeader(name, value);
}

void Http1Connection::onMessageHeaderEnd() {
  TRACE("onMessageHeaderEnd! expectsBody=$0", expectsBody_);
  channel_->onMessageHeaderEnd();
  if (parser_.isContentExpected() && !expectsBody_) {
    onMessageEnd();
  }
}

void Http1Connection::onMessageContent(const BufferRef& chunk) {
  channel_->onMessageContent(chunk);
}

void Http1Connection::onMessageContent(FileView&& chunk) {
  channel_->onMessageContent(std::move(chunk));
}

void Http1Connection::onMessageEnd() {
  TRACE("onMessageEnd!");
  responseComplete_ = true;
  channel_->onMessageEnd();
}

void Http1Connection::onError(std::error_code ec) {
  TRACE("onError! $0", ec.message());
  channel_->onError(ec);
}
// }}}

} // namespace client
} // namespace http
} // namespace xzero
<commit_msg>[xzero] client/Http1Connection: honor NDEBUG<commit_after>// This file is part of the "x0" project, http://github.com/christianparpart/x0>
//   (c) 2009-2017 Christian Parpart <christian@parpart.family>
//
// Licensed under the MIT License (the "License"); you may not use this
// file except in compliance with the License. You may obtain a copy of
// the License at: http://opensource.org/licenses/MIT

#include <xzero/http/client/Http1Connection.h>
#include <xzero/http/BadMessage.h>
#include <xzero/http/HttpRequestInfo.h>
#include <xzero/http/HttpRequestInfo.h>
#include <xzero/net/TcpEndPoint.h>
#include <xzero/logging.h>
#include <xzero/HugeBuffer.h>
#include <xzero/Buffer.h>

namespace xzero {
namespace http {
namespace client {

#if !defined(NDEBUG)
#define TRACE(msg...) logTrace("http.client.Http1Connection: " msg)
#else
#define TRACE(msg...) do {} while (0)
#endif

Http1Connection::Http1Connection(HttpListener* channel,
                                 TcpEndPoint* endpoint,
                                 Executor* executor)
    : TcpConnection(endpoint, executor),
      channel_(channel),
      onComplete_(),
      writer_(),
      generator_(&writer_),
      parser_(http1::Parser::RESPONSE, this),
      inputBuffer_(),
      inputOffset_(0),
      expectsBody_(true),
      responseComplete_(false),
      keepAliveCount_(0) {
  inputBuffer_.reserve(4096);
}

Http1Connection::~Http1Connection() {
}

void Http1Connection::setListener(HttpListener* channel) {
  channel_ = channel;
}

static void removeConnectionHeaders(HeaderFieldList& headers) { // {{{
  // filter out disruptive connection-level headers
  headers.remove("Connection");
  headers.remove("Content-Length");
  headers.remove("Expect");
  headers.remove("Trailer");
  headers.remove("Transfer-Encoding");
  headers.remove("Upgrade");
} // }}}

void Http1Connection::send(const HttpRequestInfo& requestInfo,
                           CompletionHandler onComplete) {
  HttpRequestInfo req(requestInfo);
  removeConnectionHeaders(req.headers());

  setCompleter(onComplete);
  responseComplete_ = false;
  expectsBody_ = req.method() != HttpMethod::HEAD;
  generator_.generateRequest(req);
  wantWrite();
}

void Http1Connection::send(const HttpRequestInfo& requestInfo,
                           const BufferRef& chunk,
                           CompletionHandler onComplete) {
  HttpRequestInfo req(requestInfo);
  removeConnectionHeaders(req.headers());

  setCompleter(onComplete);
  responseComplete_ = false;
  expectsBody_ = req.method() != HttpMethod::HEAD;
  generator_.generateRequest(req, chunk);
  wantWrite();
}

void Http1Connection::send(const HttpRequestInfo& requestInfo,
                           Buffer&& chunk,
                           CompletionHandler onComplete) {
  HttpRequestInfo req(requestInfo);
  removeConnectionHeaders(req.headers());

  setCompleter(onComplete);
  responseComplete_ = false;
  expectsBody_ = req.method() != HttpMethod::HEAD;
  generator_.generateRequest(req, chunk);
  wantWrite();
}

void Http1Connection::send(const HttpRequestInfo& requestInfo,
                           FileView&& chunk,
                           CompletionHandler onComplete) {
  HttpRequestInfo req(requestInfo);
  removeConnectionHeaders(req.headers());

  setCompleter(onComplete);
  responseComplete_ = false;
  expectsBody_ = req.method() != HttpMethod::HEAD;
  generator_.generateRequest(req, std::move(chunk));
  wantWrite();
}

void Http1Connection::send(const HttpRequestInfo& requestInfo,
                           HugeBuffer&& chunk,
                           CompletionHandler onComplete) {
  HttpRequestInfo req(requestInfo);
  removeConnectionHeaders(req.headers());

  setCompleter(onComplete);
  responseComplete_ = false;
  expectsBody_ = req.method() != HttpMethod::HEAD;
  generator_.generateRequest(req, std::move(chunk));
  wantWrite();
}

void Http1Connection::send(const BufferRef& chunk, CompletionHandler onComplete) {
  setCompleter(onComplete);
  generator_.generateBody(std::move(chunk));
  wantWrite();
}

void Http1Connection::send(Buffer&& chunk, CompletionHandler onComplete) {
  setCompleter(onComplete);
  generator_.generateBody(std::move(chunk));
  wantWrite();
}

void Http1Connection::send(FileView&& chunk, CompletionHandler onComplete) {
  setCompleter(onComplete_);
  generator_.generateBody(std::move(chunk));
  wantWrite();
}

void Http1Connection::send(HugeBuffer&& chunk, CompletionHandler onComplete) {
  if (chunk.isBuffered()) {
    send(chunk.takeBuffer(), onComplete);
  } else {
    send(chunk.takeFileView(), onComplete);
  }
}

void Http1Connection::completed() {
  if (!generator_.isChunked() && generator_.remainingContentLength() > 0)
    throw InvalidState{"Request not fully written but completed() invoked."};

  setCompleter(std::bind(&Http1Connection::onRequestComplete, this,
                         std::placeholders::_1));

  //generator_.generateTrailer(channel_->requestInfo()->trailers());
  wantWrite();
}

void Http1Connection::onRequestComplete(bool success) {
  TRACE("onRequestComplete($0)", success ? "success" : "failed");
  if (success) {
    wantRead();
  }
}

void Http1Connection::onResponseComplete(bool success) {
  // channel_->responseEnd();

  if (!keepAliveCount_) {
    close();
  }
}

void Http1Connection::abort() {
  close();
}

void Http1Connection::onReadable() {
  TRACE("onReadable()");

  size_t n = endpoint()->read(&inputBuffer_);

  if (n == 0) {
    abort();
    return;
  }

  parseFragment();

  if (!responseComplete_) {
    wantRead();
  }
}

void Http1Connection::parseFragment() {
  size_t n = parser_.parseFragment(inputBuffer_.ref(inputOffset_));
  inputOffset_ += n;
}

void Http1Connection::onWriteable() {
  TRACE("onWriteable()");
  const bool complete = writer_.flushTo(endpoint());
  TRACE("onWriteable: $0", complete ? "completed" : "needs-more-to-flush");

  if (!complete) {
    wantWrite();
  } else {
    notifySuccess();
  }
}

void Http1Connection::onInterestFailure(const std::exception& error) {
  //TODO logError("http.client.Http1Connection", error, "Unhandled exception caught in I/O loop");

  notifyFailure(); // notify the callback that we failed doing something wrt. I/O.
  abort();
}

void Http1Connection::setCompleter(CompletionHandler onComplete) {
  if (onComplete && onComplete_)
    throw InvalidState{"There is still another completion hook."};

  onComplete_ = std::move(onComplete);
}

void Http1Connection::invokeCompleter(bool success) {
  if (onComplete_) {
    auto cb = std::move(onComplete_);
    onComplete_ = nullptr;
    cb(success);
  }
}

// {{{ HttpListener overrides
void Http1Connection::onMessageBegin(HttpVersion version,
                                     HttpStatus status,
                                     const BufferRef& text) {
  expectsBody_ = !isContentForbidden(status);
  channel_->onMessageBegin(version, status, text);
}

void Http1Connection::onMessageHeader(const BufferRef& name,
                                      const BufferRef& value) {
  channel_->onMessageHeader(name, value);
}

void Http1Connection::onMessageHeaderEnd() {
  TRACE("onMessageHeaderEnd! expectsBody=$0", expectsBody_);
  channel_->onMessageHeaderEnd();
  if (parser_.isContentExpected() && !expectsBody_) {
    onMessageEnd();
  }
}

void Http1Connection::onMessageContent(const BufferRef& chunk) {
  channel_->onMessageContent(chunk);
}

void Http1Connection::onMessageContent(FileView&& chunk) {
  channel_->onMessageContent(std::move(chunk));
}

void Http1Connection::onMessageEnd() {
  TRACE("onMessageEnd!");
  responseComplete_ = true;
  channel_->onMessageEnd();
}

void Http1Connection::onError(std::error_code ec) {
  TRACE("onError! $0", ec.message());
  channel_->onError(ec);
}
// }}}

} // namespace client
} // namespace http
} // namespace xzero
<|endoftext|>


<commit_before>/*
 * SVN.cpp : Implementation of CSVNWorkingCopy
 *
 * ====================================================================
 * Copyright (c) 2001 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 * ====================================================================
 */

#include "stdafx.h"

#include "SVNCOM.h"
#include "SVN.h"
#include "misc.h"
#include "SVNStatus.h"

/////////////////////////////////////////////////////////////////////////////
// CSVNWorkingCopy

STDMETHODIMP
CSVNWorkingCopy::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] =
	{
		&IID_ISVNWorkingCopy
	};
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}

//
// Sets pfIsValid to VARIANT_TRUE if the directory contains
// valid SVN meta-data.
//
STDMETHODIMP
CSVNWorkingCopy::check_wc(BSTR bstrDir, VARIANT_BOOL *pfIsValid)
{
	USES_CONVERSION;
	HRESULT hr;
	svn_error_t *error;
	svn_boolean_t is_wc;
	svn_string_t *path;

	if (pfIsValid == NULL)
		return E_POINTER;

	path = svn_string_create(W2A(bstrDir), g_pool);

	error = svn_wc_check_wc(path, &is_wc, g_pool);

	if (error) {
		hr = convert_err_to_hresult(error);
		goto Cleanup;
	}

	if (is_wc)
		*pfIsValid = VARIANT_TRUE;
	else
		*pfIsValid = VARIANT_FALSE;

	hr = S_OK;

Cleanup:
	svn_pool_clear(g_pool);
	return hr;
}

//
// Create a secondary thread to watch for file changes
// in the specified directory (bstrDir).
// This secondary thread fires "RefreshFiles" when
// a change is detected.
//
STDMETHODIMP
CSVNWorkingCopy::watch_dir(BSTR bstrDir)
{
	USES_CONVERSION;
	HRESULT hr;
	CHAR *psz;

	EnterCriticalSection(&_csNewDir);

	if (_hFindNotification_Stop == NULL)
	{
		_hFindNotification_NewDir = CreateEvent(
			NULL, FALSE, FALSE, NULL);
		if (_hFindNotification_NewDir == NULL)
		{
			hr = E_FAIL;
			goto Error;
		}

		_hFindNotification_Stop = CreateEvent(
			NULL, FALSE, FALSE, NULL);
		if (_hFindNotification_Stop == NULL)
		{
			hr = E_FAIL;
			goto Error;
		}

		_hFindNotification_Thread = (HANDLE)_beginthread(
			FileNotificationThreadProc,
			0,
			this);
		if (_hFindNotification_Thread == NULL)
		{
			hr = E_FAIL;
			goto Cleanup;
		}
	}
	else
	{
		// Free previous directory.
		free(_pszNotification_Dir);
	}

	// Setup new direcotry
	psz = W2A(bstrDir);
	_pszNotification_Dir = (char *)malloc(strlen(psz) + 1);
	strcpy(_pszNotification_Dir, psz);

	// Tell the thread that we have a directory to care about.
	SetEvent(_hFindNotification_NewDir);

	hr = S_OK;
Cleanup:
	LeaveCriticalSection(&_csNewDir);
	return hr;
Error:
	Assert(FAILED(hr));
	if (_hFindNotification_Stop != NULL)
		CloseHandle(_hFindNotification_Stop);
	if (_hFindNotification_NewDir != NULL)
		CloseHandle(_hFindNotification_NewDir);
	goto Cleanup;
}

// Pump any waiting messages in the message queue.
static void
PumpWaitingMessages(void)
{
	MSG msg;

	//
	// Read all of the messages in this next loop,
	// removing each message as we read it.
	//
	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	{
		//
		// If it's a quit message, we're out of here.
		//
		if (msg.message == WM_QUIT)
		{
			break;
		}

		//
		// Otherwise, dispatch the message.
		//
		DispatchMessage(&msg);
	}
}

//
// Thread procedure for the file/directory notification
// thread. This thread is created for the first time when
// some calls watch_dir.
//
void
CSVNWorkingCopy::FileNotificationThreadProc(void *pv)
{
	USES_CONVERSION;
	CSVNWorkingCopy *wc;
	// Keep track of the current directory we're watching.
	CHAR *pszCurrentDir = NULL;
	HANDLE aHandles[3];
	DWORD dw;
	CComBSTR sbstr;

	// Initialize COM on this thread
	if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
		abort();

	wc = static_cast<CSVNWorkingCopy *>(pv);

	// Wait for initial all clear.
	WaitForSingleObject(wc->_hFindNotification_NewDir, INFINITE);

	aHandles[1] = wc->_hFindNotification_NewDir;
	aHandles[2] = wc->_hFindNotification_Stop;

NewDirectory:
	if (wc->_hFindNotification != NULL)
	{
		FindCloseChangeNotification(wc->_hFindNotification);
	}

	// Enter critical section to lock down _pszNotification_Dir
	EnterCriticalSection(&wc->_csNewDir);

	if (pszCurrentDir != NULL)
	{
		free(pszCurrentDir);
	}

	pszCurrentDir = (CHAR *)malloc(strlen(wc->_pszNotification_Dir) + 1);
	if (pszCurrentDir == NULL)
	{
		abort();
	}

	strcpy(pszCurrentDir, wc->_pszNotification_Dir);

	// Leave the critical section.
	LeaveCriticalSection(&wc->_csNewDir);

	sbstr.Empty();
	sbstr = A2BSTR(pszCurrentDir);

	wc->_hFindNotification = FindFirstChangeNotification(
		pszCurrentDir, FALSE,
		FILE_NOTIFY_CHANGE_FILE_NAME |
		FILE_NOTIFY_CHANGE_LAST_WRITE);
	if (wc->_hFindNotification == INVALID_HANDLE_VALUE)
	{
		abort();
	}

	aHandles[0] = wc->_hFindNotification;

	while (1)
	{
		dw = MsgWaitForMultipleObjects(
			3, aHandles,
			FALSE, INFINITE, QS_ALLINPUT);
		switch (dw)
		{
		// Change notification
		case WAIT_OBJECT_0:
			wc->Fire_RefreshFiles(sbstr);
			if (!FindNextChangeNotification(wc->_hFindNotification))
				abort();
			continue;
		// New directory
		case WAIT_OBJECT_0 + 1:
			goto NewDirectory;
		// End Thread
		case WAIT_OBJECT_0 + 2:
			_endthread();
		// Since this thread is COM enabled,
		// we have to be good citizens, and
		// pump any incoming messages to
		// our thread, so that we prevent broadcasted
		// SendMessage calls from hanging.
		case WAIT_OBJECT_0 + 3:
			PumpWaitingMessages();
			continue;
		}
	}
}

STDMETHODIMP
CSVNWorkingCopy::wc_statuses(BSTR bstrPath, SAFEARRAY **ppsa)
{
	USES_CONVERSION;
	HRESULT hr;
	apr_hash_t *hash;
	svn_error_t *error;
	svn_wc_status_t *status;
	svn_string_t *path;
	apr_hash_index_t *hi;
	SAFEARRAY *psa;
	SAFEARRAYBOUND rgsBound;
	IDispatch **paDisp;
	apr_size_t klen;
	int i;
	apr_size_t count;
	CHAR *pszKey;
	CComObject<CSVNStatus> *com_status = NULL;
	svn_boolean_t fLockedSA = FALSE;

	hash = apr_make_hash(g_pool);
	path = svn_string_create(W2A(bstrPath), g_pool);
	error = svn_wc_statuses(hash, path, FALSE, g_pool);
	if (error) {
		hr = convert_err_to_hresult(error);
		goto Cleanup;
	}

	apr_hash_count(hash, &count);
	rgsBound.cElements = count;
	rgsBound.lLbound = 0;

	psa = SafeArrayCreate(VT_DISPATCH, 1, &rgsBound);
	if (psa == NULL)
		abort();

	hr = SafeArrayAccessData(psa, (void **)&paDisp);
	if (FAILED(hr))
		goto Cleanup;
	fLockedSA = TRUE;

	for (i = 0, hi = apr_hash_first(hash); hi; i++, hi = apr_hash_next(hi)) {
		apr_hash_this(hi, (const void **)&pszKey, &klen, (void **)&status);
		hr = CComObject<CSVNStatus>::CreateInstance(&com_status);
		if (FAILED(hr))
			goto Cleanup;
		// This is what we want since the hash key is an absolute path.
		pszKey = ((svn_string_t *)apr_hash_get (status->entry->attributes,
							   (const void *)SVN_WC_ENTRY_ATTR_NAME,
							   strlen(SVN_WC_ENTRY_ATTR_NAME)))->data;
		// SVN_WC_ENTRY_THIS_DIR is ".", we don't care about its status.
		if (strcmp(pszKey, SVN_WC_ENTRY_THIS_DIR) == 0) {
			delete com_status;
			com_status = NULL;
			// Pretend the iteration didn't happen.
			i--;
			continue;
		}
		hr = com_status->init(status, pszKey);
		if (FAILED(hr))
			goto Cleanup;
		hr = com_status->QueryInterface(&paDisp[i]);
		if (FAILED(hr))
			goto Cleanup;

		// NULL out the local variable,
		// the COM reference count is now owned by paDisp[i]
		com_status = NULL;
	}

	SafeArrayUnaccessData(psa);
	fLockedSA = FALSE;

	if (rgsBound.cElements > i) {
		rgsBound.cElements = i;
		hr = SafeArrayRedim(psa, &rgsBound);
		if (FAILED(hr))
			goto Cleanup;
	}

	*ppsa = psa;

	hr = S_OK;
Cleanup:
	if (fLockedSA)
		SafeArrayUnaccessData(psa);
	delete com_status;
	svn_pool_clear(g_pool);
	return hr;
}
<commit_msg>* SVN.cpp (CSVNWorkingCopy::wc_statuses): Fix apr_hash_count call to current prototype.<commit_after>/*
 * SVN.cpp : Implementation of CSVNWorkingCopy
 *
 * ====================================================================
 * Copyright (c) 2001 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 * ====================================================================
 */

#include "stdafx.h"

#include "SVNCOM.h"
#include "SVN.h"
#include "misc.h"
#include "SVNStatus.h"

/////////////////////////////////////////////////////////////////////////////
// CSVNWorkingCopy

STDMETHODIMP
CSVNWorkingCopy::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] =
	{
		&IID_ISVNWorkingCopy
	};
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}

//
// Sets pfIsValid to VARIANT_TRUE if the directory contains
// valid SVN meta-data.
//
STDMETHODIMP
CSVNWorkingCopy::check_wc(BSTR bstrDir, VARIANT_BOOL *pfIsValid)
{
	USES_CONVERSION;
	HRESULT hr;
	svn_error_t *error;
	svn_boolean_t is_wc;
	svn_string_t *path;

	if (pfIsValid == NULL)
		return E_POINTER;

	path = svn_string_create(W2A(bstrDir), g_pool);

	error = svn_wc_check_wc(path, &is_wc, g_pool);

	if (error) {
		hr = convert_err_to_hresult(error);
		goto Cleanup;
	}

	if (is_wc)
		*pfIsValid = VARIANT_TRUE;
	else
		*pfIsValid = VARIANT_FALSE;

	hr = S_OK;

Cleanup:
	svn_pool_clear(g_pool);
	return hr;
}

//
// Create a secondary thread to watch for file changes
// in the specified directory (bstrDir).
// This secondary thread fires "RefreshFiles" when
// a change is detected.
//
STDMETHODIMP
CSVNWorkingCopy::watch_dir(BSTR bstrDir)
{
	USES_CONVERSION;
	HRESULT hr;
	CHAR *psz;

	EnterCriticalSection(&_csNewDir);

	if (_hFindNotification_Stop == NULL)
	{
		_hFindNotification_NewDir = CreateEvent(
			NULL, FALSE, FALSE, NULL);
		if (_hFindNotification_NewDir == NULL)
		{
			hr = E_FAIL;
			goto Error;
		}

		_hFindNotification_Stop = CreateEvent(
			NULL, FALSE, FALSE, NULL);
		if (_hFindNotification_Stop == NULL)
		{
			hr = E_FAIL;
			goto Error;
		}

		_hFindNotification_Thread = (HANDLE)_beginthread(
			FileNotificationThreadProc,
			0,
			this);
		if (_hFindNotification_Thread == NULL)
		{
			hr = E_FAIL;
			goto Cleanup;
		}
	}
	else
	{
		// Free previous directory.
		free(_pszNotification_Dir);
	}

	// Setup new direcotry
	psz = W2A(bstrDir);
	_pszNotification_Dir = (char *)malloc(strlen(psz) + 1);
	strcpy(_pszNotification_Dir, psz);

	// Tell the thread that we have a directory to care about.
	SetEvent(_hFindNotification_NewDir);

	hr = S_OK;
Cleanup:
	LeaveCriticalSection(&_csNewDir);
	return hr;
Error:
	Assert(FAILED(hr));
	if (_hFindNotification_Stop != NULL)
		CloseHandle(_hFindNotification_Stop);
	if (_hFindNotification_NewDir != NULL)
		CloseHandle(_hFindNotification_NewDir);
	goto Cleanup;
}

// Pump any waiting messages in the message queue.
static void
PumpWaitingMessages(void)
{
	MSG msg;

	//
	// Read all of the messages in this next loop,
	// removing each message as we read it.
	//
	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	{
		//
		// If it's a quit message, we're out of here.
		//
		if (msg.message == WM_QUIT)
		{
			break;
		}

		//
		// Otherwise, dispatch the message.
		//
		DispatchMessage(&msg);
	}
}

//
// Thread procedure for the file/directory notification
// thread. This thread is created for the first time when
// some calls watch_dir.
//
void
CSVNWorkingCopy::FileNotificationThreadProc(void *pv)
{
	USES_CONVERSION;
	CSVNWorkingCopy *wc;
	// Keep track of the current directory we're watching.
	CHAR *pszCurrentDir = NULL;
	HANDLE aHandles[3];
	DWORD dw;
	CComBSTR sbstr;

	// Initialize COM on this thread
	if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
		abort();

	wc = static_cast<CSVNWorkingCopy *>(pv);

	// Wait for initial all clear.
	WaitForSingleObject(wc->_hFindNotification_NewDir, INFINITE);

	aHandles[1] = wc->_hFindNotification_NewDir;
	aHandles[2] = wc->_hFindNotification_Stop;

NewDirectory:
	if (wc->_hFindNotification != NULL)
	{
		FindCloseChangeNotification(wc->_hFindNotification);
	}

	// Enter critical section to lock down _pszNotification_Dir
	EnterCriticalSection(&wc->_csNewDir);

	if (pszCurrentDir != NULL)
	{
		free(pszCurrentDir);
	}

	pszCurrentDir = (CHAR *)malloc(strlen(wc->_pszNotification_Dir) + 1);
	if (pszCurrentDir == NULL)
	{
		abort();
	}

	strcpy(pszCurrentDir, wc->_pszNotification_Dir);

	// Leave the critical section.
	LeaveCriticalSection(&wc->_csNewDir);

	sbstr.Empty();
	sbstr = A2BSTR(pszCurrentDir);

	wc->_hFindNotification = FindFirstChangeNotification(
		pszCurrentDir, FALSE,
		FILE_NOTIFY_CHANGE_FILE_NAME |
		FILE_NOTIFY_CHANGE_LAST_WRITE);
	if (wc->_hFindNotification == INVALID_HANDLE_VALUE)
	{
		abort();
	}

	aHandles[0] = wc->_hFindNotification;

	while (1)
	{
		dw = MsgWaitForMultipleObjects(
			3, aHandles,
			FALSE, INFINITE, QS_ALLINPUT);
		switch (dw)
		{
		// Change notification
		case WAIT_OBJECT_0:
			wc->Fire_RefreshFiles(sbstr);
			if (!FindNextChangeNotification(wc->_hFindNotification))
				abort();
			continue;
		// New directory
		case WAIT_OBJECT_0 + 1:
			goto NewDirectory;
		// End Thread
		case WAIT_OBJECT_0 + 2:
			_endthread();
		// Since this thread is COM enabled,
		// we have to be good citizens, and
		// pump any incoming messages to
		// our thread, so that we prevent broadcasted
		// SendMessage calls from hanging.
		case WAIT_OBJECT_0 + 3:
			PumpWaitingMessages();
			continue;
		}
	}
}

STDMETHODIMP
CSVNWorkingCopy::wc_statuses(BSTR bstrPath, SAFEARRAY **ppsa)
{
	USES_CONVERSION;
	HRESULT hr;
	apr_hash_t *hash;
	svn_error_t *error;
	svn_wc_status_t *status;
	svn_string_t *path;
	apr_hash_index_t *hi;
	SAFEARRAY *psa;
	SAFEARRAYBOUND rgsBound;
	IDispatch **paDisp;
	apr_size_t klen;
	int i;
	apr_size_t count;
	CHAR *pszKey;
	CComObject<CSVNStatus> *com_status = NULL;
	svn_boolean_t fLockedSA = FALSE;

	hash = apr_make_hash(g_pool);
	path = svn_string_create(W2A(bstrPath), g_pool);
	error = svn_wc_statuses(hash, path, FALSE, g_pool);
	if (error) {
		hr = convert_err_to_hresult(error);
		goto Cleanup;
	}

	count = apr_hash_count(hash);
	rgsBound.cElements = count;
	rgsBound.lLbound = 0;

	psa = SafeArrayCreate(VT_DISPATCH, 1, &rgsBound);
	if (psa == NULL)
		abort();

	hr = SafeArrayAccessData(psa, (void **)&paDisp);
	if (FAILED(hr))
		goto Cleanup;
	fLockedSA = TRUE;

	for (i = 0, hi = apr_hash_first(hash); hi; i++, hi = apr_hash_next(hi)) {
		apr_hash_this(hi, (const void **)&pszKey, &klen, (void **)&status);
		hr = CComObject<CSVNStatus>::CreateInstance(&com_status);
		if (FAILED(hr))
			goto Cleanup;
		// This is what we want since the hash key is an absolute path.
		pszKey = ((svn_string_t *)apr_hash_get (status->entry->attributes,
							   (const void *)SVN_WC_ENTRY_ATTR_NAME,
							   strlen(SVN_WC_ENTRY_ATTR_NAME)))->data;
		// SVN_WC_ENTRY_THIS_DIR is ".", we don't care about its status.
		if (strcmp(pszKey, SVN_WC_ENTRY_THIS_DIR) == 0) {
			delete com_status;
			com_status = NULL;
			// Pretend the iteration didn't happen.
			i--;
			continue;
		}
		hr = com_status->init(status, pszKey);
		if (FAILED(hr))
			goto Cleanup;
		hr = com_status->QueryInterface(&paDisp[i]);
		if (FAILED(hr))
			goto Cleanup;

		// NULL out the local variable,
		// the COM reference count is now owned by paDisp[i]
		com_status = NULL;
	}

	SafeArrayUnaccessData(psa);
	fLockedSA = FALSE;

	if (rgsBound.cElements > i) {
		rgsBound.cElements = i;
		hr = SafeArrayRedim(psa, &rgsBound);
		if (FAILED(hr))
			goto Cleanup;
	}

	*ppsa = psa;

	hr = S_OK;
Cleanup:
	if (fLockedSA)
		SafeArrayUnaccessData(psa);
	delete com_status;
	svn_pool_clear(g_pool);
	return hr;
}
<|endoftext|>


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

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"
#ifndef _SVTOOLS_EDITBROWSEBOX_HXX_
#include "editbrowsebox.hxx"
#endif
#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLE_HPP_
#include <com/sun/star/accessibility/XAccessible.hpp>
#endif
#ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLEEVENTID_HPP_
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#endif
#ifndef _SVTOOLS_ACCESSIBILEEDITBROWSEBOXTABLECELL_HXX
#include "editbrowseboxcell.hxx"
#endif
#ifndef SVTOOLS_EDITBROWSEBOX_IMPL_HXX
#include "editbrowseboximpl.hxx"
#endif
#ifndef _COMPHELPER_TYPES_HXX_
#include <comphelper/types.hxx>
#endif
#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
#include <toolkit/helper/vclunohelper.hxx>
#endif
#ifndef _SVTOOLS_ACCESSIBLEBROWSEBOXCHECKBOXCELL_HXX
#include "AccessibleBrowseBoxCheckBoxCell.hxx"
#endif // _SVTOOLS_ACCESSIBLEBROWSEBOXCHECKBOXCELL_HXX

namespace svt
{
    using namespace com::sun::star::accessibility;
    using namespace com::sun::star::uno;
    using namespace ::com::sun::star::accessibility::AccessibleEventId;

// -----------------------------------------------------------------------------
Reference< XAccessible > EditBrowseBox::CreateAccessibleCheckBoxCell(long _nRow, USHORT _nColumnPos,const TriState& eState,sal_Bool _bEnabled)
{
    XACC xAcc = GetAccessible();
    Reference<XAccessibleContext> xAccContext = xAcc->getAccessibleContext();
    return new AccessibleCheckBoxCell(xAccContext->getAccessibleChild( ::svt::BBINDEX_TABLE )
        ,*this
        ,NULL
        ,_nRow
        ,_nColumnPos
        ,eState
        ,_bEnabled);
}
// -----------------------------------------------------------------------------
Reference< XAccessible > EditBrowseBox::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos )
{
    return BrowseBox::CreateAccessibleCell( _nRow, _nColumnPos );
}
// -----------------------------------------------------------------------------
sal_Int32 EditBrowseBox::GetAccessibleControlCount() const
{
    return IsEditing() ? 1 : 0;
}
// -----------------------------------------------------------------------------
void EditBrowseBox::implCreateActiveAccessible( )
{
    DBG_ASSERT( IsEditing(), "EditBrowseBox::implCreateActiveAccessible: not to be called if we're not editing currently!" );
    DBG_ASSERT( !m_aImpl->m_xActiveCell.is(), "EditBrowseBox::implCreateActiveAccessible: not to be called if the old one is still alive!" );

    if ( !m_aImpl->m_xActiveCell.is() && IsEditing() )
    {
         Reference< XAccessible > xCont = aController->GetWindow().GetAccessible();
         Reference< XAccessible > xMy = GetAccessible();
         if ( xMy.is() && xCont.is() )
          {
             m_aImpl->m_xActiveCell = m_aImpl->m_pActiveCell = new EditBrowseBoxTableCellAccess(
                 xMy,                                                       // parent accessible
                 xCont,                                                     // control accessible
                 VCLUnoHelper::GetInterface( &aController->GetWindow() ),   // focus window (for notifications)
                 *this,                                                     // the browse box
                 GetCurRow(),
                 GetColumnPos( GetCurColumnId() )
             );

             commitBrowseBoxEvent( CHILD, makeAny( m_aImpl->m_xActiveCell ), Any() );
          }
    }
}

// -----------------------------------------------------------------------------
Reference< XAccessible > EditBrowseBox::CreateAccessibleControl( sal_Int32
#ifdef DBG_UTIL
_nIndex
#endif
)
{
    DBG_ASSERT( 0 == _nIndex, "EditBrowseBox::CreateAccessibleControl: invalid index!" );

    if ( isAccessibleAlive() )
    {
        if ( !m_aImpl->m_xActiveCell.is() )
            implCreateActiveAccessible();
    }

    return m_aImpl->m_xActiveCell;
}
// -----------------------------------------------------------------------------
Reference<XAccessible > EditBrowseBox::CreateAccessibleRowHeader( sal_Int32 _nRow )
{
    return BrowseBox::CreateAccessibleRowHeader( _nRow );
}
// -----------------------------------------------------------------------------
void EditBrowseBoxImpl::clearActiveCell()
{
    try
    {
        ::comphelper::disposeComponent(m_xActiveCell);
    }
    catch(const Exception&)
    {
        OSL_ENSURE( sal_False, "EditBrowseBoxImpl::clearActiveCell: caught an exception while disposing the AccessibleCell!" );
    }

    m_pActiveCell = NULL;
    m_xActiveCell = NULL;
}
// -----------------------------------------------------------------------------
void EditBrowseBox::GrabTableFocus()
{
    if ( aController.Is() )
        aController->GetWindow().GrabFocus();
}
//------------------------------------------------------------------------------
void EditBrowseBox::DetermineFocus( const sal_uInt16 _nGetFocusFlags )
{
    sal_Bool bFocus = sal_False;
    for (Window* pWindow = Application::GetFocusWindow();
         pWindow && !bFocus;
         pWindow = pWindow->GetParent())
         bFocus = pWindow == this;

    if (bFocus != bHasFocus)
    {
        bHasFocus = bFocus;

        if ( GetBrowserFlags( ) & EBBF_SMART_TAB_TRAVEL )
        {
            if  (   bHasFocus                           // we got the focus
                &&  ( _nGetFocusFlags & GETFOCUS_TAB )  // using the TAB key
                )
            {
                long nRows = GetRowCount();
                USHORT nCols = ColCount();

                if ( ( nRows > 0 ) && ( nCols > 0 ) )
                {
                    if ( _nGetFocusFlags & GETFOCUS_FORWARD )
                    {
                        if ( GetColumnId( 0 ) != 0 )
                        {
                            GoToRowColumnId( 0, GetColumnId( 0 ) );
                        }
                        else
                        {   // the first column is the handle column -> not focussable
                            if ( nCols > 1 )
                                GoToRowColumnId( 0, GetColumnId( 1 ) );
                        }
                    }
                    else if ( _nGetFocusFlags & GETFOCUS_BACKWARD )
                    {
                        GoToRowColumnId( nRows - 1, GetColumnId( nCols -1 ) );
                    }
                }
            }
        }
    }
}
// -----------------------------------------------------------------------------
Rectangle EditBrowseBox::GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 _nIndex)
{
    Rectangle aRect;
    if ( SeekRow(_nRow) )
    {
        CellController* pController = GetController( _nRow,GetColumnId( _nColumnPos ) );
        if ( pController )
            aRect = pController->GetWindow().GetCharacterBounds(_nIndex);
    }
    return aRect;
}
// -----------------------------------------------------------------------------
sal_Int32 EditBrowseBox::GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint)
{
    sal_Int32 nRet = -1;
    if ( SeekRow(_nRow) )
    {
        CellController* pController = GetController( _nRow, GetColumnId( _nColumnPos ) );
        if ( pController )
            nRet = pController->GetWindow().GetIndexForPoint(_rPoint);
    }
    return nRet;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
} // namespace svt
// -----------------------------------------------------------------------------

<commit_msg>INTEGRATION: CWS sb59 (1.12.64); FILE MERGED 2006/07/25 08:52:50 sb 1.12.64.1: #i67487# Made code warning-free (wntmsci10).<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: editbrowsebox2.cxx,v $
 *
 *  $Revision: 1.14 $
 *
 *  last change: $Author: obo $ $Date: 2006-10-12 15:07:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"
#ifndef _SVTOOLS_EDITBROWSEBOX_HXX_
#include "editbrowsebox.hxx"
#endif
#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLE_HPP_
#include <com/sun/star/accessibility/XAccessible.hpp>
#endif
#ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLEEVENTID_HPP_
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#endif
#ifndef _SVTOOLS_ACCESSIBILEEDITBROWSEBOXTABLECELL_HXX
#include "editbrowseboxcell.hxx"
#endif
#ifndef SVTOOLS_EDITBROWSEBOX_IMPL_HXX
#include "editbrowseboximpl.hxx"
#endif
#ifndef _COMPHELPER_TYPES_HXX_
#include <comphelper/types.hxx>
#endif
#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
#include <toolkit/helper/vclunohelper.hxx>
#endif
#ifndef _SVTOOLS_ACCESSIBLEBROWSEBOXCHECKBOXCELL_HXX
#include "AccessibleBrowseBoxCheckBoxCell.hxx"
#endif // _SVTOOLS_ACCESSIBLEBROWSEBOXCHECKBOXCELL_HXX

namespace svt
{
    using namespace com::sun::star::accessibility;
    using namespace com::sun::star::uno;
    using namespace ::com::sun::star::accessibility::AccessibleEventId;

// -----------------------------------------------------------------------------
Reference< XAccessible > EditBrowseBox::CreateAccessibleCheckBoxCell(long _nRow, USHORT _nColumnPos,const TriState& eState,sal_Bool _bEnabled)
{
    XACC xAcc = GetAccessible();
    Reference<XAccessibleContext> xAccContext = xAcc->getAccessibleContext();
    return new AccessibleCheckBoxCell(xAccContext->getAccessibleChild( ::svt::BBINDEX_TABLE )
        ,*this
        ,NULL
        ,_nRow
        ,_nColumnPos
        ,eState
        ,_bEnabled);
}
// -----------------------------------------------------------------------------
Reference< XAccessible > EditBrowseBox::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos )
{
    return BrowseBox::CreateAccessibleCell( _nRow, _nColumnPos );
}
// -----------------------------------------------------------------------------
sal_Int32 EditBrowseBox::GetAccessibleControlCount() const
{
    return IsEditing() ? 1 : 0;
}
// -----------------------------------------------------------------------------
void EditBrowseBox::implCreateActiveAccessible( )
{
    DBG_ASSERT( IsEditing(), "EditBrowseBox::implCreateActiveAccessible: not to be called if we're not editing currently!" );
    DBG_ASSERT( !m_aImpl->m_xActiveCell.is(), "EditBrowseBox::implCreateActiveAccessible: not to be called if the old one is still alive!" );

    if ( !m_aImpl->m_xActiveCell.is() && IsEditing() )
    {
         Reference< XAccessible > xCont = aController->GetWindow().GetAccessible();
         Reference< XAccessible > xMy = GetAccessible();
         if ( xMy.is() && xCont.is() )
          {
             m_aImpl->m_xActiveCell = m_aImpl->m_pActiveCell = new EditBrowseBoxTableCellAccess(
                 xMy,                                                       // parent accessible
                 xCont,                                                     // control accessible
                 VCLUnoHelper::GetInterface( &aController->GetWindow() ),   // focus window (for notifications)
                 *this,                                                     // the browse box
                 GetCurRow(),
                 GetColumnPos( GetCurColumnId() )
             );

             commitBrowseBoxEvent( CHILD, makeAny( m_aImpl->m_xActiveCell ), Any() );
          }
    }
}

// -----------------------------------------------------------------------------
Reference< XAccessible > EditBrowseBox::CreateAccessibleControl( sal_Int32
#ifdef DBG_UTIL
_nIndex
#endif
)
{
    DBG_ASSERT( 0 == _nIndex, "EditBrowseBox::CreateAccessibleControl: invalid index!" );

    if ( isAccessibleAlive() )
    {
        if ( !m_aImpl->m_xActiveCell.is() )
            implCreateActiveAccessible();
    }

    return m_aImpl->m_xActiveCell;
}
// -----------------------------------------------------------------------------
Reference<XAccessible > EditBrowseBox::CreateAccessibleRowHeader( sal_Int32 _nRow )
{
    return BrowseBox::CreateAccessibleRowHeader( _nRow );
}
// -----------------------------------------------------------------------------
void EditBrowseBoxImpl::clearActiveCell()
{
    try
    {
        ::comphelper::disposeComponent(m_xActiveCell);
    }
    catch(const Exception&)
    {
        OSL_ENSURE( sal_False, "EditBrowseBoxImpl::clearActiveCell: caught an exception while disposing the AccessibleCell!" );
    }

    m_pActiveCell = NULL;
    m_xActiveCell = NULL;
}
// -----------------------------------------------------------------------------
void EditBrowseBox::GrabTableFocus()
{
    if ( aController.Is() )
        aController->GetWindow().GrabFocus();
}
//------------------------------------------------------------------------------
void EditBrowseBox::DetermineFocus( const sal_uInt16 _nGetFocusFlags )
{
    sal_Bool bFocus = sal_False;
    for (Window* pWindow = Application::GetFocusWindow();
         pWindow && !bFocus;
         pWindow = pWindow->GetParent())
         bFocus = pWindow == this;

    if (bFocus != bHasFocus)
    {
        bHasFocus = bFocus;

        if ( GetBrowserFlags( ) & EBBF_SMART_TAB_TRAVEL )
        {
            if  (   bHasFocus                           // we got the focus
                &&  ( _nGetFocusFlags & GETFOCUS_TAB )  // using the TAB key
                )
            {
                long nRows = GetRowCount();
                USHORT nCols = ColCount();

                if ( ( nRows > 0 ) && ( nCols > 0 ) )
                {
                    if ( _nGetFocusFlags & GETFOCUS_FORWARD )
                    {
                        if ( GetColumnId( 0 ) != 0 )
                        {
                            GoToRowColumnId( 0, GetColumnId( 0 ) );
                        }
                        else
                        {   // the first column is the handle column -> not focussable
                            if ( nCols > 1 )
                                GoToRowColumnId( 0, GetColumnId( 1 ) );
                        }
                    }
                    else if ( _nGetFocusFlags & GETFOCUS_BACKWARD )
                    {
                        GoToRowColumnId( nRows - 1, GetColumnId( nCols -1 ) );
                    }
                }
            }
        }
    }
}
// -----------------------------------------------------------------------------
Rectangle EditBrowseBox::GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 _nIndex)
{
    Rectangle aRect;
    if ( SeekRow(_nRow) )
    {
        CellController* pController = GetController(
            _nRow, GetColumnId( sal::static_int_cast< USHORT >(_nColumnPos) ) );
        if ( pController )
            aRect = pController->GetWindow().GetCharacterBounds(_nIndex);
    }
    return aRect;
}
// -----------------------------------------------------------------------------
sal_Int32 EditBrowseBox::GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint)
{
    sal_Int32 nRet = -1;
    if ( SeekRow(_nRow) )
    {
        CellController* pController = GetController(
            _nRow, GetColumnId( sal::static_int_cast< USHORT >(_nColumnPos) ) );
        if ( pController )
            nRet = pController->GetWindow().GetIndexForPoint(_rPoint);
    }
    return nRet;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
} // namespace svt
// -----------------------------------------------------------------------------

<|endoftext|>