<commit_before>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#if !BOOST_PP_IS_ITERATING

#ifndef LUABIND_SIGNATURE_MATCH_HPP_INCLUDED
#define LUABIND_SIGNATURE_MATCH_HPP_INCLUDED

#include <luabind/config.hpp>

#include <boost/config.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/cat.hpp>

#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/int.hpp>
#include <boost/type_traits.hpp>

#include <luabind/detail/policy.hpp>
#include <luabind/detail/primitives.hpp>
#include <luabind/detail/object_rep.hpp>
#include <luabind/detail/class_rep.hpp>
#include <luabind/detail/most_derived.hpp>

namespace luabind
{

	namespace detail
	{
		template<class A>
		struct constructor_arity_helper
		{
			BOOST_STATIC_CONSTANT(int, value = 1);
		};

		template<>
		struct constructor_arity_helper<luabind::detail::null_type>
		{
			BOOST_STATIC_CONSTANT(int, value = 0);
		};
	}

#define LUABIND_SUM(z, n, _) detail::constructor_arity_helper<A##n >::value +

	template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(LUABIND_MAX_ARITY, class A, detail::null_type)>
	struct constructor
	{
		BOOST_STATIC_CONSTANT(int, arity = BOOST_PP_REPEAT(LUABIND_MAX_ARITY, LUABIND_SUM, _) 0);
	};

#undef LUABIND_SUM
}

namespace luabind { namespace detail
{
#define LUABIND_MATCH_DECL(Z, N,_) \
    typedef typename find_conversion_policy< \
        N + 1 \
      , Policies \
    >::type BOOST_PP_CAT(converter_policy, N); \
\
	typedef typename boost::mpl::apply_wrap2< \
		BOOST_PP_CAT(converter_policy, N), BOOST_PP_CAT(A, N), lua_to_cpp \
	>::type BOOST_PP_CAT(converter, N); \
\
	int BOOST_PP_CAT(r, N) = BOOST_PP_CAT(converter, N)::match( \
        L \
      , LUABIND_DECORATE_TYPE(BOOST_PP_CAT(A, N)) \
      , start_index + current_index \
    ); \
\
    current_index += BOOST_PP_CAT(converter_policy, N)::has_arg; \
\
    if (BOOST_PP_CAT(r, N) < 0) return -1; \
	else m += BOOST_PP_CAT(r, N);

	template<int N> struct match_constructor;

	#define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/signature_match.hpp>, 2))
	#include BOOST_PP_ITERATE()

#undef LUABIND_MATCH_DECL

	// this is a function that checks if the lua stack (starting at the given start_index) matches
	// the types in the constructor type given as 3:rd parameter. It uses the Policies given as
	// 4:th parameter to do the matching. It returns the total number of cast-steps that needs to
	// be taken in order to match the parameters on the lua stack to the given parameter-list. Or,
	// if the parameter doesn't match, it returns -1.
	template<
		BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)
	  , class Policies
	>
	int match_params(
		lua_State* L
	  , int start_index
	  , const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>* c
	  , const Policies* p)
	{
		typedef constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig_t;
		return match_constructor<sig_t::arity>::apply(
			L, start_index, c, p);
	}

	template<class Sig, int StartIndex, class Policies>
	struct constructor_match
	{
		inline static int apply(lua_State* L)
		{
			int top = lua_gettop(L) - StartIndex + 1;
			if (top != Sig::arity) return -1;

			return match_params(L, StartIndex, (Sig*)0, (Policies*)0);
		}};

	#define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/signature_match.hpp>, 1))
	#include BOOST_PP_ITERATE()

}}

#endif // LUABIND_SIGNATURE_MATCH_HPP_INCLUDED

#elif BOOST_PP_ITERATION_FLAGS() == 1

#define N BOOST_PP_ITERATION()

	// non-const non-member function this as a pointer
	template<
	    class WrappedClass
	  , class Policies
	  , class R
		BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
			BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
	>
	int match(R(*)(
		BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A))
	  , lua_State* L
	  , WrappedClass*
	  , Policies const*)
	{
		typedef constructor<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)> ParameterTypes;
		return match_params(
			L, 1, (ParameterTypes*)0, (Policies*)0);
	}

# if (BOOST_PP_ITERATION() < (LUABIND_MAX_ARITY - 1))

	// non-const member function
	template<
		class T
	  , class WrappedClass
	  , class Policies
	  , class R
		BOOST_PP_COMMA_IF(N)
			BOOST_PP_ENUM_PARAMS(N, class A)
	>
	int match(
		R(T::*)(BOOST_PP_ENUM_PARAMS(N, A))
	  , lua_State* L
	  , WrappedClass*
	  , Policies const*)
	{
		typedef constructor<
			BOOST_DEDUCED_TYPENAME most_derived<T,WrappedClass>::type&
		    BOOST_PP_ENUM_TRAILING_PARAMS(N, A)
		> params_t;

		return match_params(
			L, 1, (params_t*)0, (Policies*)0);
	}

	// const member function
	template<
		class T
	  , class WrappedClass
	  , class Policies
	  , class R
			BOOST_PP_COMMA_IF(N)
				BOOST_PP_ENUM_PARAMS(N, class A)
	>
	int match(
		R(T::*)(BOOST_PP_ENUM_PARAMS(N, A)) const
	  , lua_State* L
	  , WrappedClass*
	  , Policies const* policies)
	{
		typedef constructor<
			BOOST_DEDUCED_TYPENAME most_derived<T,WrappedClass>::type const&
			BOOST_PP_ENUM_TRAILING_PARAMS(N, A)
		> params_t;
		return match_params(
			L, 1, (params_t*)0, (Policies*)0);
	}

# endif

#undef N

#elif BOOST_PP_ITERATION_FLAGS() == 2

#define N BOOST_PP_ITERATION()

	template<>
	struct match_constructor<N>
	{
		template<
			BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)
		  , class Policies
		>
		static int apply(
			lua_State* L
		  , int start_index
		  , const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*
		  , const Policies*)
		{
			int m = 0;
#if N
            int current_index = 0;
#endif
			// Removes unreferenced local variable warning on VC7.
			(void)start_index;
			(void)L;

            BOOST_PP_REPEAT(N, LUABIND_MATCH_DECL, _)
			return m;
		}
	};

#undef N

#endif

<commit_msg>Add constructor<>::signature MPL sequence.<commit_after>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#if !BOOST_PP_IS_ITERATING

#ifndef LUABIND_SIGNATURE_MATCH_HPP_INCLUDED
#define LUABIND_SIGNATURE_MATCH_HPP_INCLUDED

#include <luabind/config.hpp>

#include <boost/config.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>

#include <boost/mpl/vector.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/iterator_range.hpp>
#include <boost/mpl/size.hpp>

#include <luabind/detail/policy.hpp>
#include <luabind/detail/primitives.hpp>
#include <luabind/detail/object_rep.hpp>
#include <luabind/detail/class_rep.hpp>
#include <luabind/detail/most_derived.hpp>

namespace luabind
{

	template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(LUABIND_MAX_ARITY, class A, detail::null_type)>
	struct constructor
	{
		typedef BOOST_PP_CAT(boost::mpl::vector, BOOST_PP_INC(LUABIND_MAX_ARITY))<
			void, BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)
		> signature0;

		typedef typename boost::mpl::find<
			signature0, detail::null_type>::type first_null_element;

		typedef boost::mpl::iterator_range<
			typename boost::mpl::begin<signature0>::type
		  , first_null_element
		> signature;

		BOOST_STATIC_CONSTANT(int, arity = boost::mpl::size<signature>::value - 1);
	};

}

namespace luabind { namespace detail
{
#define LUABIND_MATCH_DECL(Z, N,_) \
    typedef typename find_conversion_policy< \
        N + 1 \
      , Policies \
    >::type BOOST_PP_CAT(converter_policy, N); \
\
	typedef typename boost::mpl::apply_wrap2< \
		BOOST_PP_CAT(converter_policy, N), BOOST_PP_CAT(A, N), lua_to_cpp \
	>::type BOOST_PP_CAT(converter, N); \
\
	int BOOST_PP_CAT(r, N) = BOOST_PP_CAT(converter, N)::match( \
        L \
      , LUABIND_DECORATE_TYPE(BOOST_PP_CAT(A, N)) \
      , start_index + current_index \
    ); \
\
    current_index += BOOST_PP_CAT(converter_policy, N)::has_arg; \
\
    if (BOOST_PP_CAT(r, N) < 0) return -1; \
	else m += BOOST_PP_CAT(r, N);

	template<int N> struct match_constructor;

	#define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/signature_match.hpp>, 2))
	#include BOOST_PP_ITERATE()

#undef LUABIND_MATCH_DECL

	// this is a function that checks if the lua stack (starting at the given start_index) matches
	// the types in the constructor type given as 3:rd parameter. It uses the Policies given as
	// 4:th parameter to do the matching. It returns the total number of cast-steps that needs to
	// be taken in order to match the parameters on the lua stack to the given parameter-list. Or,
	// if the parameter doesn't match, it returns -1.
	template<
		BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)
	  , class Policies
	>
	int match_params(
		lua_State* L
	  , int start_index
	  , const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>* c
	  , const Policies* p)
	{
		typedef constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig_t;
		return match_constructor<sig_t::arity>::apply(
			L, start_index, c, p);
	}

	template<class Sig, int StartIndex, class Policies>
	struct constructor_match
	{
		inline static int apply(lua_State* L)
		{
			int top = lua_gettop(L) - StartIndex + 1;
			if (top != Sig::arity) return -1;

			return match_params(L, StartIndex, (Sig*)0, (Policies*)0);
		}};

	#define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/signature_match.hpp>, 1))
	#include BOOST_PP_ITERATE()

}}

#endif // LUABIND_SIGNATURE_MATCH_HPP_INCLUDED

#elif BOOST_PP_ITERATION_FLAGS() == 1

#define N BOOST_PP_ITERATION()

	// non-const non-member function this as a pointer
	template<
	    class WrappedClass
	  , class Policies
	  , class R
		BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
			BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
	>
	int match(R(*)(
		BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A))
	  , lua_State* L
	  , WrappedClass*
	  , Policies const*)
	{
		typedef constructor<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)> ParameterTypes;
		return match_params(
			L, 1, (ParameterTypes*)0, (Policies*)0);
	}

# if (BOOST_PP_ITERATION() < (LUABIND_MAX_ARITY - 1))

	// non-const member function
	template<
		class T
	  , class WrappedClass
	  , class Policies
	  , class R
		BOOST_PP_COMMA_IF(N)
			BOOST_PP_ENUM_PARAMS(N, class A)
	>
	int match(
		R(T::*)(BOOST_PP_ENUM_PARAMS(N, A))
	  , lua_State* L
	  , WrappedClass*
	  , Policies const*)
	{
		typedef constructor<
			BOOST_DEDUCED_TYPENAME most_derived<T,WrappedClass>::type&
		    BOOST_PP_ENUM_TRAILING_PARAMS(N, A)
		> params_t;

		return match_params(
			L, 1, (params_t*)0, (Policies*)0);
	}

	// const member function
	template<
		class T
	  , class WrappedClass
	  , class Policies
	  , class R
			BOOST_PP_COMMA_IF(N)
				BOOST_PP_ENUM_PARAMS(N, class A)
	>
	int match(
		R(T::*)(BOOST_PP_ENUM_PARAMS(N, A)) const
	  , lua_State* L
	  , WrappedClass*
	  , Policies const* policies)
	{
		typedef constructor<
			BOOST_DEDUCED_TYPENAME most_derived<T,WrappedClass>::type const&
			BOOST_PP_ENUM_TRAILING_PARAMS(N, A)
		> params_t;
		return match_params(
			L, 1, (params_t*)0, (Policies*)0);
	}

# endif

#undef N

#elif BOOST_PP_ITERATION_FLAGS() == 2

#define N BOOST_PP_ITERATION()

	template<>
	struct match_constructor<N>
	{
		template<
			BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)
		  , class Policies
		>
		static int apply(
			lua_State* L
		  , int start_index
		  , const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*
		  , const Policies*)
		{
			int m = 0;
#if N
            int current_index = 0;
#endif
			// Removes unreferenced local variable warning on VC7.
			(void)start_index;
			(void)L;

            BOOST_PP_REPEAT(N, LUABIND_MATCH_DECL, _)
			return m;
		}
	};

#undef N

#endif

<|endoftext|>


<commit_before>#include "MCMessageParser.h"

#include <libetpan/libetpan.h>
#if __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#endif

#include "MCDefines.h"
#include "MCAttachment.h"
#include "MCMessageHeader.h"
#include "MCHTMLRenderer.h"
#include "MCHTMLBodyRendererTemplateCallback.h"

using namespace mailcore;

MessageParser * MessageParser::messageParserWithData(Data * data)
{
    MessageParser * parser = new MessageParser(data);
    return (MessageParser *) parser->autorelease();
}

MessageParser * MessageParser::messageParserWithContentsOfFile(String * filename)
{
    Data * data = Data::dataWithContentsOfFile(filename);
    return messageParserWithData(data);
}

void MessageParser::init()
{
    mData = NULL;
    mMainPart = NULL;
#if __APPLE__
    mNSData = NULL;
#endif
}

void MessageParser::setBytes(char * dataBytes, unsigned int dataLength)
{
    const char * start = NULL;
    unsigned int length = 0;
    if (dataLength > 5) {
        if (strncmp(dataBytes, "From ", 5) == 0) {
            start = dataBytes;
            for(unsigned int i = 0 ; i < dataLength ; i ++) {
                if (start[i] == '\n') {
                    start = start + i + 1;
                    length = dataLength - (i + 1);
                    break;
                }
            }
        }
    }
    if (start != NULL) {
        dataBytes = (char *) start;
        dataLength = length;
    }

    mailmessage * msg;
    struct mailmime * mime;

    msg = data_message_init(dataBytes, dataLength);
    mailmessage_get_bodystructure(msg, &mime);
    mMainPart = (AbstractPart *) Attachment::attachmentsWithMIME(msg->msg_mime)->retain();
    mMainPart->applyUniquePartID();

    size_t cur_token = 0;
    struct mailimf_fields * fields;
    int r = mailimf_envelope_and_optional_fields_parse(dataBytes, dataLength, &cur_token, &fields);
    if (r == MAILIMAP_NO_ERROR) {
        header()->importIMFFields(fields);
        mailimf_fields_free(fields);
    }
    mailmessage_free(msg);

    setupPartID();
}

MessageParser::MessageParser()
{
    init();
}

MessageParser::MessageParser(Data * data)
{
    init();

    setBytes(data->bytes(), data->length());
    mData = (Data *) data->retain();
}

MessageParser::MessageParser(MessageParser * other) : AbstractMessage(other)
{
    init();
    MC_SAFE_REPLACE_RETAIN(Data, mData, other->mData);
    MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, other->mMainPart);
    setupPartID();
}

MessageParser::~MessageParser()
{
    MC_SAFE_RELEASE(mMainPart);
    MC_SAFE_RELEASE(mData);
#if __APPLE__
    if (mNSData != NULL) {
        CFRelease(mNSData);
    }
#endif
}

AbstractPart * MessageParser::mainPart()
{
    return mMainPart;
}

Data * MessageParser::data()
{
#if __APPLE__
    if (mNSData != NULL) {
        return dataFromNSData();
    }
#endif
    return mData;
}

String * MessageParser::description()
{
    String * result = String::string();
    result->appendUTF8Format("<%s:%p ", MCUTF8(className()), this);
    result->appendUTF8Format("<%p>", mMainPart);
    if (mMainPart != NULL) {
        result->appendString(mMainPart->description());
    }
    result->appendUTF8Characters(">");

    return result;
}

HashMap * MessageParser::serializable()
{
    HashMap * result = AbstractMessage::serializable();
    if (mMainPart != NULL) {
        result->setObjectForKey(MCSTR("mainPart"), mMainPart->serializable());
    }
    return result;
}

void MessageParser::importSerializable(HashMap * serializable)
{
    AbstractMessage::importSerializable(serializable);
    MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("mainPart"))));
    if (mMainPart != NULL) {
        mMainPart->applyUniquePartID();
    }
    setupPartID();
}

Object * MessageParser::copy()
{
    return new MessageParser(this);
}

AbstractPart * MessageParser::partForContentID(String * contentID)
{
    if (mainPart() == NULL) {
        return NULL;
    }
    return mainPart()->partForContentID(contentID);
}

AbstractPart * MessageParser::partForUniqueID(String * uniqueID)
{
    if (mainPart() == NULL) {
        return NULL;
    }
    return mainPart()->partForUniqueID(uniqueID);
}

String * MessageParser::htmlRendering(HTMLRendererTemplateCallback * htmlCallback)
{
    return HTMLRenderer::htmlForRFC822Message(this, NULL, htmlCallback);
}

String * MessageParser::htmlRenderingWithDataCallback(HTMLRendererTemplateCallback * htmlCallback,
                                                      HTMLRendererRFC822Callback * dataCallback)
{
    return HTMLRenderer::htmlForRFC822Message(this, dataCallback, htmlCallback);
}

String * MessageParser::htmlBodyRendering()
{
    HTMLBodyRendererTemplateCallback * callback = new HTMLBodyRendererTemplateCallback();
    String * result = htmlRendering(callback);
    MC_SAFE_RELEASE(callback);
    return result;
}

String * MessageParser::plainTextRendering()
{
    String * html = htmlRendering(NULL);
    return html->flattenHTML();
}

String * MessageParser::plainTextBodyRendering(bool stripWhitespace)
{
    String * html = htmlBodyRendering();
    String * plainTextBodyString = html->flattenHTML();

    if (stripWhitespace) {
        plainTextBodyString = plainTextBodyString->stripWhitespace();
    }
    return plainTextBodyString;
}

void MessageParser::setupPartID()
{
    if (mMainPart == NULL) {
        return;
    }
    recursiveSetupPartIDWithPart(mMainPart, MCSTR(""));
}

void MessageParser::recursiveSetupPartIDWithPart(mailcore::AbstractPart * part,
                                                 mailcore::String * partIDPrefix)
{
    switch (part->partType()) {
        case PartTypeSingle:
        {
            String * partID = NULL;
            if (partIDPrefix->length() == 0) {
                partID = MCSTR("1");
            }
            else {
                partID = partIDPrefix;
            }
            return recursiveSetupPartIDWithSinglePart((Attachment *) part, partID);
        }
        case PartTypeMessage:
        {
            String * partID = NULL;
            if (partIDPrefix->length() == 0) {
                partID = MCSTR("1");
            }
            else {
                partID = partIDPrefix;
            }
            return recursiveSetupPartIDWithMessagePart((MessagePart *) part, partID);
        }
        case PartTypeMultipartMixed:
        case PartTypeMultipartRelated:
        case PartTypeMultipartAlternative:
        case PartTypeMultipartSigned:
            return recursiveSetupPartIDWithMultipart((Multipart *) part, partIDPrefix);
        default:
            MCAssert(0);
    }
}

void MessageParser::recursiveSetupPartIDWithSinglePart(mailcore::Attachment * part,
                                                       mailcore::String * partIDPrefix)
{
    part->setPartID(partIDPrefix);
}

void MessageParser::recursiveSetupPartIDWithMessagePart(mailcore::MessagePart * part,
                                                        mailcore::String * partIDPrefix)
{
    part->setPartID(partIDPrefix);
    String * partID = NULL;
    switch (part->mainPart()->partType()) {
        case PartTypeSingle:
        case PartTypeMessage:
        {
            if (partIDPrefix->length() == 0) {
                partID = MCSTR("1");
            }
            else {
                partID = partIDPrefix->stringByAppendingUTF8Characters(".1");
            }
            break;
        }
        default:
            partID = partIDPrefix;
            break;
    }
    recursiveSetupPartIDWithPart(part->mainPart(), partID);
}

void MessageParser::recursiveSetupPartIDWithMultipart(mailcore::Multipart * part,
                                                      mailcore::String * partIDPrefix)
{
    part->setPartID(partIDPrefix);
    mc_foreacharrayIndex(idx, AbstractPart, subpart, part->parts()) {
        String * partID = NULL;
        if (partIDPrefix->length() == 0) {
            partID = String::stringWithUTF8Format("%u", idx + 1);
        }
        else {
            partID = partIDPrefix->stringByAppendingUTF8Format(".%u", idx + 1);
        }
        recursiveSetupPartIDWithPart(subpart, partID);
    }
}

static void * createObject()
{
    return new MessageParser();
}

INITIALIZE(MessageParser)
{
    Object::registerObjectConstructor("mailcore::MessageParser", &createObject);
}
<commit_msg>Fallback if file doesn't exist<commit_after>#include "MCMessageParser.h"

#include <libetpan/libetpan.h>
#if __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#endif

#include "MCDefines.h"
#include "MCAttachment.h"
#include "MCMessageHeader.h"
#include "MCHTMLRenderer.h"
#include "MCHTMLBodyRendererTemplateCallback.h"

using namespace mailcore;

MessageParser * MessageParser::messageParserWithData(Data * data)
{
    MessageParser * parser = new MessageParser(data);
    return (MessageParser *) parser->autorelease();
}

MessageParser * MessageParser::messageParserWithContentsOfFile(String * filename)
{
    Data * data = Data::dataWithContentsOfFile(filename);
    if (data == NULL) {
        data = Data::data();
    }
    return messageParserWithData(data);
}

void MessageParser::init()
{
    mData = NULL;
    mMainPart = NULL;
#if __APPLE__
    mNSData = NULL;
#endif
}

void MessageParser::setBytes(char * dataBytes, unsigned int dataLength)
{
    const char * start = NULL;
    unsigned int length = 0;
    if (dataLength > 5) {
        if (strncmp(dataBytes, "From ", 5) == 0) {
            start = dataBytes;
            for(unsigned int i = 0 ; i < dataLength ; i ++) {
                if (start[i] == '\n') {
                    start = start + i + 1;
                    length = dataLength - (i + 1);
                    break;
                }
            }
        }
    }
    if (start != NULL) {
        dataBytes = (char *) start;
        dataLength = length;
    }

    mailmessage * msg;
    struct mailmime * mime;

    msg = data_message_init(dataBytes, dataLength);
    mailmessage_get_bodystructure(msg, &mime);
    mMainPart = (AbstractPart *) Attachment::attachmentsWithMIME(msg->msg_mime)->retain();
    mMainPart->applyUniquePartID();

    size_t cur_token = 0;
    struct mailimf_fields * fields;
    int r = mailimf_envelope_and_optional_fields_parse(dataBytes, dataLength, &cur_token, &fields);
    if (r == MAILIMAP_NO_ERROR) {
        header()->importIMFFields(fields);
        mailimf_fields_free(fields);
    }
    mailmessage_free(msg);

    setupPartID();
}

MessageParser::MessageParser()
{
    init();
}

MessageParser::MessageParser(Data * data)
{
    init();

    setBytes(data->bytes(), data->length());
    mData = (Data *) data->retain();
}

MessageParser::MessageParser(MessageParser * other) : AbstractMessage(other)
{
    init();
    MC_SAFE_REPLACE_RETAIN(Data, mData, other->mData);
    MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, other->mMainPart);
    setupPartID();
}

MessageParser::~MessageParser()
{
    MC_SAFE_RELEASE(mMainPart);
    MC_SAFE_RELEASE(mData);
#if __APPLE__
    if (mNSData != NULL) {
        CFRelease(mNSData);
    }
#endif
}

AbstractPart * MessageParser::mainPart()
{
    return mMainPart;
}

Data * MessageParser::data()
{
#if __APPLE__
    if (mNSData != NULL) {
        return dataFromNSData();
    }
#endif
    return mData;
}

String * MessageParser::description()
{
    String * result = String::string();
    result->appendUTF8Format("<%s:%p ", MCUTF8(className()), this);
    result->appendUTF8Format("<%p>", mMainPart);
    if (mMainPart != NULL) {
        result->appendString(mMainPart->description());
    }
    result->appendUTF8Characters(">");

    return result;
}

HashMap * MessageParser::serializable()
{
    HashMap * result = AbstractMessage::serializable();
    if (mMainPart != NULL) {
        result->setObjectForKey(MCSTR("mainPart"), mMainPart->serializable());
    }
    return result;
}

void MessageParser::importSerializable(HashMap * serializable)
{
    AbstractMessage::importSerializable(serializable);
    MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("mainPart"))));
    if (mMainPart != NULL) {
        mMainPart->applyUniquePartID();
    }
    setupPartID();
}

Object * MessageParser::copy()
{
    return new MessageParser(this);
}

AbstractPart * MessageParser::partForContentID(String * contentID)
{
    if (mainPart() == NULL) {
        return NULL;
    }
    return mainPart()->partForContentID(contentID);
}

AbstractPart * MessageParser::partForUniqueID(String * uniqueID)
{
    if (mainPart() == NULL) {
        return NULL;
    }
    return mainPart()->partForUniqueID(uniqueID);
}

String * MessageParser::htmlRendering(HTMLRendererTemplateCallback * htmlCallback)
{
    return HTMLRenderer::htmlForRFC822Message(this, NULL, htmlCallback);
}

String * MessageParser::htmlRenderingWithDataCallback(HTMLRendererTemplateCallback * htmlCallback,
                                                      HTMLRendererRFC822Callback * dataCallback)
{
    return HTMLRenderer::htmlForRFC822Message(this, dataCallback, htmlCallback);
}

String * MessageParser::htmlBodyRendering()
{
    HTMLBodyRendererTemplateCallback * callback = new HTMLBodyRendererTemplateCallback();
    String * result = htmlRendering(callback);
    MC_SAFE_RELEASE(callback);
    return result;
}

String * MessageParser::plainTextRendering()
{
    String * html = htmlRendering(NULL);
    return html->flattenHTML();
}

String * MessageParser::plainTextBodyRendering(bool stripWhitespace)
{
    String * html = htmlBodyRendering();
    String * plainTextBodyString = html->flattenHTML();

    if (stripWhitespace) {
        plainTextBodyString = plainTextBodyString->stripWhitespace();
    }
    return plainTextBodyString;
}

void MessageParser::setupPartID()
{
    if (mMainPart == NULL) {
        return;
    }
    recursiveSetupPartIDWithPart(mMainPart, MCSTR(""));
}

void MessageParser::recursiveSetupPartIDWithPart(mailcore::AbstractPart * part,
                                                 mailcore::String * partIDPrefix)
{
    switch (part->partType()) {
        case PartTypeSingle:
        {
            String * partID = NULL;
            if (partIDPrefix->length() == 0) {
                partID = MCSTR("1");
            }
            else {
                partID = partIDPrefix;
            }
            return recursiveSetupPartIDWithSinglePart((Attachment *) part, partID);
        }
        case PartTypeMessage:
        {
            String * partID = NULL;
            if (partIDPrefix->length() == 0) {
                partID = MCSTR("1");
            }
            else {
                partID = partIDPrefix;
            }
            return recursiveSetupPartIDWithMessagePart((MessagePart *) part, partID);
        }
        case PartTypeMultipartMixed:
        case PartTypeMultipartRelated:
        case PartTypeMultipartAlternative:
        case PartTypeMultipartSigned:
            return recursiveSetupPartIDWithMultipart((Multipart *) part, partIDPrefix);
        default:
            MCAssert(0);
    }
}

void MessageParser::recursiveSetupPartIDWithSinglePart(mailcore::Attachment * part,
                                                       mailcore::String * partIDPrefix)
{
    part->setPartID(partIDPrefix);
}

void MessageParser::recursiveSetupPartIDWithMessagePart(mailcore::MessagePart * part,
                                                        mailcore::String * partIDPrefix)
{
    part->setPartID(partIDPrefix);
    String * partID = NULL;
    switch (part->mainPart()->partType()) {
        case PartTypeSingle:
        case PartTypeMessage:
        {
            if (partIDPrefix->length() == 0) {
                partID = MCSTR("1");
            }
            else {
                partID = partIDPrefix->stringByAppendingUTF8Characters(".1");
            }
            break;
        }
        default:
            partID = partIDPrefix;
            break;
    }
    recursiveSetupPartIDWithPart(part->mainPart(), partID);
}

void MessageParser::recursiveSetupPartIDWithMultipart(mailcore::Multipart * part,
                                                      mailcore::String * partIDPrefix)
{
    part->setPartID(partIDPrefix);
    mc_foreacharrayIndex(idx, AbstractPart, subpart, part->parts()) {
        String * partID = NULL;
        if (partIDPrefix->length() == 0) {
            partID = String::stringWithUTF8Format("%u", idx + 1);
        }
        else {
            partID = partIDPrefix->stringByAppendingUTF8Format(".%u", idx + 1);
        }
        recursiveSetupPartIDWithPart(subpart, partID);
    }
}

static void * createObject()
{
    return new MessageParser();
}

INITIALIZE(MessageParser)
{
    Object::registerObjectConstructor("mailcore::MessageParser", &createObject);
}
<|endoftext|>


<commit_before>// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "pal.h"
#include "trace.h"
#include "utils.h"

#include <cassert>
#include <locale>
#include <codecvt>
#include <ShlObj.h>

pal::string_t pal::to_lower(const pal::string_t& in)
{
    pal::string_t ret = in;
    std::transform(ret.begin(), ret.end(), ret.begin(), ::towlower);
    return ret;
}

pal::string_t pal::to_string(int value)
{
    return std::to_wstring(value);
}

bool pal::touch_file(const pal::string_t& path)
{
    HANDLE hnd = ::CreateFileW(path.c_str(), 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hnd == INVALID_HANDLE_VALUE)
    {
        trace::verbose(_X("Failed to leave breadcrumb"), HRESULT_FROM_WIN32(GetLastError()));
        return false;
    }
    ::CloseHandle(hnd);
    return true;
}

void pal::setup_api_sets(const std::unordered_set<pal::string_t>& api_sets)
{
    if (api_sets.empty())
    {
        return;
    }

    pal::string_t path;

    (void) getenv(_X("PATH"), &path);

    // We need this ugly hack, as the PInvoked DLL's static dependencies can come from
    // some other NATIVE_DLL_SEARCH_DIRECTORIES and not necessarily side by side. However,
    // CoreCLR.dll loads PInvoke DLLs with LOAD_WITH_ALTERED_SEARCH_PATH. Note that this
    // option cannot be combined with LOAD_LIBRARY_SEARCH_USER_DIRS, so the AddDllDirectory
    // doesn't help much in telling CoreCLR where to load the PInvoke DLLs from.
    // So we resort to modifying the PATH variable on our own hoping Windows loader will do the right thing.
    for (const auto& as : api_sets)
    {
        // AddDllDirectory is still needed for Standalone App's CoreCLR load.
        ::AddDllDirectory(as.c_str());

        // Path patch is needed for static dependencies of a PInvoked DLL load out of the nuget cache.
        path.push_back(PATH_SEPARATOR);
        path.append(as);
    }

    trace::verbose(_X("Setting PATH=%s"), path.c_str());

    ::SetEnvironmentVariableW(_X("PATH"), path.c_str());
}

bool pal::getcwd(pal::string_t* recv)
{
    recv->clear();

    pal::char_t buf[MAX_PATH];
    DWORD result = GetCurrentDirectoryW(MAX_PATH, buf);
    if (result < MAX_PATH)
    {
        recv->assign(buf);
        return true;
    }
    else if (result != 0)
    {
        std::vector<pal::char_t> str;
        str.resize(result);
        result = GetCurrentDirectoryW(str.size(), str.data());
        assert(result <= str.size());
        if (result != 0)
        {
            recv->assign(str.data());
            return true;
        }
    }
    assert(result == 0);
    trace::error(_X("Failed to obtain working directory, HRESULT: 0x%X"), HRESULT_FROM_WIN32(GetLastError()));
    return false;
}

bool pal::load_library(const char_t* path, dll_t* dll)
{
    // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR:
    //   In portable apps, coreclr would come from another directory than the host,
    //   so make sure coreclr dependencies can be resolved from coreclr.dll load dir.
    *dll = ::LoadLibraryExW(path, NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
    if (*dll == nullptr)
    {
        trace::error(_X("Failed to load the dll from [%s], HRESULT: 0x%X"), path, HRESULT_FROM_WIN32(GetLastError()));
        return false;
    }

    // Pin the module
    HMODULE dummy_module;
    if (!::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN, path, &dummy_module))
    {
        trace::error(_X("Failed to pin library [%s] in [%s]"), path, _STRINGIFY(__FUNCTION__));
        return false;
    }

    if (trace::is_enabled())
    {
        pal::char_t buf[PATH_MAX];
        ::GetModuleFileNameW(*dll, buf, PATH_MAX);
        trace::info(_X("Loaded library from %s"), buf);
    }

    return true;
}

pal::proc_t pal::get_symbol(dll_t library, const char* name)
{
    return ::GetProcAddress(library, name);
}

void pal::unload_library(dll_t library)
{
    // No-op. On windows, we pin the library, so it can't be unloaded.
}

bool pal::get_default_breadcrumb_store(string_t* recv)
{
    recv->clear();

    pal::char_t* prog_dat;
    HRESULT hr = ::SHGetKnownFolderPath(FOLDERID_ProgramData, 0,  NULL, &prog_dat);
    if (hr != S_OK)
    {
        trace::verbose(_X("Failed to read default breadcrumb store 0x%X"), hr);
        return false;
    }
    recv->assign(prog_dat);
    append_path(recv, _X("Microsoft"));
    append_path(recv, _X("NetFramework"));
    append_path(recv, _X("BreadcrumbStore"));
    return true;
}

bool pal::get_default_servicing_directory(string_t* recv)
{
    recv->clear();

    // See https://github.com/dotnet/cli/issues/2179
#ifdef _TARGET_X86_
    // In WOW64 mode, PF maps to PFx86.
    if (!pal::getenv(_X("ProgramFiles"), recv))
#elif defined(_TARGET_AMD64_)
    if (!pal::getenv(_X("ProgramFiles(x86)"), recv))
#endif
    {
        return false;
    }

    append_path(recv, _X("coreservicing"));
    return true;
}

bool pal::is_path_rooted(const string_t& path)
{
    return path.length() >= 2 && path[1] == L':';
}

// Returns true only if an env variable can be read successfully to be non-empty.
bool pal::getenv(const char_t* name, string_t* recv)
{
    recv->clear();

    auto length = ::GetEnvironmentVariableW(name, nullptr, 0);
    if (length == 0)
    {
        auto err = GetLastError();
        if (err != ERROR_ENVVAR_NOT_FOUND)
        {
            trace::error(_X("Failed to read environment variable [%s], HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError()));
        }
        return false;
    }
    auto buf = new char_t[length];
    if (::GetEnvironmentVariableW(name, buf, length) == 0)
    {
        trace::error(_X("Failed to read environment variable [%s], HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError()));
        return false;
    }

    recv->assign(buf);
    delete[] buf;

    return true;
}

int pal::xtoi(const char_t* input)
{
    return ::_wtoi(input);
}

bool pal::get_own_executable_path(string_t* recv)
{
    char_t program_path[MAX_PATH];
    DWORD dwModuleFileName = ::GetModuleFileNameW(NULL, program_path, MAX_PATH);
    if (dwModuleFileName == 0 || dwModuleFileName >= MAX_PATH) {
        return false;
    }
    recv->assign(program_path);
    return true;
}

static bool wchar_convert_helper(DWORD code_page, const char* cstr, int len, pal::string_t* out)
{
    out->clear();

    // No need of explicit null termination, so pass in the actual length.
    size_t size = ::MultiByteToWideChar(code_page, 0, cstr, len, nullptr, 0);
    if (size == 0)
    {
        return false;
    }
    out->resize(size, '\0');
    return ::MultiByteToWideChar(code_page, 0, cstr, len, &(*out)[0], out->size()) != 0;
}

bool pal::utf8_palstring(const std::string& str, pal::string_t* out)
{
    return wchar_convert_helper(CP_UTF8, &str[0], str.size(), out);
}

bool pal::pal_clrstring(const pal::string_t& str, std::vector<char>* out)
{
    out->clear();

    // Pass -1 as we want explicit null termination in the char buffer.
    size_t size = ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, nullptr, 0, nullptr, nullptr);
    if (size == 0)
    {
        return false;
    }
    out->resize(size, '\0');
    return ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, out->data(), out->size(), nullptr, nullptr) != 0;
}

bool pal::clr_palstring(const char* cstr, pal::string_t* out)
{
    return wchar_convert_helper(CP_UTF8, cstr, ::strlen(cstr), out);
}

bool pal::realpath(string_t* path)
{
    char_t buf[MAX_PATH];
    auto res = ::GetFullPathNameW(path->c_str(), MAX_PATH, buf, nullptr);
    if (res == 0 || res > MAX_PATH)
    {
        trace::error(_X("Error resolving full path [%s]"), path->c_str());
        return false;
    }
    path->assign(buf);
    return true;
}

bool pal::file_exists(const string_t& path)
{
    if (path.empty())
    {
        return false;
    }

    WIN32_FIND_DATAW data;
    auto find_handle = ::FindFirstFileW(path.c_str(), &data);
    bool found = find_handle != INVALID_HANDLE_VALUE;
    ::FindClose(find_handle);
    return found;
}

void pal::readdir(const string_t& path, const string_t& pattern, std::vector<pal::string_t>* list)
{
    assert(list != nullptr);

    std::vector<string_t>& files = *list;

    string_t search_string(path);
    append_path(&search_string, pattern.c_str());

    WIN32_FIND_DATAW data = { 0 };
    auto handle = ::FindFirstFileExW(search_string.c_str(), FindExInfoStandard, &data, FindExSearchNameMatch, NULL, 0);
    if (handle == INVALID_HANDLE_VALUE)
    {
        return;
    }
    do
    {
        string_t filepath(data.cFileName);
        files.push_back(filepath);
    } while (::FindNextFileW(handle, &data));
    ::FindClose(handle);
}

void pal::readdir(const string_t& path, std::vector<pal::string_t>* list)
{
    pal::readdir(path, _X("*"), list);
}
<commit_msg>Get the correct ProgFolder for Arm64<commit_after>// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "pal.h"
#include "trace.h"
#include "utils.h"

#include <cassert>
#include <locale>
#include <codecvt>
#include <ShlObj.h>

pal::string_t pal::to_lower(const pal::string_t& in)
{
    pal::string_t ret = in;
    std::transform(ret.begin(), ret.end(), ret.begin(), ::towlower);
    return ret;
}

pal::string_t pal::to_string(int value)
{
    return std::to_wstring(value);
}

bool pal::touch_file(const pal::string_t& path)
{
    HANDLE hnd = ::CreateFileW(path.c_str(), 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hnd == INVALID_HANDLE_VALUE)
    {
        trace::verbose(_X("Failed to leave breadcrumb"), HRESULT_FROM_WIN32(GetLastError()));
        return false;
    }
    ::CloseHandle(hnd);
    return true;
}

void pal::setup_api_sets(const std::unordered_set<pal::string_t>& api_sets)
{
    if (api_sets.empty())
    {
        return;
    }

    pal::string_t path;

    (void) getenv(_X("PATH"), &path);

    // We need this ugly hack, as the PInvoked DLL's static dependencies can come from
    // some other NATIVE_DLL_SEARCH_DIRECTORIES and not necessarily side by side. However,
    // CoreCLR.dll loads PInvoke DLLs with LOAD_WITH_ALTERED_SEARCH_PATH. Note that this
    // option cannot be combined with LOAD_LIBRARY_SEARCH_USER_DIRS, so the AddDllDirectory
    // doesn't help much in telling CoreCLR where to load the PInvoke DLLs from.
    // So we resort to modifying the PATH variable on our own hoping Windows loader will do the right thing.
    for (const auto& as : api_sets)
    {
        // AddDllDirectory is still needed for Standalone App's CoreCLR load.
        ::AddDllDirectory(as.c_str());

        // Path patch is needed for static dependencies of a PInvoked DLL load out of the nuget cache.
        path.push_back(PATH_SEPARATOR);
        path.append(as);
    }

    trace::verbose(_X("Setting PATH=%s"), path.c_str());

    ::SetEnvironmentVariableW(_X("PATH"), path.c_str());
}

bool pal::getcwd(pal::string_t* recv)
{
    recv->clear();

    pal::char_t buf[MAX_PATH];
    DWORD result = GetCurrentDirectoryW(MAX_PATH, buf);
    if (result < MAX_PATH)
    {
        recv->assign(buf);
        return true;
    }
    else if (result != 0)
    {
        std::vector<pal::char_t> str;
        str.resize(result);
        result = GetCurrentDirectoryW(str.size(), str.data());
        assert(result <= str.size());
        if (result != 0)
        {
            recv->assign(str.data());
            return true;
        }
    }
    assert(result == 0);
    trace::error(_X("Failed to obtain working directory, HRESULT: 0x%X"), HRESULT_FROM_WIN32(GetLastError()));
    return false;
}

bool pal::load_library(const char_t* path, dll_t* dll)
{
    // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR:
    //   In portable apps, coreclr would come from another directory than the host,
    //   so make sure coreclr dependencies can be resolved from coreclr.dll load dir.
    *dll = ::LoadLibraryExW(path, NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
    if (*dll == nullptr)
    {
        trace::error(_X("Failed to load the dll from [%s], HRESULT: 0x%X"), path, HRESULT_FROM_WIN32(GetLastError()));
        return false;
    }

    // Pin the module
    HMODULE dummy_module;
    if (!::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN, path, &dummy_module))
    {
        trace::error(_X("Failed to pin library [%s] in [%s]"), path, _STRINGIFY(__FUNCTION__));
        return false;
    }

    if (trace::is_enabled())
    {
        pal::char_t buf[PATH_MAX];
        ::GetModuleFileNameW(*dll, buf, PATH_MAX);
        trace::info(_X("Loaded library from %s"), buf);
    }

    return true;
}

pal::proc_t pal::get_symbol(dll_t library, const char* name)
{
    return ::GetProcAddress(library, name);
}

void pal::unload_library(dll_t library)
{
    // No-op. On windows, we pin the library, so it can't be unloaded.
}

bool pal::get_default_breadcrumb_store(string_t* recv)
{
    recv->clear();

    pal::char_t* prog_dat;
    HRESULT hr = ::SHGetKnownFolderPath(FOLDERID_ProgramData, 0,  NULL, &prog_dat);
    if (hr != S_OK)
    {
        trace::verbose(_X("Failed to read default breadcrumb store 0x%X"), hr);
        return false;
    }
    recv->assign(prog_dat);
    append_path(recv, _X("Microsoft"));
    append_path(recv, _X("NetFramework"));
    append_path(recv, _X("BreadcrumbStore"));
    return true;
}

bool pal::get_default_servicing_directory(string_t* recv)
{
    recv->clear();

    // See https://github.com/dotnet/cli/issues/2179
#if defined(_TARGET_AMD64_)
    if (!pal::getenv(_X("ProgramFiles(x86)"), recv))
#else
    // In WOW64 mode, PF maps to PFx86.
    // For Arm64, there is no wow mode as of now, so this should be fine
    if (!pal::getenv(_X("ProgramFiles"), recv))
#endif
    {
        return false;
    }

    append_path(recv, _X("coreservicing"));
    return true;
}

bool pal::is_path_rooted(const string_t& path)
{
    return path.length() >= 2 && path[1] == L':';
}

// Returns true only if an env variable can be read successfully to be non-empty.
bool pal::getenv(const char_t* name, string_t* recv)
{
    recv->clear();

    auto length = ::GetEnvironmentVariableW(name, nullptr, 0);
    if (length == 0)
    {
        auto err = GetLastError();
        if (err != ERROR_ENVVAR_NOT_FOUND)
        {
            trace::error(_X("Failed to read environment variable [%s], HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError()));
        }
        return false;
    }
    auto buf = new char_t[length];
    if (::GetEnvironmentVariableW(name, buf, length) == 0)
    {
        trace::error(_X("Failed to read environment variable [%s], HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError()));
        return false;
    }

    recv->assign(buf);
    delete[] buf;

    return true;
}

int pal::xtoi(const char_t* input)
{
    return ::_wtoi(input);
}

bool pal::get_own_executable_path(string_t* recv)
{
    char_t program_path[MAX_PATH];
    DWORD dwModuleFileName = ::GetModuleFileNameW(NULL, program_path, MAX_PATH);
    if (dwModuleFileName == 0 || dwModuleFileName >= MAX_PATH) {
        return false;
    }
    recv->assign(program_path);
    return true;
}

static bool wchar_convert_helper(DWORD code_page, const char* cstr, int len, pal::string_t* out)
{
    out->clear();

    // No need of explicit null termination, so pass in the actual length.
    size_t size = ::MultiByteToWideChar(code_page, 0, cstr, len, nullptr, 0);
    if (size == 0)
    {
        return false;
    }
    out->resize(size, '\0');
    return ::MultiByteToWideChar(code_page, 0, cstr, len, &(*out)[0], out->size()) != 0;
}

bool pal::utf8_palstring(const std::string& str, pal::string_t* out)
{
    return wchar_convert_helper(CP_UTF8, &str[0], str.size(), out);
}

bool pal::pal_clrstring(const pal::string_t& str, std::vector<char>* out)
{
    out->clear();

    // Pass -1 as we want explicit null termination in the char buffer.
    size_t size = ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, nullptr, 0, nullptr, nullptr);
    if (size == 0)
    {
        return false;
    }
    out->resize(size, '\0');
    return ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, out->data(), out->size(), nullptr, nullptr) != 0;
}

bool pal::clr_palstring(const char* cstr, pal::string_t* out)
{
    return wchar_convert_helper(CP_UTF8, cstr, ::strlen(cstr), out);
}

bool pal::realpath(string_t* path)
{
    char_t buf[MAX_PATH];
    auto res = ::GetFullPathNameW(path->c_str(), MAX_PATH, buf, nullptr);
    if (res == 0 || res > MAX_PATH)
    {
        trace::error(_X("Error resolving full path [%s]"), path->c_str());
        return false;
    }
    path->assign(buf);
    return true;
}

bool pal::file_exists(const string_t& path)
{
    if (path.empty())
    {
        return false;
    }

    WIN32_FIND_DATAW data;
    auto find_handle = ::FindFirstFileW(path.c_str(), &data);
    bool found = find_handle != INVALID_HANDLE_VALUE;
    ::FindClose(find_handle);
    return found;
}

void pal::readdir(const string_t& path, const string_t& pattern, std::vector<pal::string_t>* list)
{
    assert(list != nullptr);

    std::vector<string_t>& files = *list;

    string_t search_string(path);
    append_path(&search_string, pattern.c_str());

    WIN32_FIND_DATAW data = { 0 };
    auto handle = ::FindFirstFileExW(search_string.c_str(), FindExInfoStandard, &data, FindExSearchNameMatch, NULL, 0);
    if (handle == INVALID_HANDLE_VALUE)
    {
        return;
    }
    do
    {
        string_t filepath(data.cFileName);
        files.push_back(filepath);
    } while (::FindNextFileW(handle, &data));
    ::FindClose(handle);
}

void pal::readdir(const string_t& path, std::vector<pal::string_t>* list)
{
    pal::readdir(path, _X("*"), list);
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2014, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <grpc++/impl/client_unary_call.h>
#include <grpc++/impl/call.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/completion_queue.h>
#include <grpc++/status.h>
#include <grpc/support/log.h>

namespace grpc {

// Wrapper that performs a blocking unary call
Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method,
                         ClientContext *context,
                         const google::protobuf::Message &request,
                         google::protobuf::Message *result) {
  CompletionQueue cq;
  Call call(channel->CreateCall(method, context, &cq));
  CallOpBuffer buf;
  Status status;
  buf.AddSendInitialMetadata(context);
  buf.AddSendMessage(request);
  buf.AddRecvInitialMetadata(&context->recv_initial_metadata_);
  buf.AddRecvMessage(result);
  buf.AddClientSendClose();
  buf.AddClientRecvStatus(&context->trailing_metadata_, &status);
  call.PerformOps(&buf);
  GPR_ASSERT(cq.Pluck(&buf) && (buf.got_message || !status.IsOk()));
  return status;
}

class ClientAsyncRequest final : public CallOpBuffer {
 public:
  void FinalizeResult(void **tag, bool *status) override {
    CallOpBuffer::FinalizeResult(tag, status);
    delete this;
  }
};

void AsyncUnaryCall(ChannelInterface *channel, const RpcMethod &method,
                    ClientContext *context,
                    const google::protobuf::Message &request,
                    google::protobuf::Message *result, Status *status,
                    CompletionQueue *cq, void *tag) {
  ClientAsyncRequest *buf = new ClientAsyncRequest;
  buf->Reset(tag);
  Call call(channel->CreateCall(method, context, cq));
  buf->AddSendInitialMetadata(context);
  buf->AddSendMessage(request);
  buf->AddRecvInitialMetadata(&context->recv_initial_metadata_);
  buf->AddRecvMessage(result);
  buf->AddClientSendClose();
  buf->AddClientRecvStatus(&context->trailing_metadata_, status);
  call.PerformOps(buf);
}

}  // namespace grpc
<commit_msg>Fix ASSERT condition<commit_after>/*
 *
 * Copyright 2014, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <grpc++/impl/client_unary_call.h>
#include <grpc++/impl/call.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/completion_queue.h>
#include <grpc++/status.h>
#include <grpc/support/log.h>

namespace grpc {

// Wrapper that performs a blocking unary call
Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method,
                         ClientContext *context,
                         const google::protobuf::Message &request,
                         google::protobuf::Message *result) {
  CompletionQueue cq;
  Call call(channel->CreateCall(method, context, &cq));
  CallOpBuffer buf;
  Status status;
  buf.AddSendInitialMetadata(context);
  buf.AddSendMessage(request);
  buf.AddRecvInitialMetadata(&context->recv_initial_metadata_);
  buf.AddRecvMessage(result);
  buf.AddClientSendClose();
  buf.AddClientRecvStatus(&context->trailing_metadata_, &status);
  call.PerformOps(&buf);
  GPR_ASSERT((cq.Pluck(&buf) && buf.got_message) || !status.IsOk());
  return status;
}

class ClientAsyncRequest final : public CallOpBuffer {
 public:
  void FinalizeResult(void **tag, bool *status) override {
    CallOpBuffer::FinalizeResult(tag, status);
    delete this;
  }
};

void AsyncUnaryCall(ChannelInterface *channel, const RpcMethod &method,
                    ClientContext *context,
                    const google::protobuf::Message &request,
                    google::protobuf::Message *result, Status *status,
                    CompletionQueue *cq, void *tag) {
  ClientAsyncRequest *buf = new ClientAsyncRequest;
  buf->Reset(tag);
  Call call(channel->CreateCall(method, context, cq));
  buf->AddSendInitialMetadata(context);
  buf->AddSendMessage(request);
  buf->AddRecvInitialMetadata(&context->recv_initial_metadata_);
  buf->AddRecvMessage(result);
  buf->AddClientSendClose();
  buf->AddClientRecvStatus(&context->trailing_metadata_, status);
  call.PerformOps(buf);
}

}  // namespace grpc
<|endoftext|>


<commit_before>#include "lcio.h"

#include "IO/LCReader.h"
#include "IMPL/LCTOOLS.h"
#include "EVENT/LCCollection.h"
#include "EVENT/Track.h"
#include "EVENT/Cluster.h"

using namespace std ;
using namespace lcio ;

// ------  define some structs for extensions and relations:-----------

// NB: the first template argument of the parent class has to the class itself !

// a simple int extension
struct Index : LCIntExtension<Index> {} ;

// a vector of strings (pointers) that are owned by the object that is extended
struct ParticleIDs : LCOwnedExtensionVector<ParticleIDs,std::string> {};

// note extensions can be attched to any LCObject and be of any type, i.e. in particular
// of user defined types:
struct UserClass{
  int someInt ;
  float aFloat ;
};
struct MyUserExtension : LCOwnedExtension<MyUserExtension,UserClass> {} ;

// relations have to specify the type of the objects from and to which they relate:

// example:   a one to many relationship between tracks and clusters:
struct TrkCluLink : LC1ToNRelation<TrkCluLink,Track,Cluster> {} ;

// a many to many relationship between MCParticles
struct ParentDaughter : LCNToNRelation<ParentDaughter,MCParticle,MCParticle> {} ;

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

/** Example/test program for new runtime extensions and relations
 *  requires recjob.slcio (from simjob/recjob).
 */

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

  LCReader* lcReader = LCFactory::getInstance()->createLCReader() ;

  lcReader->open( "recjob.slcio" ) ;

  LCEvent* evt ;
  int nEvents = 0 ;

  //----------- the event loop -----------
  while( (evt = lcReader->readNextEvent()) != 0 && nEvents < 1 ) {

    LCCollection* mcpcol = evt->getCollection("MCParticle" ) ;

    int nmcp = mcpcol->getNumberOfElements() ;

    for(int i=0 ; i< nmcp  ; i++ ){

      MCParticle*  mcp = dynamic_cast<MCParticle*>( mcpcol->getElementAt(i) ) ;

      // ints can be assigned directly - w/o pointer !
      // make every particle know it's index in the collection
      mcp->ext<Index>() = i ;

      // assign a user object to each particle:

      mcp->ext<MyUserExtension>() = new UserClass ;

      mcp->ext<MyUserExtension>()->someInt = i*42 ;
      mcp->ext<MyUserExtension>()->aFloat = i*3.1415 ;

      // assign some pid strings - note ownership is taken by particle

      if( ! (i % 2) )

	mcp->ext<ParticleIDs>()->push_back( new std::string("charged")  )  ;

      else

	mcp->ext<ParticleIDs>()->push_back( new std::string("neutral")  )  ;

      if( ! (i % 3) )

	mcp->ext<ParticleIDs>()->push_back( new std::string("hadron")  )  ;

      else if( ! ((i+1) % 3) )

	mcp->ext<ParticleIDs>()->push_back( new std::string("photon")  )  ;

      else if( ! ((i+2) % 3) )

	mcp->ext<ParticleIDs>()->push_back( new std::string("electron")  )  ;

      // copy the parent - daughter relationship:

      const MCParticleVec& daughters = mcp->getDaughters() ;

      for(unsigned j=0 ; j< daughters.size()   ; j++ ){

	add_relation<ParentDaughter>( mcp, daughters[j] ) ;
      }

    }

    LCCollection* trkcol = evt->getCollection("SomeTracks" ) ;
    LCCollection* clucol = evt->getCollection("SomeClusters" ) ;

    if( trkcol && clucol ) {

      int nclu = clucol->getNumberOfElements() ;
      int ntrk = trkcol->getNumberOfElements() ;

      for(int j=0 ; j< ntrk  ; j++ ){

	Track*   trk = dynamic_cast<Track*>   ( trkcol->getElementAt(j) ) ;

	// ints can be assigned directly - w/o pointer !
	// make every track know it's index in the collection
	trk->ext<Index>() = j ;

	for(int k=0 ; k< nclu ; k++ ){

	  Cluster* clu = dynamic_cast<Cluster*> ( clucol->getElementAt(k) ) ;

	  // make every cluster know it's index in the collection
 	  if( j == 0 )
	    clu->ext<Index>() = k ;

	  if( j % 2  && ( k == j || k == j-1 ) )

	    add_relation<TrkCluLink>( trk ,clu );
	}
      }

      // --- now print the relations:

      std::cout << "   ---- tracks assigned to clusters: " << std::endl ;
      for(int j=0 ; j< ntrk ; j++ ){

	Track*   trk = dynamic_cast<Track*>   ( trkcol->getElementAt(j) ) ;

	std::cout << " track " << trk->ext<Index>()  << " assigned to clusters :   " ;

	TrkCluLink::to::rel_type clulist =  trk->rel<TrkCluLink::to>() ;

	for( TrkCluLink::to::const_iterator iclu = clulist->begin() ;
	     iclu != clulist->end() ; ++iclu ){

	  Cluster* clu = *iclu ; // iterator is of type pointer to container element

	  std::cout <<  clu->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;
      }

      std::cout << "   ----- now the inverse relation : " << std::endl ;

      for(int k=0 ; k< nclu ; k++ ){

	Cluster* clu = dynamic_cast<Cluster*> ( clucol->getElementAt(k) ) ;

	Track* trk =  clu->rel<TrkCluLink::from>() ;

	std::cout << " cluster "
		  << clu->ext<Index>() << " assigned from track:   " ;
	if( trk != 0 )
	  std::cout << trk->ext<Index>() << std::endl ;
	else
	  std::cout << " none "  << std::endl ;
      }

      std::cout << std::endl ;

      // print MCParticle extensions and relations:

      std::cout << "   ----- MCParticles in event : : " << std::endl ;

      nmcp = ( nmcp < 10 ? nmcp : 10 ) ;

      for(int i=0 ; i<nmcp  ; i++ ){

	MCParticle*  mcp = dynamic_cast<MCParticle*>( mcpcol->getElementAt(i) ) ;

	MCParticle*  mcp0 = 0 ;   // keep the first particle
	if( i == 0 ) mcp0 = mcp  ;

	ParticleIDs::ext_type pidv =  mcp->ext<ParticleIDs>() ;

	std::cout <<  "   --- particle " << mcp->ext<Index>()  << " found to be : " ;

	for( ParticleIDs::const_iterator ipid = pidv->begin() ; ipid != pidv->end(); ++ipid){

	  std::cout << **ipid << ", " ;
	}

	if( ( *(*pidv)[0] == "charged" && *(*pidv)[1] == "photon"  ) ||
	    ( *(*pidv)[0] == "neutral" && *(*pidv)[1] == "electron")   )

	  std::cout << " --- ooops ! " ;

	std::cout << std::endl ;

	std::cout <<  "   --- particle " << mcp->ext<Index>()   <<  " user extension : "
		  << " someInt: " << mcp->ext<MyUserExtension>()->someInt
		  << " aFloat:  " << mcp->ext<MyUserExtension>()->aFloat
		  << std::endl ;

	// now check that the runtime relation for daughters:

	const MCParticleVec& daughters = mcp->getDaughters() ;

	std::cout <<  "   --- particle " << mcp->ext<Index>()   <<  " daughters: "
		  << std::endl ;

	std::cout <<  "      --- from MCParticle:  " ;

	for(MCParticleVec::const_iterator idau = daughters.begin() ;
	    idau != daughters.end() ; ++idau){

	  std::cout << (*idau)->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;

	std::cout <<  "      --- from runtime rel: " ;

	ParentDaughter::to::rel_type daulist =  mcp->rel<ParentDaughter::to>() ;

	for( ParentDaughter::to::const_iterator idau = daulist->begin();
	     idau != daulist->end(); ++idau){

	  std::cout << (*idau)->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;

	std::cout <<  "   --- particle " << mcp->ext<Index>()   <<  " parents: "
		  << std::endl ;

	std::cout <<  "      --- from MCParticle:  " ;

	const MCParticleVec& parents = mcp->getParents() ;

	for(MCParticleVec::const_iterator ipar = parents.begin() ;
	    ipar != parents.end() ; ++ipar){

	  std::cout << (*ipar)->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;

	std::cout <<  "      --- from runtime rel: " ;

	ParentDaughter::from::rel_type parlist =  mcp->rel<ParentDaughter::from>() ;

	for( ParentDaughter::from::const_iterator ipar = parlist->begin();
	     ipar != parlist->end(); ++ipar){

	  std::cout << (*ipar)->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;

	// for demonstration we can rearange the daughter relationships:
	if(i>0)

	  merge_relations<ParentDaughter>( mcp0 , mcp ) ;
      }

      for(int i=0 ; i<nmcp  ; i++ ){

	MCParticle*  mcp = dynamic_cast<MCParticle*>( mcpcol->getElementAt(i) ) ;

	std::cout <<  "   --- particle " << mcp->ext<Index>()
		  <<  " daughters after merging : " ;

	ParentDaughter::to::rel_type daulist =  mcp->rel<ParentDaughter::to>() ;

	for( ParentDaughter::to::const_iterator idau = daulist->begin();
	     idau != daulist->end(); ++idau){

	  std::cout << (*idau)->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;

      }

    } else {
      std::cout << " couldn't find Track and Cluster collection in event !" << std::endl ;
    }

    nEvents ++ ;
  }
  // -------- end of event loop -----------

  lcReader->close() ;
  delete lcReader ;
  return 0 ;
}

<commit_msg>bug fix with mcp0<commit_after>#include "lcio.h"

#include "IO/LCReader.h"
#include "IMPL/LCTOOLS.h"
#include "EVENT/LCCollection.h"
#include "EVENT/Track.h"
#include "EVENT/Cluster.h"

using namespace std ;
using namespace lcio ;

// ------  define some structs for extensions and relations:-----------

// NB: the first template argument of the parent class has to the class itself !

// a simple int extension
struct Index : LCIntExtension<Index> {} ;

// a vector of strings (pointers) that are owned by the object that is extended
struct ParticleIDs : LCOwnedExtensionVector<ParticleIDs,std::string> {};

// note extensions can be attched to any LCObject and be of any type, i.e. in particular
// of user defined types:
struct UserClass{
  int someInt ;
  float aFloat ;
};
struct MyUserExtension : LCOwnedExtension<MyUserExtension,UserClass> {} ;

// relations have to specify the type of the objects from and to which they relate:

// example:   a one to many relationship between tracks and clusters:
struct TrkCluLink : LC1ToNRelation<TrkCluLink,Track,Cluster> {} ;

// a many to many relationship between MCParticles
struct ParentDaughter : LCNToNRelation<ParentDaughter,MCParticle,MCParticle> {} ;

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

/** Example/test program for new runtime extensions and relations
 *  requires recjob.slcio (from simjob/recjob).
 */

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

  LCReader* lcReader = LCFactory::getInstance()->createLCReader() ;

  lcReader->open( "recjob.slcio" ) ;

  LCEvent* evt ;
  int nEvents = 0 ;

  //----------- the event loop -----------
  while( (evt = lcReader->readNextEvent()) != 0 && nEvents < 1 ) {

    LCCollection* mcpcol = evt->getCollection("MCParticle" ) ;

    int nmcp = mcpcol->getNumberOfElements() ;

    for(int i=0 ; i< nmcp  ; i++ ){

      MCParticle*  mcp = dynamic_cast<MCParticle*>( mcpcol->getElementAt(i) ) ;

      // ints can be assigned directly - w/o pointer !
      // make every particle know it's index in the collection
      mcp->ext<Index>() = i ;

      // assign a user object to each particle:

      mcp->ext<MyUserExtension>() = new UserClass ;

      mcp->ext<MyUserExtension>()->someInt = i*42 ;
      mcp->ext<MyUserExtension>()->aFloat = i*3.1415 ;

      // assign some pid strings - note ownership is taken by particle

      if( ! (i % 2) )

	mcp->ext<ParticleIDs>()->push_back( new std::string("charged")  )  ;

      else

	mcp->ext<ParticleIDs>()->push_back( new std::string("neutral")  )  ;

      if( ! (i % 3) )

	mcp->ext<ParticleIDs>()->push_back( new std::string("hadron")  )  ;

      else if( ! ((i+1) % 3) )

	mcp->ext<ParticleIDs>()->push_back( new std::string("photon")  )  ;

      else if( ! ((i+2) % 3) )

	mcp->ext<ParticleIDs>()->push_back( new std::string("electron")  )  ;

      // copy the parent - daughter relationship:

      const MCParticleVec& daughters = mcp->getDaughters() ;

      for(unsigned j=0 ; j< daughters.size()   ; j++ ){

	add_relation<ParentDaughter>( mcp, daughters[j] ) ;
      }

    }

    LCCollection* trkcol = evt->getCollection("SomeTracks" ) ;
    LCCollection* clucol = evt->getCollection("SomeClusters" ) ;

    if( trkcol && clucol ) {

      int nclu = clucol->getNumberOfElements() ;
      int ntrk = trkcol->getNumberOfElements() ;

      for(int j=0 ; j< ntrk  ; j++ ){

	Track*   trk = dynamic_cast<Track*>   ( trkcol->getElementAt(j) ) ;

	// ints can be assigned directly - w/o pointer !
	// make every track know it's index in the collection
	trk->ext<Index>() = j ;

	for(int k=0 ; k< nclu ; k++ ){

	  Cluster* clu = dynamic_cast<Cluster*> ( clucol->getElementAt(k) ) ;

	  // make every cluster know it's index in the collection
 	  if( j == 0 )
	    clu->ext<Index>() = k ;

	  if( j % 2  && ( k == j || k == j-1 ) )

	    add_relation<TrkCluLink>( trk ,clu );
	}
      }

      // --- now print the relations:

      std::cout << "   ---- tracks assigned to clusters: " << std::endl ;
      for(int j=0 ; j< ntrk ; j++ ){

	Track*   trk = dynamic_cast<Track*>   ( trkcol->getElementAt(j) ) ;

	std::cout << " track " << trk->ext<Index>()  << " assigned to clusters :   " ;

	TrkCluLink::to::rel_type clulist =  trk->rel<TrkCluLink::to>() ;

	for( TrkCluLink::to::const_iterator iclu = clulist->begin() ;
	     iclu != clulist->end() ; ++iclu ){

	  Cluster* clu = *iclu ; // iterator is of type pointer to container element

	  std::cout <<  clu->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;
      }

      std::cout << "   ----- now the inverse relation : " << std::endl ;

      for(int k=0 ; k< nclu ; k++ ){

	Cluster* clu = dynamic_cast<Cluster*> ( clucol->getElementAt(k) ) ;

	Track* trk =  clu->rel<TrkCluLink::from>() ;

	std::cout << " cluster "
		  << clu->ext<Index>() << " assigned from track:   " ;
	if( trk != 0 )
	  std::cout << trk->ext<Index>() << std::endl ;
	else
	  std::cout << " none "  << std::endl ;
      }

      std::cout << std::endl ;

      // print MCParticle extensions and relations:

      std::cout << "   ----- MCParticles in event : : " << std::endl ;

      nmcp = ( nmcp < 10 ? nmcp : 10 ) ;

      MCParticle*  mcp0 = 0 ;   // pointer for first particle

      for(int i=0 ; i<nmcp  ; i++ ){

	MCParticle*  mcp = dynamic_cast<MCParticle*>( mcpcol->getElementAt(i) ) ;

	if( i == 0 ) mcp0 = mcp  ;

	ParticleIDs::ext_type pidv =  mcp->ext<ParticleIDs>() ;

	std::cout <<  "   --- particle " << mcp->ext<Index>()  << " found to be : " ;

	for( ParticleIDs::const_iterator ipid = pidv->begin() ; ipid != pidv->end(); ++ipid){

	  std::cout << **ipid << ", " ;
	}

	if( ( *(*pidv)[0] == "charged" && *(*pidv)[1] == "photon"  ) ||
	    ( *(*pidv)[0] == "neutral" && *(*pidv)[1] == "electron")   )

	  std::cout << " --- ooops ! " ;

	std::cout << std::endl ;

	std::cout <<  "   --- particle " << mcp->ext<Index>()   <<  " user extension : "
		  << " someInt: " << mcp->ext<MyUserExtension>()->someInt
		  << " aFloat:  " << mcp->ext<MyUserExtension>()->aFloat
		  << std::endl ;

	// now check that the runtime relation for daughters:

	const MCParticleVec& daughters = mcp->getDaughters() ;

	std::cout <<  "   --- particle " << mcp->ext<Index>()   <<  " daughters: "
		  << std::endl ;

	std::cout <<  "      --- from MCParticle:  " ;

	for(MCParticleVec::const_iterator idau = daughters.begin() ;
	    idau != daughters.end() ; ++idau){

	  std::cout << (*idau)->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;

	std::cout <<  "      --- from runtime rel: " ;

	ParentDaughter::to::rel_type daulist =  mcp->rel<ParentDaughter::to>() ;

	for( ParentDaughter::to::const_iterator idau = daulist->begin();
	     idau != daulist->end(); ++idau){

	  std::cout << (*idau)->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;

	std::cout <<  "   --- particle " << mcp->ext<Index>()   <<  " parents: "
		  << std::endl ;

	std::cout <<  "      --- from MCParticle:  " ;

	const MCParticleVec& parents = mcp->getParents() ;

	for(MCParticleVec::const_iterator ipar = parents.begin() ;
	    ipar != parents.end() ; ++ipar){

	  std::cout << (*ipar)->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;

	std::cout <<  "      --- from runtime rel: " ;

	ParentDaughter::from::rel_type parlist =  mcp->rel<ParentDaughter::from>() ;

	for( ParentDaughter::from::const_iterator ipar = parlist->begin();
	     ipar != parlist->end(); ++ipar){

	  std::cout << (*ipar)->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;

	// for demonstration we can rearange the daughter relationships:
	if(i>0)

	  merge_relations<ParentDaughter>( mcp0 , mcp ) ;
      }

      for(int i=0 ; i<nmcp  ; i++ ){

	MCParticle*  mcp = dynamic_cast<MCParticle*>( mcpcol->getElementAt(i) ) ;

	std::cout <<  "   --- particle " << mcp->ext<Index>()
		  <<  " daughters after merging : " ;

	ParentDaughter::to::rel_type daulist =  mcp->rel<ParentDaughter::to>() ;

	for( ParentDaughter::to::const_iterator idau = daulist->begin();
	     idau != daulist->end(); ++idau){

	  std::cout << (*idau)->ext<Index>() << ", " ;
	}
	std::cout << std::endl ;

      }

    } else {
      std::cout << " couldn't find Track and Cluster collection in event !" << std::endl ;
    }

    nEvents ++ ;
  }
  // -------- end of event loop -----------

  lcReader->close() ;
  delete lcReader ;
  return 0 ;
}

<|endoftext|>


<commit_before>// implementation for goertzel_reinsch.h

namespace MathTL
{
  template <class C>
  C
  Goertzel<C>::value(const Point<1,C>&p, const unsigned int component) const
  {
    // adjoint summation for the three-term recursion
    //   p_k = 2*cos(x) * p_{k-1} - p_{k-2}

    assert(coeffs_.size() >= 1);

    C uk(0), ukplus1(0), ukplus2(0);

    const C gamma = cos(p[0]);
    for (int k(coeffs_.size()-1); k >= 1; --k) {
      uk = 2*gamma*ukplus1 - ukplus2 + coeffs_[k];
      if (k > 0) {
	ukplus2 = ukplus1;
	ukplus1 = uk;
      }
    }

    return (sine_ ? uk*sin(p[0]) : coeffs_[0]+uk*cos(p[0])-ukplus1);
  }

  template <class C>
  C
  GoertzelReinsch<C>::value(const Point<1,C>&p, const unsigned int component) const
  {
    assert(coeffs_.size() >= 1);

    C uk(0), ukplus1(0), wk(0), wkplus1, lambda(0);

    if (cos(p[0])>0) {
      lambda = -4*sin(p[0]/2.)*sin(p[0]/2.);
      for (int k(coeffs_.size()-1); k >= 0; --k) {
	uk = wk + ukplus1;
	wkplus1 = wk;
	wk = (lambda*uk + wkplus1) + coeffs_[k];
	if (k > 0) {
	  ukplus1 = uk;
	}
      }
    } else {
      lambda = 4*cos(p[0]/2.)*cos(p[0]/2.);
      for (int k(coeffs_.size()-1); k >= 0; --k) {
	uk = wk - ukplus1;
	wkplus1 = wk;
	wk = (lambda*uk - wkplus1) + coeffs_[k];
	if (k > 0) {
	  ukplus1 = uk;
	}
      }
    }

    return sine_ ? uk*sin(p[0]) : wk - wkplus1*(lambda/2);
  }

}
<commit_msg>code cosmetics<commit_after>// implementation for goertzel_reinsch.h

namespace MathTL
{
  template <class C>
  C
  Goertzel<C>::value(const Point<1,C>&p, const unsigned int component) const
  {
    // adjoint summation for the three-term recursion
    //   p_k = 2*cos(x) * p_{k-1} - p_{k-2}

    assert(coeffs_.size() >= 1);

    C uk(0), ukplus1(0), ukplus2(0);

    const C gamma = cos(p[0]);
    for (int k(coeffs_.size()-1); k >= 1; --k) {
      uk = 2*gamma*ukplus1 - ukplus2 + coeffs_[k];
      if (k > 0) {
	ukplus2 = ukplus1;
	ukplus1 = uk;
      }
    }

    return (sine_ ? uk*sin(p[0]) : coeffs_[0]+uk*cos(p[0])-ukplus1);
  }

  template <class C>
  C
  GoertzelReinsch<C>::value(const Point<1,C>&p, const unsigned int component) const
  {
    assert(coeffs_.size() >= 1);

    C uk(0), ukplus1(0), wk(0), wkplus1(0), lambda(0);

    if (cos(p[0])>0) {
      lambda = -4*sin(p[0]/2.)*sin(p[0]/2.);
      for (int k(coeffs_.size()-1); k >= 0; --k) {
	uk = wk + ukplus1;
	wkplus1 = wk;
	wk = (lambda*uk + wkplus1) + coeffs_[k];
	if (k > 0) {
	  ukplus1 = uk;
	}
      }
    } else {
      lambda = 4*cos(p[0]/2.)*cos(p[0]/2.);
      for (int k(coeffs_.size()-1); k >= 0; --k) {
	uk = wk - ukplus1;
	wkplus1 = wk;
	wk = (lambda*uk - wkplus1) + coeffs_[k];
	if (k > 0) {
	  ukplus1 = uk;
	}
      }
    }

    return sine_ ? uk*sin(p[0]) : wk - wkplus1*(lambda/2);
  }

}
<|endoftext|>


<commit_before>#include <ctime>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include "camera.hpp"

static const int WIDTH = 640;
static const int HEIGHT = 480;
static const int FPS = 5;
static const int DEVICE = 0;
static const std::string DIRECTORY_PATH = "/home/pi/Pictures/";//pathの先頭
static const std::string FILE_EXTENTION = ".jpg";//拡張子

static const int AOV = 62.2;//ANGLE OF VIEW
//明度について
static const int MAX_VALUE = 255;//明るさ最大
static const int NO_VALUE = 0;//明るさ最小

Camera::Camera()
{
	if(!capture.open(DEVICE))
	{
		std::cout<<"capture is not opened 1"<<std::endl;
	}
	if (!capture.isOpened())
	{
		std::cout<<"capture is not opened 2"<<std::endl;
	}
	capture.set(CV_CAP_PROP_FRAME_WIDTH,WIDTH);
	capture.set(CV_CAP_PROP_FRAME_HEIGHT,HEIGHT);
	capture.set(CV_CAP_PROP_FPS,FPS);
	cap.set(CV_CAP_PROP_BUFFERSIZE, 2);
}

Camera::~Camera()
{
	capture.release();
}

int Camera::takePhoto()
{
	makeTimePath();
	cv::Mat frame;
	do
	{
		capture>>frame;
	} while(frame.empty());
	input = frame;
	imwrite(timePath+FILE_EXTENTION,input);
	return 0;
}

//時間を元にtimePathを作る
int Camera::makeTimePath(void)
{
	time_t timer;//時刻を受け取る変数
	struct tm *timeptr;//日時を集めた構造体ポインタ
	char buffer[80];
	time(&timer);//現在時刻の取得
	timeptr = localtime(&timer);//ポインタ
	strftime(buffer, sizeof(buffer), "%Y%m%d-%H%M%S", timeptr);//日時を文字列に変換してｓに代入
	std::string str(buffer);
	timePath = DIRECTORY_PATH+str;
  return 0;
}

//ノイズ除去
cv::Mat Camera::rmNoise(cv::Mat src)
{
	cv::erode(src,src,cv::Mat(),cv::Point(-1, -1),10);//縮小処理
	cv::dilate(src,src,cv::Mat(),cv::Point(-1, -1),25);//膨張処理
	cv::erode(src,src,cv::Mat(),cv::Point(-1, -1),15);//縮小処理
	return src;
}

int Camera::binarize()
{
	cv::Mat hsv;
	cv::Mat hsv_filtered15 ;//画像の初期化
	cv::Mat hsv_filtered180;//画像の初期化
	cv::cvtColor(input, hsv, CV_BGR2HSV);//入力画像(src)をhsv色空間(dst)に変換
	//inRange(入力画像,下界画像,上界画像,出力画像)
	//「HSV」は、色を色相(Hue)・彩度(Saturation)・明度(Value)
	cv::inRange(hsv, cv::Scalar(0, 70, 60), cv::Scalar(2, 255, MAX_VALUE), hsv_filtered15);
	cv::inRange(hsv, cv::Scalar(160, 70, 60), cv::Scalar(180, 255, MAX_VALUE), hsv_filtered180);
	cv::add(hsv_filtered15,hsv_filtered180,hsv);
	output = rmNoise(hsv);
	imwrite(timePath+"BINARY"+FILE_EXTENTION,output);
	return 0;
}

//二値化した画像から1の面積を抽出
double Camera::countArea()
{

	double Area = output.rows*output.cols;//全ピクセル数
	double redCount = 0; //赤色を認識したピクセルの数
	redCount = cv::countNonZero(output);//赤色部分の面積を計算
	double percentage = 0; //割合
	percentage = (redCount / Area)*100;//割合を計算
	std::cout<<"面積のPercentageは"<<percentage<<std::endl;
	return percentage;
}

//二値化画像のcenterを角度で返す
double Camera::getCenter()
{
	cv::Moments mu = cv::moments(output, false);//重心の計算結果をmuに代入
	double mc = mu.m10 / mu.m00;//重心のx座標
	double center = (mc - output.cols / 2) * AOV / output.cols;//正規化
	std::cout<<"重心の位置は"<<center<<std::endl;
	return center;
}
<commit_msg>debug<commit_after>#include <ctime>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include "camera.hpp"

static const int WIDTH = 640;
static const int HEIGHT = 480;
static const int FPS = 5;
static const int DEVICE = 0;
static const std::string DIRECTORY_PATH = "/home/pi/Pictures/";//pathの先頭
static const std::string FILE_EXTENTION = ".jpg";//拡張子

static const int AOV = 62.2;//ANGLE OF VIEW
//明度について
static const int MAX_VALUE = 255;//明るさ最大
static const int NO_VALUE = 0;//明るさ最小

Camera::Camera()
{
	if(!capture.open(DEVICE))
	{
		std::cout<<"capture is not opened 1"<<std::endl;
	}
	if (!capture.isOpened())
	{
		std::cout<<"capture is not opened 2"<<std::endl;
	}
	capture.set(CV_CAP_PROP_FRAME_WIDTH,WIDTH);
	capture.set(CV_CAP_PROP_FRAME_HEIGHT,HEIGHT);
	capture.set(CV_CAP_PROP_FPS,FPS);
	capture.set(CV_CAP_PROP_BUFFERSIZE, 2);
}

Camera::~Camera()
{
	capture.release();
}

int Camera::takePhoto()
{
	makeTimePath();
	cv::Mat frame;
	do
	{
		capture>>frame;
	} while(frame.empty());
	input = frame;
	imwrite(timePath+FILE_EXTENTION,input);
	return 0;
}

//時間を元にtimePathを作る
int Camera::makeTimePath(void)
{
	time_t timer;//時刻を受け取る変数
	struct tm *timeptr;//日時を集めた構造体ポインタ
	char buffer[80];
	time(&timer);//現在時刻の取得
	timeptr = localtime(&timer);//ポインタ
	strftime(buffer, sizeof(buffer), "%Y%m%d-%H%M%S", timeptr);//日時を文字列に変換してｓに代入
	std::string str(buffer);
	timePath = DIRECTORY_PATH+str;
  return 0;
}

//ノイズ除去
cv::Mat Camera::rmNoise(cv::Mat src)
{
	cv::erode(src,src,cv::Mat(),cv::Point(-1, -1),10);//縮小処理
	cv::dilate(src,src,cv::Mat(),cv::Point(-1, -1),25);//膨張処理
	cv::erode(src,src,cv::Mat(),cv::Point(-1, -1),15);//縮小処理
	return src;
}

int Camera::binarize()
{
	cv::Mat hsv;
	cv::Mat hsv_filtered15 ;//画像の初期化
	cv::Mat hsv_filtered180;//画像の初期化
	cv::cvtColor(input, hsv, CV_BGR2HSV);//入力画像(src)をhsv色空間(dst)に変換
	//inRange(入力画像,下界画像,上界画像,出力画像)
	//「HSV」は、色を色相(Hue)・彩度(Saturation)・明度(Value)
	cv::inRange(hsv, cv::Scalar(0, 70, 60), cv::Scalar(2, 255, MAX_VALUE), hsv_filtered15);
	cv::inRange(hsv, cv::Scalar(160, 70, 60), cv::Scalar(180, 255, MAX_VALUE), hsv_filtered180);
	cv::add(hsv_filtered15,hsv_filtered180,hsv);
	output = rmNoise(hsv);
	imwrite(timePath+"BINARY"+FILE_EXTENTION,output);
	return 0;
}

//二値化した画像から1の面積を抽出
double Camera::countArea()
{

	double Area = output.rows*output.cols;//全ピクセル数
	double redCount = 0; //赤色を認識したピクセルの数
	redCount = cv::countNonZero(output);//赤色部分の面積を計算
	double percentage = 0; //割合
	percentage = (redCount / Area)*100;//割合を計算
	std::cout<<"面積のPercentageは"<<percentage<<std::endl;
	return percentage;
}

//二値化画像のcenterを角度で返す
double Camera::getCenter()
{
	cv::Moments mu = cv::moments(output, false);//重心の計算結果をmuに代入
	double mc = mu.m10 / mu.m00;//重心のx座標
	double center = (mc - output.cols / 2) * AOV / output.cols;//正規化
	std::cout<<"重心の位置は"<<center<<std::endl;
	return center;
}
<|endoftext|>