<commit_before>// Copyright 2015 Vladimir Alyamkin. All Rights Reserved.
// Original code by https://github.com/unktomi

#include "VaRestEditorPluginPrivatePCH.h"
#include "VaRest_BreakJson.h"

#define LOCTEXT_NAMESPACE "VaRest_BreakJson"

class FKCHandler_BreakJson : public FNodeHandlingFunctor
{

public:
	FKCHandler_BreakJson(FKismetCompilerContext& InCompilerContext)
		: FNodeHandlingFunctor(InCompilerContext)
	{
	}

	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		UEdGraphPin* InputPin = NULL;

		for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
		{
			UEdGraphPin* Pin = Node->Pins[PinIndex];
			if (Pin && (EGPD_Input == Pin->Direction))
			{
				InputPin = Pin;
				break;
			}
		}

		UEdGraphPin *InNet = FEdGraphUtilities::GetNetFromPin(InputPin);
		UClass *Class = Cast<UClass>(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRestPlugin.VaRestJsonObject'")));

		FBPTerminal **SourceTerm = Context.NetMap.Find(InNet);
		if (SourceTerm == nullptr)
		{
			return;
		}

		for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
		{
			UEdGraphPin* Pin = Node->Pins[PinIndex];
			if (Pin && (EGPD_Output == Pin->Direction))
			{
				if (Pin->LinkedTo.Num() < 1)
				{
					continue;
				}

				FBPTerminal **Target = Context.NetMap.Find(Pin);

				const FString &FieldName = Pin->PinName;
				const FString &FieldType = Pin->PinType.PinCategory;

				FBPTerminal* FieldNameTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal);
				FieldNameTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_String;
				FieldNameTerm->Source = Pin;
				FieldNameTerm->Name = FieldName;
				FieldNameTerm->TextLiteral = FText::FromString(FieldName);

 				FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node);
				FName FunctionName;

				bool bIsArray = Pin->PinType.bIsArray;

				if (FieldType == CompilerContext.GetSchema()->PC_Boolean)
				{
					FunctionName = bIsArray ? TEXT("GetBoolArrayField") : TEXT("GetBoolField");
				}
				else if (FieldType == CompilerContext.GetSchema()->PC_Float)
				{
					FunctionName = bIsArray ? TEXT("GetNumberArrayField") : TEXT("GetNumberField");
				}
				else if (FieldType == CompilerContext.GetSchema()->PC_String)
				{
					FunctionName = bIsArray ? TEXT("GetStringArrayField") : TEXT("GetStringField");
				}
				else if (FieldType == CompilerContext.GetSchema()->PC_Object)
				{
					FunctionName = bIsArray ? TEXT("GetObjectArrayField") : TEXT("GetObjectField");
				}
				else
				{
					continue;
				}

				UFunction *FunctionPtr = Class->FindFunctionByName(FunctionName);
				Statement.Type = KCST_CallFunction;
				Statement.FunctionToCall = FunctionPtr;
				Statement.FunctionContext = *SourceTerm;
				Statement.bIsParentContext = false;
				Statement.LHS = *Target;
				Statement.RHS.Add(FieldNameTerm);
			}
		}
	}

	FBPTerminal* RegisterInputTerm(FKismetFunctionContext& Context, UVaRest_BreakJson* Node)
	{
		// Find input pin
		UEdGraphPin* InputPin = NULL;
		for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
		{
			UEdGraphPin* Pin = Node->Pins[PinIndex];
			if (Pin && (EGPD_Input == Pin->Direction))
			{
				InputPin = Pin;
				break;
			}
		}
		check(NULL != InputPin);

		// Find structure source net
		UEdGraphPin* Net = FEdGraphUtilities::GetNetFromPin(InputPin);
		FBPTerminal **TermPtr = Context.NetMap.Find(Net);

		if (!TermPtr)
		{
			FBPTerminal *Term = Context.CreateLocalTerminalFromPinAutoChooseScope(Net, Context.NetNameMap->MakeValidName(Net));

			Context.NetMap.Add(Net, Term);

			return Term;
		}

		return *TermPtr;
	}

	void RegisterOutputTerm(FKismetFunctionContext& Context, UEdGraphPin* OutputPin, FBPTerminal* ContextTerm)
	{
		FBPTerminal *Term = Context.CreateLocalTerminalFromPinAutoChooseScope(OutputPin, Context.NetNameMap->MakeValidName(OutputPin));
		Context.NetMap.Add(OutputPin, Term);
	}

	virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* InNode) override
	{
		UVaRest_BreakJson* Node = Cast<UVaRest_BreakJson>(InNode);
		FNodeHandlingFunctor::RegisterNets(Context, Node);

		check(NULL != Node);

		if (FBPTerminal* StructContextTerm = RegisterInputTerm(Context, Node))
		{
			for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
			{
				UEdGraphPin* Pin = Node->Pins[PinIndex];
				if (NULL != Pin && EGPD_Output == Pin->Direction)
				{
					RegisterOutputTerm(Context, Pin, StructContextTerm);
				}
			}
		}
	}
};

/**
 * Main node class
 */
UVaRest_BreakJson::UVaRest_BreakJson(const FObjectInitializer &ObjectInitializer)
	: Super(ObjectInitializer)
{
}

FNodeHandlingFunctor* UVaRest_BreakJson::CreateNodeHandler(class FKismetCompilerContext& CompilerContext) const
{
	return new FKCHandler_BreakJson(CompilerContext);
}

void UVaRest_BreakJson::AllocateDefaultPins()
{
	const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();

	UClass *Class = Cast<UClass>(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRestPlugin.VaRestJsonObject'")));
	UEdGraphPin* Pin = CreatePin(EGPD_Input, K2Schema->PC_Object, TEXT(""), Class, false, false, TEXT("Target"));

	K2Schema->SetPinDefaultValueBasedOnType(Pin);

	CreateProjectionPins(Pin);
}

FLinearColor UVaRest_BreakJson::GetNodeTitleColor() const
{
	return FLinearColor(255.0f, 255.0f, 0.0f);
}

void UVaRest_BreakJson::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent)
{
	bool bIsDirty = false;

	FName PropertyName = (PropertyChangedEvent.Property != NULL) ? PropertyChangedEvent.Property->GetFName() : NAME_None;
	if (true || PropertyName == TEXT("Outputs"))
	{
		bIsDirty = true;
	}

	if (bIsDirty)
	{
		ReconstructNode();
		GetGraph()->NotifyGraphChanged();
	}

	Super::PostEditChangeProperty(PropertyChangedEvent);
}

void UVaRest_BreakJson::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
	// actions get registered under specific object-keys; the idea is that
	// actions might have to be updated (or deleted) if their object-key is
	// mutated (or removed)... here we use the node's class (so if the node
	// type disappears, then the action should go with it)
	UClass* ActionKey = GetClass();

	// to keep from needlessly instantiating a UBlueprintNodeSpawner, first
	// check to make sure that the registrar is looking for actions of this type
	// (could be regenerating actions for a specific asset, and therefore the
	// registrar would only accept actions corresponding to that asset)
	if (ActionRegistrar.IsOpenForRegistration(ActionKey))
	{
		UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass());
		check(NodeSpawner != nullptr);

		ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner);
	}
}

FText UVaRest_BreakJson::GetMenuCategory() const
{
	static FNodeTextCache CachedCategory;

	if (CachedCategory.IsOutOfDate(this))
	{
		// FText::Format() is slow, so we cache this to save on performance
		CachedCategory.SetCachedText(FEditorCategoryUtils::BuildCategoryString(FCommonEditorCategory::Utilities, LOCTEXT("ActionMenuCategory", "Va Rest")), this);
	}
	return CachedCategory;
}

void UVaRest_BreakJson::CreateProjectionPins(UEdGraphPin *Source)
{
	const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
	UClass *Class = Cast<UClass>(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRestPlugin.VaRestJsonObject'")));

	for (TArray<FVaRest_NamedType>::TIterator it(Outputs); it; ++it)
	{
		FString Type;
		UObject *Subtype = nullptr;
		FString FieldName = (*it).Name;

		switch ((*it).Type) {
			case EVaRest_JsonType::JSON_Bool:
				Type = K2Schema->PC_Boolean;
				break;

			case EVaRest_JsonType::JSON_Number:
				Type = K2Schema->PC_Float;
				break;

			case EVaRest_JsonType::JSON_String:
				Type = K2Schema->PC_String;
				break;

			case EVaRest_JsonType::JSON_Object:
				Type = K2Schema->PC_Object;
				Subtype = Class;
				break;
		}

		UEdGraphPin *OutputPin = CreatePin(EGPD_Output, Type, TEXT(""), Subtype, (*it).bIsArray, false, (*it).Name);
	}
}

FText UVaRest_BreakJson::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
	return LOCTEXT("VaRest_Break_Json.NodeTitle", "Break Json");
}

#undef LOCTEXT_NAMESPACE
<commit_msg>fix 4.13 regression<commit_after>// Copyright 2015 Vladimir Alyamkin. All Rights Reserved.
// Original code by https://github.com/unktomi

#include "VaRestEditorPluginPrivatePCH.h"
#include "VaRest_BreakJson.h"
#include "Runtime/Launch/Resources/Version.h"

#define LOCTEXT_NAMESPACE "VaRest_BreakJson"

class FKCHandler_BreakJson : public FNodeHandlingFunctor
{

public:
	FKCHandler_BreakJson(FKismetCompilerContext& InCompilerContext)
		: FNodeHandlingFunctor(InCompilerContext)
	{
	}

	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		UEdGraphPin* InputPin = NULL;

		for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
		{
			UEdGraphPin* Pin = Node->Pins[PinIndex];
			if (Pin && (EGPD_Input == Pin->Direction))
			{
				InputPin = Pin;
				break;
			}
		}

		UEdGraphPin *InNet = FEdGraphUtilities::GetNetFromPin(InputPin);
		UClass *Class = Cast<UClass>(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRestPlugin.VaRestJsonObject'")));

		FBPTerminal **SourceTerm = Context.NetMap.Find(InNet);
		if (SourceTerm == nullptr)
		{
			return;
		}

		for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
		{
			UEdGraphPin* Pin = Node->Pins[PinIndex];
			if (Pin && (EGPD_Output == Pin->Direction))
			{
				if (Pin->LinkedTo.Num() < 1)
				{
					continue;
				}

				FBPTerminal **Target = Context.NetMap.Find(Pin);

				const FString &FieldName = Pin->PinName;
				const FString &FieldType = Pin->PinType.PinCategory;

				FBPTerminal* FieldNameTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal);
				FieldNameTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_String;
#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 13
				FieldNameTerm->SourcePin = Pin;
#else
				FieldNameTerm->Source = Pin;
#endif
				FieldNameTerm->Name = FieldName;
				FieldNameTerm->TextLiteral = FText::FromString(FieldName);

 				FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node);
				FName FunctionName;

				bool bIsArray = Pin->PinType.bIsArray;

				if (FieldType == CompilerContext.GetSchema()->PC_Boolean)
				{
					FunctionName = bIsArray ? TEXT("GetBoolArrayField") : TEXT("GetBoolField");
				}
				else if (FieldType == CompilerContext.GetSchema()->PC_Float)
				{
					FunctionName = bIsArray ? TEXT("GetNumberArrayField") : TEXT("GetNumberField");
				}
				else if (FieldType == CompilerContext.GetSchema()->PC_String)
				{
					FunctionName = bIsArray ? TEXT("GetStringArrayField") : TEXT("GetStringField");
				}
				else if (FieldType == CompilerContext.GetSchema()->PC_Object)
				{
					FunctionName = bIsArray ? TEXT("GetObjectArrayField") : TEXT("GetObjectField");
				}
				else
				{
					continue;
				}

				UFunction *FunctionPtr = Class->FindFunctionByName(FunctionName);
				Statement.Type = KCST_CallFunction;
				Statement.FunctionToCall = FunctionPtr;
				Statement.FunctionContext = *SourceTerm;
				Statement.bIsParentContext = false;
				Statement.LHS = *Target;
				Statement.RHS.Add(FieldNameTerm);
			}
		}
	}

	FBPTerminal* RegisterInputTerm(FKismetFunctionContext& Context, UVaRest_BreakJson* Node)
	{
		// Find input pin
		UEdGraphPin* InputPin = NULL;
		for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
		{
			UEdGraphPin* Pin = Node->Pins[PinIndex];
			if (Pin && (EGPD_Input == Pin->Direction))
			{
				InputPin = Pin;
				break;
			}
		}
		check(NULL != InputPin);

		// Find structure source net
		UEdGraphPin* Net = FEdGraphUtilities::GetNetFromPin(InputPin);
		FBPTerminal **TermPtr = Context.NetMap.Find(Net);

		if (!TermPtr)
		{
			FBPTerminal *Term = Context.CreateLocalTerminalFromPinAutoChooseScope(Net, Context.NetNameMap->MakeValidName(Net));

			Context.NetMap.Add(Net, Term);

			return Term;
		}

		return *TermPtr;
	}

	void RegisterOutputTerm(FKismetFunctionContext& Context, UEdGraphPin* OutputPin, FBPTerminal* ContextTerm)
	{
		FBPTerminal *Term = Context.CreateLocalTerminalFromPinAutoChooseScope(OutputPin, Context.NetNameMap->MakeValidName(OutputPin));
		Context.NetMap.Add(OutputPin, Term);
	}

	virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* InNode) override
	{
		UVaRest_BreakJson* Node = Cast<UVaRest_BreakJson>(InNode);
		FNodeHandlingFunctor::RegisterNets(Context, Node);

		check(NULL != Node);

		if (FBPTerminal* StructContextTerm = RegisterInputTerm(Context, Node))
		{
			for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
			{
				UEdGraphPin* Pin = Node->Pins[PinIndex];
				if (NULL != Pin && EGPD_Output == Pin->Direction)
				{
					RegisterOutputTerm(Context, Pin, StructContextTerm);
				}
			}
		}
	}
};

/**
 * Main node class
 */
UVaRest_BreakJson::UVaRest_BreakJson(const FObjectInitializer &ObjectInitializer)
	: Super(ObjectInitializer)
{
}

FNodeHandlingFunctor* UVaRest_BreakJson::CreateNodeHandler(class FKismetCompilerContext& CompilerContext) const
{
	return new FKCHandler_BreakJson(CompilerContext);
}

void UVaRest_BreakJson::AllocateDefaultPins()
{
	const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();

	UClass *Class = Cast<UClass>(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRestPlugin.VaRestJsonObject'")));
	UEdGraphPin* Pin = CreatePin(EGPD_Input, K2Schema->PC_Object, TEXT(""), Class, false, false, TEXT("Target"));

	K2Schema->SetPinDefaultValueBasedOnType(Pin);

	CreateProjectionPins(Pin);
}

FLinearColor UVaRest_BreakJson::GetNodeTitleColor() const
{
	return FLinearColor(255.0f, 255.0f, 0.0f);
}

void UVaRest_BreakJson::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent)
{
	bool bIsDirty = false;

	FName PropertyName = (PropertyChangedEvent.Property != NULL) ? PropertyChangedEvent.Property->GetFName() : NAME_None;
	if (true || PropertyName == TEXT("Outputs"))
	{
		bIsDirty = true;
	}

	if (bIsDirty)
	{
		ReconstructNode();
		GetGraph()->NotifyGraphChanged();
	}

	Super::PostEditChangeProperty(PropertyChangedEvent);
}

void UVaRest_BreakJson::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
	// actions get registered under specific object-keys; the idea is that
	// actions might have to be updated (or deleted) if their object-key is
	// mutated (or removed)... here we use the node's class (so if the node
	// type disappears, then the action should go with it)
	UClass* ActionKey = GetClass();

	// to keep from needlessly instantiating a UBlueprintNodeSpawner, first
	// check to make sure that the registrar is looking for actions of this type
	// (could be regenerating actions for a specific asset, and therefore the
	// registrar would only accept actions corresponding to that asset)
	if (ActionRegistrar.IsOpenForRegistration(ActionKey))
	{
		UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass());
		check(NodeSpawner != nullptr);

		ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner);
	}
}

FText UVaRest_BreakJson::GetMenuCategory() const
{
	static FNodeTextCache CachedCategory;

	if (CachedCategory.IsOutOfDate(this))
	{
		// FText::Format() is slow, so we cache this to save on performance
		CachedCategory.SetCachedText(FEditorCategoryUtils::BuildCategoryString(FCommonEditorCategory::Utilities, LOCTEXT("ActionMenuCategory", "Va Rest")), this);
	}
	return CachedCategory;
}

void UVaRest_BreakJson::CreateProjectionPins(UEdGraphPin *Source)
{
	const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
	UClass *Class = Cast<UClass>(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRestPlugin.VaRestJsonObject'")));

	for (TArray<FVaRest_NamedType>::TIterator it(Outputs); it; ++it)
	{
		FString Type;
		UObject *Subtype = nullptr;
		FString FieldName = (*it).Name;

		switch ((*it).Type) {
			case EVaRest_JsonType::JSON_Bool:
				Type = K2Schema->PC_Boolean;
				break;

			case EVaRest_JsonType::JSON_Number:
				Type = K2Schema->PC_Float;
				break;

			case EVaRest_JsonType::JSON_String:
				Type = K2Schema->PC_String;
				break;

			case EVaRest_JsonType::JSON_Object:
				Type = K2Schema->PC_Object;
				Subtype = Class;
				break;
		}

		UEdGraphPin *OutputPin = CreatePin(EGPD_Output, Type, TEXT(""), Subtype, (*it).bIsArray, false, (*it).Name);
	}
}

FText UVaRest_BreakJson::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
	return LOCTEXT("VaRest_Break_Json.NodeTitle", "Break Json");
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012 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:
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "config.h"
#include "RenderThemeChromiumCommon.h"

#include "InputTypeNames.h"
#include "LayoutUnit.h"

// FIXME: Merge this.

namespace WebCore {

bool RenderThemeChromiumCommon::supportsDataListUI(const AtomicString& type)
{
    return type == InputTypeNames::text() || type == InputTypeNames::search() || type == InputTypeNames::url()
        || type == InputTypeNames::telephone() || type == InputTypeNames::email() || type == InputTypeNames::number()
#if ENABLE(INPUT_TYPE_COLOR)
        || type == InputTypeNames::color()
#endif
#if ENABLE(CALENDAR_PICKER)
        || type == InputTypeNames::date()
#endif
        || type == InputTypeNames::datetime()
        || type == InputTypeNames::datetimelocal()
        || type == InputTypeNames::month()
        || type == InputTypeNames::week()
        || type == InputTypeNames::time()
        || type == InputTypeNames::range();
}

#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
bool RenderThemeChromiumCommon::supportsCalendarPicker(const AtomicString& type)
{
    return type == InputTypeNames::date()
        || type == InputTypeNames::datetime()
        || type == InputTypeNames::datetimelocal()
        || type == InputTypeNames::month()
        || type == InputTypeNames::week();
}
#endif

LayoutUnit RenderThemeChromiumCommon::sliderTickSnappingThreshold()
{
    return 5;
}

}
<commit_msg>remove testing FIXME<commit_after>/*
 * Copyright (C) 2012 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:
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "config.h"
#include "RenderThemeChromiumCommon.h"

#include "InputTypeNames.h"
#include "LayoutUnit.h"

namespace WebCore {

bool RenderThemeChromiumCommon::supportsDataListUI(const AtomicString& type)
{
    return type == InputTypeNames::text() || type == InputTypeNames::search() || type == InputTypeNames::url()
        || type == InputTypeNames::telephone() || type == InputTypeNames::email() || type == InputTypeNames::number()
#if ENABLE(INPUT_TYPE_COLOR)
        || type == InputTypeNames::color()
#endif
#if ENABLE(CALENDAR_PICKER)
        || type == InputTypeNames::date()
#endif
        || type == InputTypeNames::datetime()
        || type == InputTypeNames::datetimelocal()
        || type == InputTypeNames::month()
        || type == InputTypeNames::week()
        || type == InputTypeNames::time()
        || type == InputTypeNames::range();
}

#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
bool RenderThemeChromiumCommon::supportsCalendarPicker(const AtomicString& type)
{
    return type == InputTypeNames::date()
        || type == InputTypeNames::datetime()
        || type == InputTypeNames::datetimelocal()
        || type == InputTypeNames::month()
        || type == InputTypeNames::week();
}
#endif

LayoutUnit RenderThemeChromiumCommon::sliderTickSnappingThreshold()
{
    return 5;
}

}
<|endoftext|>


<commit_before>#ifndef m_data_hpp_1337420
#define m_data_hpp_1337420

#include <cstdlib>
#include <cmath>
#include <memory>

#ifdef __stl_compatibility
	#include <string>
	#include <sstream>
#endif

#include "../ztl_base.hpp"

__ztl_namespace_start

class string {
public:
	typedef unsigned long long				size_type;
	typedef int						difference_type;
	typedef char*						iterator;
	typedef const char*					const_iterator;
	typedef __stl::reverse_iterator<iterator>		reverse_iterator;
	typedef __stl::reverse_iterator<const_iterator>		const_reverse_iterator;
	typedef __stl::random_access_iterator_tag		iterator_category;

private:
	int m_capacity;
	int m_length;
	char* m_data;

public:
	static string empty, npos;

	string() : m_capacity(16), m_length(0), m_data(new char[m_capacity + 1]) {
		memset(m_data, 0, m_capacity + 1);
	}

	string(const char * c_str) : m_length(0) {
		while (c_str[m_length] != '\0') m_length++;;
		m_capacity = m_length <= 16 ? 16 : m_length;
		m_data = new char[m_capacity + 1];
		memset(m_data, 0, m_capacity + 1);
		memcpy(m_data, c_str, m_length);
	}

	string(size_type _size) : m_capacity(_size), m_length(0), m_data(new char[m_capacity + 1]) {
		memset(m_data, 0, m_capacity + 1);
	}

	string::string(const string & _x) : m_capacity(_x.m_capacity), m_length(_x.m_length) {
		if (_x != string::empty) {
			m_data = new char[m_capacity + 1];
			memset(m_data, 0, m_capacity + 1);
			memcpy(m_data, _x.m_data, m_length);
		}
		else {
			m_data = NULL;
			m_length = 0;
			m_capacity = 0;
		}
	}

	~string()
	{
		m_length = 0;
		m_capacity = 0;
		delete[] m_data;
	}

#ifdef __stl_compatibility
	string(const __stl::string& _s) : m_length(_s.length()), m_capacity(m_length), m_data(new char[m_capacity + 1]) {
		memcpy(m_data, _s.c_str(), m_length);
		m_data[m_capacity] = '\0';
	}
#endif

	inline char& operator[](const int _i) { return m_data[_i]; }
	inline const char& operator[](const int _i) const { return m_data[_i]; }

	void operator+= (const string & _x) {
		if ((m_length + _x.m_length) > m_capacity) {
			m_capacity = m_length + _x.m_length;
			char *buffer = new char[m_capacity + 1];
			memset(buffer, 0, m_capacity + 1);
			memcpy(buffer, m_data, m_length);
			delete[] m_data;
			m_data = buffer;
		}

		memcpy(m_data + m_length, _x.m_data, _x.m_length);
		m_length += _x.m_length;
	}

	void operator+= (const char* const _x) {
		size_type strlen = 0;
		while (_x[strlen] != '\0') strlen++;
		if ((m_length + strlen) > m_capacity) {
			m_capacity = m_length + strlen;
			char *buffer = new char[m_capacity + 1];
			memset(buffer, 0, m_capacity + 1);
			memcpy(buffer, m_data, m_length);
			delete[] m_data;
			m_data = buffer;
		}

		memcpy(m_data + m_length, _x, strlen);
		m_length += strlen;
	}

	string& operator=(const string & _x)
	{
		if (m_capacity < _x.m_length)
			this->clear(_x.m_length);

		memcpy(m_data, _x.m_data, _x.m_length);
		m_length = _x.m_length;
		m_data[m_length] = 0;

		return *this;
	}

	string& operator=(const char * const _x)
	{
		m_length = 0;
		while (_x[m_length] != '\0') m_length++;

		delete[] m_data;
		m_capacity = m_length < 16 ? 16 : m_length;
		m_data = new char[m_capacity + 1];

		memset(m_data, 0, m_capacity + 1);
		memcpy(m_data, _x, m_length);

		return *this;
	}

	void clear() {
		delete[] m_data;
		m_data = new char[m_capacity + 1];
		memset(m_data, 0, m_capacity + 1);
		m_length = 0;
	}

	void clear(size_type _capacity) {
		delete[] m_data;
		m_capacity = _capacity;
		m_data = new char[m_capacity + 1];
		memset(m_data, 0, m_capacity + 1);
		m_length = 0;
	}

	inline void	resize(size_type n) {
		m_capacity = n;
		char *buffer = new char[m_capacity + 1];
		memset(buffer, 0, n + 1);
		memcpy(buffer, m_data, m_length);
		delete[] m_data;
		m_data = buffer;
		m_length = __min(m_length, n);
		m_data[m_length] = '\0';
	}

	inline void	resize(size_type n, char c) {
		m_capacity = n;
		char *buffer = new char[m_capacity + 1];
		memset(buffer, c, n + 1);
		memcpy(buffer, m_data, m_length);
		delete[] m_data;
		m_data = buffer;
		m_length = m_capacity;
		m_data[m_capacity] = '\0';
	}

	inline char& at(int _i) {
		if (_i < 0 || _i >= m_length) {
#ifdef __stl_compatibility
			throw __stl::out_of_range("Index out of range");
#else
			return NULL;
#endif
		}
		return m_data[_i];
	}

	inline const char& at(int _i) const {
		if (_i < 0 || _i >= m_length) {
#ifdef __stl_compatibility
			throw __stl::out_of_range("Index out of range");
#else
			return NULL;
#endif
		}
		return m_data[_i];
	}

	inline size_type			length() const { return m_length; }
	inline size_type			size() const { return m_length;	}
	inline size_type			max_size() const { return size_type(-1); }
	inline size_type			capacity() const { return m_capacity; }

	inline iterator				begin() { return m_data; }
	inline iterator				end() { return m_data + m_length; }
	inline const_iterator			cbegin() const { return m_data; }
	inline const_iterator			cend() const { return m_data + m_length; }
	inline reverse_iterator			rbegin() { return reverse_iterator(end()); }
	inline reverse_iterator			rend() { return reverse_iterator(begin()); }
	inline const_reverse_iterator		crbegin() const { return const_reverse_iterator(cend()); }
	inline const_reverse_iterator		crend() const { return const_reverse_iterator(cbegin()); }

	inline const char*			c_str() const { return m_data; }

	string& substr(int start_index, int length) const {
		if (start_index + length > m_length) {
#ifdef __stl_compatibility
			throw __stl::invalid_argument("string::substr: length exceed string length");
#else
			return string::empty;
#endif
		}

		char *buffer = new char[length + 1];
		memcpy(buffer, m_data + start_index, length);
		buffer[length] = '\0';
		string* temp = new string(buffer);
		delete[] buffer;
		return *temp;
	}

	// OPERATORS
	friend bool operator==(const string&, const string&);
	friend bool operator==(const string&, const char* const);
	friend bool operator> (const string&, const string&);
	friend bool operator> (const string&, const char*);
	friend bool operator< (const string&, const string&);
	friend bool operator< (const string&, const char*);
	friend bool operator>= (const string&, const string&);
	friend bool operator>= (const string&, const char*);
	friend bool operator<= (const string&, const string&);
	friend bool operator<= (const string&, const char*);
	friend bool operator!=(const string&, const string&);
	friend bool operator!=(const string&, const char*);

#ifdef __stl_compatibility

	friend __stl::ostream & operator<< (__stl::ostream & os, const string & _x);
	friend __stl::istream & operator>> (__stl::istream & is, string & _x);

#endif

};

string string::empty = string();
string string::npos = string();

bool operator> (const string& _x, const string& _y) {
	for (int i = 0; i < __min(_x.m_length, _y.m_length); i++) {
		if (_x[i] == _y[i]) continue;
		return _x[i] > _y[i];
	}
	return _x.length() > _y.length();
}

bool operator> (const string& _x, const char* _y) {
	int i;
	for (i = 0; i < _x.m_length; i++) {
		if (_x[i] == _y[i]) continue;
		return _y[i] == '\0' || _x[i] > _y[i];
	}
	return _y[i+1] != '\0';
}

bool operator== (const string& _x, const string& _y) {
	if (_x.m_length != _y.m_length) return false;
	for (int i = 0; i < _x.m_length; i++)
		if (_x[i] != _y[i]) return false;

	return true;
}

bool operator==(const string& _x, const char* _y) {
	int i;
	for (i = 0; i < _x.m_length; i++)
		if (_y[i] == '\0' || _x[i] != _y[i]) return false;

	return _y[++i] == '\0';
}

bool operator< (const string& _x, const string& _y) { return !(_x > _y || _x == _y); }
bool operator< (const string& _x, const char* _y) { return !(_x > _y || _x == _y); }
bool operator>= (const string& _x, const string& _y) { return !(_x < _y); }
bool operator>= (const string& _x, const char* _y) { return !(_x < _y); }
bool operator<= (const string& _x, const string& _y) { return !(_x > _y); }
bool operator<= (const string& _x, const char* _y) { return !(_x > _y); }
bool operator!=(const string& _x, const string& _y) { return !(_y == _x); }
bool operator!=(const string& _x, const char* _y) { return !(_y == _x); }

#ifdef __stl_compatibility

__stl::ostream & operator<< (__stl::ostream & os, const string & _x) {
	os << _x.m_data;
	return os;
}

__stl::istream & operator>> (__stl::istream & is, string& _x) {
	char *buffer = new char[1024];
	is.getline(buffer, 1024);

	if (is.gcount() > 0) {
		_x.clear(is.gcount());
		_x = buffer;
	}
	else
		_x.clear();

	return is;
}

#endif

__ztl_namespace_end

#endif
<commit_msg>Constructor edit<commit_after>#ifndef m_data_hpp_1337420
#define m_data_hpp_1337420

#include <cstdlib>
#include <cmath>
#include <memory>

#ifdef __stl_compatibility
	#include <string>
	#include <sstream>
#endif

#include "../ztl_base.hpp"

__ztl_namespace_start

class string {
public:
	typedef unsigned long long				size_type;
	typedef int						difference_type;
	typedef char*						iterator;
	typedef const char*					const_iterator;
	typedef __stl::reverse_iterator<iterator>		reverse_iterator;
	typedef __stl::reverse_iterator<const_iterator>		const_reverse_iterator;
	typedef __stl::random_access_iterator_tag		iterator_category;

private:
	int m_capacity;
	int m_length;
	char* m_data;

public:
	static string empty, npos;

	string() : m_capacity(16), m_length(0), m_data(new char[m_capacity + 1]) {
		memset(m_data, 0, m_capacity + 1);
	}

	string(const char * c_str) : m_length(0) {
		while (c_str[m_length] != '\0') m_length++;;
		m_capacity = m_length <= 16 ? 16 : m_length;
		m_data = new char[m_capacity + 1];
		memset(m_data, 0, m_capacity + 1);
		memcpy(m_data, c_str, m_length);
	}

	string(size_type _size) : m_capacity(_size), m_length(0), m_data(new char[m_capacity + 1]) {
		memset(m_data, 0, m_capacity + 1);
	}

	string(const string & _x) : m_capacity(_x.m_capacity), m_length(_x.m_length) {
		if (_x != string::empty) {
			m_data = new char[m_capacity + 1];
			memset(m_data, 0, m_capacity + 1);
			memcpy(m_data, _x.m_data, m_length);
		}
		else {
			m_data = NULL;
			m_length = 0;
			m_capacity = 0;
		}
	}

	~string() {
		m_length = 0;
		m_capacity = 0;
		delete[] m_data;
	}

#ifdef __stl_compatibility
	string(const __stl::string& _s) : m_length(_s.length()), m_capacity(m_length), m_data(new char[m_capacity + 1]) {
		memcpy(m_data, _s.c_str(), m_length);
		m_data[m_capacity] = '\0';
	}
#endif

	inline char& operator[](const int _i) { return m_data[_i]; }
	inline const char& operator[](const int _i) const { return m_data[_i]; }

	void operator+= (const string & _x) {
		if ((m_length + _x.m_length) > m_capacity) {
			m_capacity = m_length + _x.m_length;
			char *buffer = new char[m_capacity + 1];
			memset(buffer, 0, m_capacity + 1);
			memcpy(buffer, m_data, m_length);
			delete[] m_data;
			m_data = buffer;
		}

		memcpy(m_data + m_length, _x.m_data, _x.m_length);
		m_length += _x.m_length;
	}

	void operator+= (const char* const _x) {
		size_type strlen = 0;
		while (_x[strlen] != '\0') strlen++;
		if ((m_length + strlen) > m_capacity) {
			m_capacity = m_length + strlen;
			char *buffer = new char[m_capacity + 1];
			memset(buffer, 0, m_capacity + 1);
			memcpy(buffer, m_data, m_length);
			delete[] m_data;
			m_data = buffer;
		}

		memcpy(m_data + m_length, _x, strlen);
		m_length += strlen;
	}

	string& operator=(const string & _x)
	{
		if (m_capacity < _x.m_length)
			this->clear(_x.m_length);

		memcpy(m_data, _x.m_data, _x.m_length);
		m_length = _x.m_length;
		m_data[m_length] = 0;

		return *this;
	}

	string& operator=(const char * const _x)
	{
		m_length = 0;
		while (_x[m_length] != '\0') m_length++;

		delete[] m_data;
		m_capacity = m_length < 16 ? 16 : m_length;
		m_data = new char[m_capacity + 1];

		memset(m_data, 0, m_capacity + 1);
		memcpy(m_data, _x, m_length);

		return *this;
	}

	void clear() {
		delete[] m_data;
		m_data = new char[m_capacity + 1];
		memset(m_data, 0, m_capacity + 1);
		m_length = 0;
	}

	void clear(size_type _capacity) {
		delete[] m_data;
		m_capacity = _capacity;
		m_data = new char[m_capacity + 1];
		memset(m_data, 0, m_capacity + 1);
		m_length = 0;
	}

	inline void	resize(size_type n) {
		m_capacity = n;
		char *buffer = new char[m_capacity + 1];
		memset(buffer, 0, n + 1);
		memcpy(buffer, m_data, m_length);
		delete[] m_data;
		m_data = buffer;
		m_length = __min(m_length, n);
		m_data[m_length] = '\0';
	}

	inline void	resize(size_type n, char c) {
		m_capacity = n;
		char *buffer = new char[m_capacity + 1];
		memset(buffer, c, n + 1);
		memcpy(buffer, m_data, m_length);
		delete[] m_data;
		m_data = buffer;
		m_length = m_capacity;
		m_data[m_capacity] = '\0';
	}

	inline char& at(int _i) {
		if (_i < 0 || _i >= m_length) {
#ifdef __stl_compatibility
			throw __stl::out_of_range("Index out of range");
#else
			return NULL;
#endif
		}
		return m_data[_i];
	}

	inline const char& at(int _i) const {
		if (_i < 0 || _i >= m_length) {
#ifdef __stl_compatibility
			throw __stl::out_of_range("Index out of range");
#else
			return NULL;
#endif
		}
		return m_data[_i];
	}

	inline size_type			length() const { return m_length; }
	inline size_type			size() const { return m_length;	}
	inline size_type			max_size() const { return size_type(-1); }
	inline size_type			capacity() const { return m_capacity; }

	inline iterator				begin() { return m_data; }
	inline iterator				end() { return m_data + m_length; }
	inline const_iterator			cbegin() const { return m_data; }
	inline const_iterator			cend() const { return m_data + m_length; }
	inline reverse_iterator			rbegin() { return reverse_iterator(end()); }
	inline reverse_iterator			rend() { return reverse_iterator(begin()); }
	inline const_reverse_iterator		crbegin() const { return const_reverse_iterator(cend()); }
	inline const_reverse_iterator		crend() const { return const_reverse_iterator(cbegin()); }

	inline const char*			c_str() const { return m_data; }

	string& substr(int start_index, int length) const {
		if (start_index + length > m_length) {
#ifdef __stl_compatibility
			throw __stl::invalid_argument("string::substr: length exceed string length");
#else
			return string::empty;
#endif
		}

		char *buffer = new char[length + 1];
		memcpy(buffer, m_data + start_index, length);
		buffer[length] = '\0';
		string* temp = new string(buffer);
		delete[] buffer;
		return *temp;
	}

	// OPERATORS
	friend bool operator==(const string&, const string&);
	friend bool operator==(const string&, const char* const);
	friend bool operator> (const string&, const string&);
	friend bool operator> (const string&, const char*);
	friend bool operator< (const string&, const string&);
	friend bool operator< (const string&, const char*);
	friend bool operator>= (const string&, const string&);
	friend bool operator>= (const string&, const char*);
	friend bool operator<= (const string&, const string&);
	friend bool operator<= (const string&, const char*);
	friend bool operator!=(const string&, const string&);
	friend bool operator!=(const string&, const char*);

#ifdef __stl_compatibility

	friend __stl::ostream & operator<< (__stl::ostream & os, const string & _x);
	friend __stl::istream & operator>> (__stl::istream & is, string & _x);

#endif

};

string string::empty = string();
string string::npos = string();

bool operator> (const string& _x, const string& _y) {
	for (int i = 0; i < __min(_x.m_length, _y.m_length); i++) {
		if (_x[i] == _y[i]) continue;
		return _x[i] > _y[i];
	}
	return _x.length() > _y.length();
}

bool operator> (const string& _x, const char* _y) {
	int i;
	for (i = 0; i < _x.m_length; i++) {
		if (_x[i] == _y[i]) continue;
		return _y[i] == '\0' || _x[i] > _y[i];
	}
	return _y[i+1] != '\0';
}

bool operator== (const string& _x, const string& _y) {
	if (_x.m_length != _y.m_length) return false;
	for (int i = 0; i < _x.m_length; i++)
		if (_x[i] != _y[i]) return false;

	return true;
}

bool operator==(const string& _x, const char* _y) {
	int i;
	for (i = 0; i < _x.m_length; i++)
		if (_y[i] == '\0' || _x[i] != _y[i]) return false;

	return _y[++i] == '\0';
}

bool operator< (const string& _x, const string& _y) { return !(_x > _y || _x == _y); }
bool operator< (const string& _x, const char* _y) { return !(_x > _y || _x == _y); }
bool operator>= (const string& _x, const string& _y) { return !(_x < _y); }
bool operator>= (const string& _x, const char* _y) { return !(_x < _y); }
bool operator<= (const string& _x, const string& _y) { return !(_x > _y); }
bool operator<= (const string& _x, const char* _y) { return !(_x > _y); }
bool operator!=(const string& _x, const string& _y) { return !(_y == _x); }
bool operator!=(const string& _x, const char* _y) { return !(_y == _x); }

#ifdef __stl_compatibility

__stl::ostream & operator<< (__stl::ostream & os, const string & _x) {
	os << _x.m_data;
	return os;
}

__stl::istream & operator>> (__stl::istream & is, string& _x) {
	char *buffer = new char[1024];
	is.getline(buffer, 1024);

	if (is.gcount() > 0) {
		_x.clear(is.gcount());
		_x = buffer;
	}
	else
		_x.clear();

	return is;
}

#endif

__ztl_namespace_end

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Jeremy Lainé
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include <QDataStream>

#include "QXmppCodec.h"
#include "QXmppJingleIq.h"
#include "QXmppRtpChannel.h"

//#define QXMPP_DEBUG_RTP
#define SAMPLE_BYTES 2

const quint8 RTP_VERSION = 0x02;

class QXmppRtpChannelPrivate
{
public:
    QXmppRtpChannelPrivate();

    // signals
    bool signalsEmitted;
    qint64 writtenSinceLastEmit;

    // RTP
    QXmppCodec *codec;
    QHostAddress remoteHost;
    quint16 remotePort;

    QByteArray incomingBuffer;
    bool incomingBuffering;
    int incomingMinimum;
    int incomingMaximum;
    quint16 incomingSequence;
    quint32 incomingStamp;

    quint16 outgoingChunk;
    QByteArray outgoingBuffer;
    bool outgoingMarker;
    quint16 outgoingSequence;
    quint32 outgoingStamp;

    quint32 ssrc;
    QXmppJinglePayloadType payloadType;
};

QXmppRtpChannelPrivate::QXmppRtpChannelPrivate()
    : signalsEmitted(false),
    writtenSinceLastEmit(0),
    codec(0),
    incomingBuffering(true),
    incomingMinimum(0),
    incomingMaximum(0),
    incomingSequence(0),
    incomingStamp(0),
    outgoingMarker(true),
    outgoingSequence(0),
    outgoingStamp(0),
    ssrc(0)
{
    ssrc = qrand();
}

/// Creates a new RTP channel.
///
/// \param parent

QXmppRtpChannel::QXmppRtpChannel(QObject *parent)
    : QIODevice(parent),
    d(new QXmppRtpChannelPrivate)
{
    QXmppLoggable *logParent = qobject_cast<QXmppLoggable*>(parent);
    if (logParent) {
        connect(this, SIGNAL(logMessage(QXmppLogger::MessageType,QString)),
                logParent, SIGNAL(logMessage(QXmppLogger::MessageType,QString)));
    }
}

/// Destroys an RTP channel.
///

QXmppRtpChannel::~QXmppRtpChannel()
{
    delete d;
}

/// Returns the number of bytes that are available for reading.
///

qint64 QXmppRtpChannel::bytesAvailable() const
{
    return d->incomingBuffer.size();
}

/// Processes an incoming RTP packet.
///
/// \param ba
void QXmppRtpChannel::datagramReceived(const QByteArray &ba)
{
    if (!d->codec)
    {
        warning("QXmppRtpChannel::datagramReceived before codec selection");
        return;
    }

    if (ba.size() < 12 || (quint8(ba.at(0)) >> 6) != RTP_VERSION)
    {
        warning("QXmppRtpChannel::datagramReceived got an invalid RTP packet");
        return;
    }

    // parse RTP header
    QDataStream stream(ba);
    quint8 version, marker_type;
    quint32 ssrc;
    quint16 sequence;
    quint32 stamp;
    stream >> version;
    stream >> marker_type;
    stream >> sequence;
    stream >> stamp;
    stream >> ssrc;
    const bool marker = marker_type & 0x80;
    const quint8 type = marker_type & 0x7f;
    const qint64 packetLength = ba.size() - 12;

#ifdef QXMPP_DEBUG_RTP
    logReceived(QString("RTP packet seq %1 stamp %2 marker %3 type %4 size %5").arg(
            QString::number(sequence),
            QString::number(stamp),
            QString::number(marker),
            QString::number(type),
            QString::number(packetLength)));
#endif

    // check type
    if (type != d->payloadType.id())
    {
        warning(QString("RTP packet seq %1 has unknown type %2")
                .arg(QString::number(sequence))
                .arg(QString::number(type)));
        return;
    }

    // check sequence number
    if (!marker && sequence != d->incomingSequence + 1)
        warning(QString("RTP packet seq %1 is out of order, previous was %2")
                .arg(QString::number(sequence))
                .arg(QString::number(d->incomingSequence)));
    d->incomingSequence = sequence;

    // determine packet's position in the buffer (in bytes)
    qint64 packetOffset = 0;
    if (!d->incomingBuffer.isEmpty())
    {
        packetOffset = (stamp - d->incomingStamp) * SAMPLE_BYTES;
        if (packetOffset < 0)
        {
            warning(QString("RTP packet stamp %1 is too old, buffer start is %2")
                    .arg(QString::number(stamp))
                    .arg(QString::number(d->incomingStamp)));
            return;
        }
    } else {
        d->incomingStamp = stamp;
    }

    // allocate space for new packet
    if (packetOffset + packetLength > d->incomingBuffer.size())
        d->incomingBuffer += QByteArray(packetOffset + packetLength - d->incomingBuffer.size(), 0);
    QDataStream output(&d->incomingBuffer, QIODevice::WriteOnly);
    output.device()->seek(packetOffset);
    output.setByteOrder(QDataStream::LittleEndian);
    d->codec->decode(stream, output);

    // check whether we are running late
    if (d->incomingBuffer.size() > d->incomingMaximum)
    {
        const qint64 droppedSize = d->incomingBuffer.size() - d->incomingMinimum;
        debug(QString("RTP buffer is too full, dropping %1 bytes")
                .arg(QString::number(droppedSize)));
        d->incomingBuffer = d->incomingBuffer.right(d->incomingMinimum);
        d->incomingStamp += droppedSize / SAMPLE_BYTES;
    }
    // check whether we have filled the initial buffer
    if (d->incomingBuffer.size() >= d->incomingMinimum)
        d->incomingBuffering = false;
    if (!d->incomingBuffering)
        emit readyRead();
}

void QXmppRtpChannel::emitSignals()
{
    emit bytesWritten(d->writtenSinceLastEmit);
    d->writtenSinceLastEmit = 0;
    d->signalsEmitted = false;
}

/// Returns true, as the RTP channel is a sequential device.
///

bool QXmppRtpChannel::isSequential() const
{
    return true;
}

qint64 QXmppRtpChannel::readData(char * data, qint64 maxSize)
{
    // if we are filling the buffer, return empty samples
    if (d->incomingBuffering)
    {
        memset(data, 0, maxSize);
        return maxSize;
    }

    qint64 readSize = qMin(maxSize, qint64(d->incomingBuffer.size()));
    memcpy(data, d->incomingBuffer.constData(), readSize);
    d->incomingBuffer.remove(0, readSize);
    if (readSize < maxSize)
    {
#ifdef QXMPP_DEBUG_RTP
        debug(QString("QXmppRtpChannel::readData missing %1 bytes").arg(QString::number(maxSize - readSize)));
#endif
        memset(data + readSize, 0, maxSize - readSize);
    }
    d->incomingStamp += readSize / SAMPLE_BYTES;
    return maxSize;
}

/// Returns the RTP channel's payload type.
///
/// You can use this to determine the QAudioFormat to use with your
/// QAudioInput/QAudioOutput.

QXmppJinglePayloadType QXmppRtpChannel::payloadType() const
{
    return d->payloadType;
}

/// Sets the RTP channel's payload type.
///
/// \param payloadType

void QXmppRtpChannel::setPayloadType(const QXmppJinglePayloadType &payloadType)
{
    d->payloadType = payloadType;
    if (payloadType.id() == G711u)
        d->codec = new QXmppG711uCodec(payloadType.clockrate());
    else if (payloadType.id() == G711a)
        d->codec = new QXmppG711aCodec(payloadType.clockrate());
#ifdef QXMPP_USE_SPEEX
    else if (payloadType.name().toLower() == "speex")
        d->codec = new QXmppSpeexCodec(payloadType.clockrate());
#endif
    else
    {
        warning(QString("QXmppCall got an unknown codec : %1 (%2)")
                .arg(QString::number(payloadType.id()))
                .arg(payloadType.name()));
        return;
    }

    // size in bytes of an unencoded packet
    d->outgoingChunk = SAMPLE_BYTES * payloadType.ptime() * payloadType.clockrate() / 1000;

    // initial number of bytes to buffer
    d->incomingMinimum = d->outgoingChunk * 5;
    d->incomingMaximum = d->outgoingChunk * 8;

    open(QIODevice::ReadWrite | QIODevice::Unbuffered);
}

/// Returns the list of supported payload types.
///

QList<QXmppJinglePayloadType> QXmppRtpChannel::supportedPayloadTypes() const
{
    QList<QXmppJinglePayloadType> payloads;
    QXmppJinglePayloadType payload;

#ifdef QXMPP_USE_SPEEX
    payload.setId(96);
    payload.setChannels(1);
    payload.setName("SPEEX");
    payload.setClockrate(16000);
    payloads << payload;

    payload.setId(97);
    payload.setChannels(1);
    payload.setName("SPEEX");
    payload.setClockrate(8000);
    payloads << payload;
#endif

    payload.setId(QXmppRtpChannel::G711u);
    payload.setChannels(1);
    payload.setName("PCMU");
    payload.setClockrate(8000);
    payloads << payload;

    payload.setId(QXmppRtpChannel::G711a);
    payload.setChannels(1);
    payload.setName("PCMA");
    payload.setClockrate(8000);
    payloads << payload;

    return payloads;
}

qint64 QXmppRtpChannel::writeData(const char * data, qint64 maxSize)
{
    if (!d->codec)
    {
        warning("QXmppRtpChannel::writeData before codec was set");
        return -1;
    }

    d->outgoingBuffer += QByteArray::fromRawData(data, maxSize);
    while (d->outgoingBuffer.size() >= d->outgoingChunk)
    {
        QByteArray header;
        QDataStream stream(&header, QIODevice::WriteOnly);
        quint8 version = RTP_VERSION << 6;
        stream << version;
        quint8 marker_type = d->payloadType.id();
        if (d->outgoingMarker)
        {
            marker_type |= 0x80;
            d->outgoingMarker= false;
        }
        stream << marker_type;
        stream << ++d->outgoingSequence;
        stream << d->outgoingStamp;
        stream << d->ssrc;

        QByteArray chunk = d->outgoingBuffer.left(d->outgoingChunk);
        QDataStream input(chunk);
        input.setByteOrder(QDataStream::LittleEndian);
        d->outgoingStamp += d->codec->encode(input, stream);

#ifdef QXMPP_DEBUG_RTP
        logSent(QString("RTP packet seq %1 stamp %2 marker %3 type %4 size %5").arg(
                    QString::number(d->outgoingSequence),
                    QString::number(d->outgoingStamp),
                    QString::number(marker_type & 0x80 != 0),
                    QString::number(marker_type & 0x7f),
                    QString::number(header.size() - 12)));
#endif
        emit sendDatagram(header);

        d->outgoingBuffer.remove(0, chunk.size());
    }

    d->writtenSinceLastEmit += maxSize;
    if (!d->signalsEmitted && !signalsBlocked()) {
        d->signalsEmitted = true;
        QMetaObject::invokeMethod(this, "emitSignals", Qt::QueuedConnection);
    }

    return maxSize;
}
<commit_msg>fix a spurious RTP warning<commit_after>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Jeremy Lainé
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include <QDataStream>

#include "QXmppCodec.h"
#include "QXmppJingleIq.h"
#include "QXmppRtpChannel.h"

//#define QXMPP_DEBUG_RTP
#define SAMPLE_BYTES 2

const quint8 RTP_VERSION = 0x02;

class QXmppRtpChannelPrivate
{
public:
    QXmppRtpChannelPrivate();

    // signals
    bool signalsEmitted;
    qint64 writtenSinceLastEmit;

    // RTP
    QXmppCodec *codec;
    QHostAddress remoteHost;
    quint16 remotePort;

    QByteArray incomingBuffer;
    bool incomingBuffering;
    int incomingMinimum;
    int incomingMaximum;
    quint16 incomingSequence;
    quint32 incomingStamp;

    quint16 outgoingChunk;
    QByteArray outgoingBuffer;
    bool outgoingMarker;
    quint16 outgoingSequence;
    quint32 outgoingStamp;

    quint32 ssrc;
    QXmppJinglePayloadType payloadType;
};

QXmppRtpChannelPrivate::QXmppRtpChannelPrivate()
    : signalsEmitted(false),
    writtenSinceLastEmit(0),
    codec(0),
    incomingBuffering(true),
    incomingMinimum(0),
    incomingMaximum(0),
    incomingSequence(0),
    incomingStamp(0),
    outgoingMarker(true),
    outgoingSequence(0),
    outgoingStamp(0),
    ssrc(0)
{
    ssrc = qrand();
}

/// Creates a new RTP channel.
///
/// \param parent

QXmppRtpChannel::QXmppRtpChannel(QObject *parent)
    : QIODevice(parent),
    d(new QXmppRtpChannelPrivate)
{
    QXmppLoggable *logParent = qobject_cast<QXmppLoggable*>(parent);
    if (logParent) {
        connect(this, SIGNAL(logMessage(QXmppLogger::MessageType,QString)),
                logParent, SIGNAL(logMessage(QXmppLogger::MessageType,QString)));
    }
}

/// Destroys an RTP channel.
///

QXmppRtpChannel::~QXmppRtpChannel()
{
    delete d;
}

/// Returns the number of bytes that are available for reading.
///

qint64 QXmppRtpChannel::bytesAvailable() const
{
    return d->incomingBuffer.size();
}

/// Processes an incoming RTP packet.
///
/// \param ba
void QXmppRtpChannel::datagramReceived(const QByteArray &ba)
{
    if (!d->codec)
    {
        warning("QXmppRtpChannel::datagramReceived before codec selection");
        return;
    }

    if (ba.size() < 12 || (quint8(ba.at(0)) >> 6) != RTP_VERSION)
    {
        warning("QXmppRtpChannel::datagramReceived got an invalid RTP packet");
        return;
    }

    // parse RTP header
    QDataStream stream(ba);
    quint8 version, marker_type;
    quint32 ssrc;
    quint16 sequence;
    quint32 stamp;
    stream >> version;
    stream >> marker_type;
    stream >> sequence;
    stream >> stamp;
    stream >> ssrc;
    const bool marker = marker_type & 0x80;
    const quint8 type = marker_type & 0x7f;
    const qint64 packetLength = ba.size() - 12;

#ifdef QXMPP_DEBUG_RTP
    logReceived(QString("RTP packet seq %1 stamp %2 marker %3 type %4 size %5").arg(
            QString::number(sequence),
            QString::number(stamp),
            QString::number(marker),
            QString::number(type),
            QString::number(packetLength)));
#endif

    // check type
    if (type != d->payloadType.id())
    {
        warning(QString("RTP packet seq %1 has unknown type %2")
                .arg(QString::number(sequence))
                .arg(QString::number(type)));
        return;
    }

    // check sequence number
    if (d->incomingSequence && sequence != d->incomingSequence + 1)
        warning(QString("RTP packet seq %1 is out of order, previous was %2")
                .arg(QString::number(sequence))
                .arg(QString::number(d->incomingSequence)));
    d->incomingSequence = sequence;

    // determine packet's position in the buffer (in bytes)
    qint64 packetOffset = 0;
    if (!d->incomingBuffer.isEmpty())
    {
        packetOffset = (stamp - d->incomingStamp) * SAMPLE_BYTES;
        if (packetOffset < 0)
        {
            warning(QString("RTP packet stamp %1 is too old, buffer start is %2")
                    .arg(QString::number(stamp))
                    .arg(QString::number(d->incomingStamp)));
            return;
        }
    } else {
        d->incomingStamp = stamp;
    }

    // allocate space for new packet
    if (packetOffset + packetLength > d->incomingBuffer.size())
        d->incomingBuffer += QByteArray(packetOffset + packetLength - d->incomingBuffer.size(), 0);
    QDataStream output(&d->incomingBuffer, QIODevice::WriteOnly);
    output.device()->seek(packetOffset);
    output.setByteOrder(QDataStream::LittleEndian);
    d->codec->decode(stream, output);

    // check whether we are running late
    if (d->incomingBuffer.size() > d->incomingMaximum)
    {
        const qint64 droppedSize = d->incomingBuffer.size() - d->incomingMinimum;
        debug(QString("RTP buffer is too full, dropping %1 bytes")
                .arg(QString::number(droppedSize)));
        d->incomingBuffer = d->incomingBuffer.right(d->incomingMinimum);
        d->incomingStamp += droppedSize / SAMPLE_BYTES;
    }
    // check whether we have filled the initial buffer
    if (d->incomingBuffer.size() >= d->incomingMinimum)
        d->incomingBuffering = false;
    if (!d->incomingBuffering)
        emit readyRead();
}

void QXmppRtpChannel::emitSignals()
{
    emit bytesWritten(d->writtenSinceLastEmit);
    d->writtenSinceLastEmit = 0;
    d->signalsEmitted = false;
}

/// Returns true, as the RTP channel is a sequential device.
///

bool QXmppRtpChannel::isSequential() const
{
    return true;
}

qint64 QXmppRtpChannel::readData(char * data, qint64 maxSize)
{
    // if we are filling the buffer, return empty samples
    if (d->incomingBuffering)
    {
        memset(data, 0, maxSize);
        return maxSize;
    }

    qint64 readSize = qMin(maxSize, qint64(d->incomingBuffer.size()));
    memcpy(data, d->incomingBuffer.constData(), readSize);
    d->incomingBuffer.remove(0, readSize);
    if (readSize < maxSize)
    {
#ifdef QXMPP_DEBUG_RTP
        debug(QString("QXmppRtpChannel::readData missing %1 bytes").arg(QString::number(maxSize - readSize)));
#endif
        memset(data + readSize, 0, maxSize - readSize);
    }
    d->incomingStamp += readSize / SAMPLE_BYTES;
    return maxSize;
}

/// Returns the RTP channel's payload type.
///
/// You can use this to determine the QAudioFormat to use with your
/// QAudioInput/QAudioOutput.

QXmppJinglePayloadType QXmppRtpChannel::payloadType() const
{
    return d->payloadType;
}

/// Sets the RTP channel's payload type.
///
/// \param payloadType

void QXmppRtpChannel::setPayloadType(const QXmppJinglePayloadType &payloadType)
{
    d->payloadType = payloadType;
    if (payloadType.id() == G711u)
        d->codec = new QXmppG711uCodec(payloadType.clockrate());
    else if (payloadType.id() == G711a)
        d->codec = new QXmppG711aCodec(payloadType.clockrate());
#ifdef QXMPP_USE_SPEEX
    else if (payloadType.name().toLower() == "speex")
        d->codec = new QXmppSpeexCodec(payloadType.clockrate());
#endif
    else
    {
        warning(QString("QXmppCall got an unknown codec : %1 (%2)")
                .arg(QString::number(payloadType.id()))
                .arg(payloadType.name()));
        return;
    }

    // size in bytes of an unencoded packet
    d->outgoingChunk = SAMPLE_BYTES * payloadType.ptime() * payloadType.clockrate() / 1000;

    // initial number of bytes to buffer
    d->incomingMinimum = d->outgoingChunk * 5;
    d->incomingMaximum = d->outgoingChunk * 8;

    open(QIODevice::ReadWrite | QIODevice::Unbuffered);
}

/// Returns the list of supported payload types.
///

QList<QXmppJinglePayloadType> QXmppRtpChannel::supportedPayloadTypes() const
{
    QList<QXmppJinglePayloadType> payloads;
    QXmppJinglePayloadType payload;

#ifdef QXMPP_USE_SPEEX
    payload.setId(96);
    payload.setChannels(1);
    payload.setName("SPEEX");
    payload.setClockrate(16000);
    payloads << payload;

    payload.setId(97);
    payload.setChannels(1);
    payload.setName("SPEEX");
    payload.setClockrate(8000);
    payloads << payload;
#endif

    payload.setId(QXmppRtpChannel::G711u);
    payload.setChannels(1);
    payload.setName("PCMU");
    payload.setClockrate(8000);
    payloads << payload;

    payload.setId(QXmppRtpChannel::G711a);
    payload.setChannels(1);
    payload.setName("PCMA");
    payload.setClockrate(8000);
    payloads << payload;

    return payloads;
}

qint64 QXmppRtpChannel::writeData(const char * data, qint64 maxSize)
{
    if (!d->codec)
    {
        warning("QXmppRtpChannel::writeData before codec was set");
        return -1;
    }

    d->outgoingBuffer += QByteArray::fromRawData(data, maxSize);
    while (d->outgoingBuffer.size() >= d->outgoingChunk)
    {
        QByteArray header;
        QDataStream stream(&header, QIODevice::WriteOnly);
        quint8 version = RTP_VERSION << 6;
        stream << version;
        quint8 marker_type = d->payloadType.id();
        if (d->outgoingMarker)
        {
            marker_type |= 0x80;
            d->outgoingMarker= false;
        }
        stream << marker_type;
        stream << ++d->outgoingSequence;
        stream << d->outgoingStamp;
        stream << d->ssrc;

        QByteArray chunk = d->outgoingBuffer.left(d->outgoingChunk);
        QDataStream input(chunk);
        input.setByteOrder(QDataStream::LittleEndian);
        d->outgoingStamp += d->codec->encode(input, stream);

#ifdef QXMPP_DEBUG_RTP
        logSent(QString("RTP packet seq %1 stamp %2 marker %3 type %4 size %5").arg(
                    QString::number(d->outgoingSequence),
                    QString::number(d->outgoingStamp),
                    QString::number(marker_type & 0x80 != 0),
                    QString::number(marker_type & 0x7f),
                    QString::number(header.size() - 12)));
#endif
        emit sendDatagram(header);

        d->outgoingBuffer.remove(0, chunk.size());
    }

    d->writtenSinceLastEmit += maxSize;
    if (!d->signalsEmitted && !signalsBlocked()) {
        d->signalsEmitted = true;
        QMetaObject::invokeMethod(this, "emitSignals", Qt::QueuedConnection);
    }

    return maxSize;
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// type_traits

// is_base_of

#include <type_traits>

#include "test_macros.h"

//	Clang before v9 and apple-clang up to and including v10 do not
//  report that unions are never base classes - nor can they have bases.
//  See https://reviews.llvm.org/D61858
// XFAIL: apple-clang-6.0, apple-clang-7.0, apple-clang-8.0, apple-clang-9.0, apple-clang-10.0
// XFAIL: clang-3.3, clang-3.4, clang-3.5, clang-3.6, clang-3.7, clang-3.8, clang-3.9
// XFAIL: clang-4.0, clang-5.0, clang-6.0, clang-7.0, clang-8.0

template <class T, class U>
void test_is_base_of()
{
    static_assert((std::is_base_of<T, U>::value), "");
    static_assert((std::is_base_of<const T, U>::value), "");
    static_assert((std::is_base_of<T, const U>::value), "");
    static_assert((std::is_base_of<const T, const U>::value), "");
#if TEST_STD_VER > 14
    static_assert((std::is_base_of_v<T, U>), "");
    static_assert((std::is_base_of_v<const T, U>), "");
    static_assert((std::is_base_of_v<T, const U>), "");
    static_assert((std::is_base_of_v<const T, const U>), "");
#endif
}

template <class T, class U>
void test_is_not_base_of()
{
    static_assert((!std::is_base_of<T, U>::value), "");
}

struct B {};
struct B1 : B {};
struct B2 : B {};
struct D : private B1, private B2 {};
union U0;
union U1 {};
struct I0;
struct I1 {};

int main(int, char**)
{
//	A union is never the base class of anything (including incomplete types)
    test_is_not_base_of<U0, B>();
    test_is_not_base_of<U0, B1>();
    test_is_not_base_of<U0, B2>();
    test_is_not_base_of<U0, D>();
    test_is_not_base_of<U1, B>();
    test_is_not_base_of<U1, B1>();
    test_is_not_base_of<U1, B2>();
    test_is_not_base_of<U1, D>();
    test_is_not_base_of<U0, I0>();
    test_is_not_base_of<U1, I1>();
    test_is_not_base_of<U0, U1>();
    test_is_not_base_of<U0, int>();
    test_is_not_base_of<U1, int>();
    test_is_not_base_of<I0, int>();
    test_is_not_base_of<I1, int>();

//	A union never has base classes (including incomplete types)
    test_is_not_base_of<B,  U0>();
    test_is_not_base_of<B1, U0>();
    test_is_not_base_of<B2, U0>();
    test_is_not_base_of<D,  U0>();
    test_is_not_base_of<B,  U1>();
    test_is_not_base_of<B1, U1>();
    test_is_not_base_of<B2, U1>();
    test_is_not_base_of<D,  U1>();
    test_is_not_base_of<I0, U0>();
    test_is_not_base_of<I1, U1>();
    test_is_not_base_of<U1, U0>();
    test_is_not_base_of<int, U0>();
    test_is_not_base_of<int, U1>();
    test_is_not_base_of<int, I0>();
    test_is_not_base_of<int, I1>();

  return 0;
}
<commit_msg>[libc++] Re-apply XFAIL to is_base_of test that was inadvertently reverted<commit_after>//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// type_traits

// is_base_of

#include <type_traits>

#include "test_macros.h"

//  Clang before v9 and apple-clang up to and including v10 do not
//  report that unions are never base classes - nor can they have bases.
//  See https://reviews.llvm.org/D61858
// XFAIL: apple-clang-6.0, apple-clang-7.0, apple-clang-8.0
// XFAIL: apple-clang-9.0, apple-clang-9.1, apple-clang-10.0
// XFAIL: clang-3.3, clang-3.4, clang-3.5, clang-3.6, clang-3.7, clang-3.8, clang-3.9
// XFAIL: clang-4.0, clang-5.0, clang-6.0, clang-7.0, clang-8.0

template <class T, class U>
void test_is_base_of()
{
    static_assert((std::is_base_of<T, U>::value), "");
    static_assert((std::is_base_of<const T, U>::value), "");
    static_assert((std::is_base_of<T, const U>::value), "");
    static_assert((std::is_base_of<const T, const U>::value), "");
#if TEST_STD_VER > 14
    static_assert((std::is_base_of_v<T, U>), "");
    static_assert((std::is_base_of_v<const T, U>), "");
    static_assert((std::is_base_of_v<T, const U>), "");
    static_assert((std::is_base_of_v<const T, const U>), "");
#endif
}

template <class T, class U>
void test_is_not_base_of()
{
    static_assert((!std::is_base_of<T, U>::value), "");
}

struct B {};
struct B1 : B {};
struct B2 : B {};
struct D : private B1, private B2 {};
union U0;
union U1 {};
struct I0;
struct I1 {};

int main(int, char**)
{
    // A union is never the base class of anything (including incomplete types)
    test_is_not_base_of<U0, B>();
    test_is_not_base_of<U0, B1>();
    test_is_not_base_of<U0, B2>();
    test_is_not_base_of<U0, D>();
    test_is_not_base_of<U1, B>();
    test_is_not_base_of<U1, B1>();
    test_is_not_base_of<U1, B2>();
    test_is_not_base_of<U1, D>();
    test_is_not_base_of<U0, I0>();
    test_is_not_base_of<U1, I1>();
    test_is_not_base_of<U0, U1>();
    test_is_not_base_of<U0, int>();
    test_is_not_base_of<U1, int>();
    test_is_not_base_of<I0, int>();
    test_is_not_base_of<I1, int>();

    // A union never has base classes (including incomplete types)
    test_is_not_base_of<B,  U0>();
    test_is_not_base_of<B1, U0>();
    test_is_not_base_of<B2, U0>();
    test_is_not_base_of<D,  U0>();
    test_is_not_base_of<B,  U1>();
    test_is_not_base_of<B1, U1>();
    test_is_not_base_of<B2, U1>();
    test_is_not_base_of<D,  U1>();
    test_is_not_base_of<I0, U0>();
    test_is_not_base_of<I1, U1>();
    test_is_not_base_of<U1, U0>();
    test_is_not_base_of<int, U0>();
    test_is_not_base_of<int, U1>();
    test_is_not_base_of<int, I0>();
    test_is_not_base_of<int, I1>();

  return 0;
}
<|endoftext|>


<commit_before>
/*********************************************************************************************************
HOGtrain.c is used to train the pedestrian detection system.
*********************************************************************************************************/
float* model;
int modelflag=0;

#include "HOGtrain.hpp"

using namespace cv;
using namespace std;

char method_id[STR_SIZE];
static inline float min(float x, float y) { return (x <= y ? x : y); }
static inline float max(float x, float y) { return (x <= y ? y : x); }

static inline int min(int x, int y) { return (x <= y ? x : y); }
static inline int max(int x, int y) { return (x <= y ? y : x); }

/*****************************************************************
Helper function to set the descriptor parameters
******************************************************************/

dtct_s setDescriptorParams(char *hCell,char *wCell,char *hBlock,char *wBlock,char *n_bins)
{
	dtct_s dtctInfo;
	dtctInfo.hCell_i = atoi(hCell);
	dtctInfo.wCell_i = atoi(wCell);
	dtctInfo.hBlck_i = atoi(hBlock);
	dtctInfo.wBlck_i = atoi(wBlock);
	dtctInfo.nBins_i = atoi(n_bins);
	return dtctInfo;
}

/*****************************************************************
Helper function to compute the image gradient
******************************************************************/

Grad_s *computeGradient(IplImage *inputImg)
{
	Grad_s *imgGrad;
	imgGrad = (Grad_s*) malloc(sizeof(Grad_s));
	imgGrad->Gradientinit(inputImg->width,inputImg->height);
	imageGradient(inputImg,imgGrad);
	return imgGrad;
}

/**********************************************************************
Helper function to compute the image histogram
**********************************************************************/

imgHist_s *computeHistogram(double *img_rank_s, Grad_s *imgGrad, dtct_s dtctInfo, int method_no, int n_channels, int width, int height)
{
	imgHist_s *imgHist;
	imgHist = (imgHist_s*) malloc(sizeof(imgHist_s));
	imgHist->imgHistogramInit(dtctInfo,width,height);
	cellwiseImgHistogram(img_rank_s, imgGrad,imgHist,dtctInfo,method_no,n_channels,width,height);
	return imgHist;
}

/**********************************************************************
Returns the pixel intensity values in a single dimensional array
This might be buggy.  It doesn't take into account the widthStep param
and the depth-major order of opencv's iplimage.
**********************************************************************/

rank *getIntensityValues(IplImage *inputImg,int no_bins)
{
	char *imagechar;
	int dims[2];
	int index;
	imagechar = inputImg->imageData;
	dims[0] = inputImg->width;
	dims[1] = inputImg->height;
    long pxlCnt = dims[0]*dims[1];

    rank *rk = (rank *)malloc(sizeof(rank));
	rk->rankInit(dims,no_bins,inputImg->nChannels,pxlCnt);

	for(index = 0; index < dims[0]*dims[1]*inputImg->nChannels; index++)
	{
		rk->img_rank[index] = imagechar[index]; //store the intensity values
	}

	return rk;
}

/**********************************************************
computes the intensity histogram of an image
Used to detect a homogeneous patch in an image
***********************************************************/

void calcHistogram(int hist[],int bins,IplImage *img)
{
	int div_fac = 255/bins; div_fac++;
	int i;
	for(i=0;i<bins;i++)hist[i]=0;
	for(i=0;i<img->height;i++)
	   {
			uchar *ptr = (uchar *)(img->imageData + i*img->widthStep);
			for(int j=0;j<img->widthStep;j++)
			{
				double intensity = ptr[j];
				int bin = (int)intensity/div_fac;
				hist[bin]++;
			}

	   }
}

/**********************************************************
checks if the image is homogeneous
***********************************************************/
int isHomogeneous(IplImage *img)
{
	int hist[25],bins = 25;
	calcHistogram(hist,bins,img);
	int no_pixels = img->width*img->height;
	int thresh = 0.7*no_pixels;
	for(int i=0;i<bins;i++) {
		//printf("%d\t",hist[i]);
		if(hist[i]>=thresh)
		{
			return 1;
		}
	}
	return 0;
}

/*****************************************************
Modify the descriptor data for homogeneous patches
******************************************************/

void modifyFV(descriptor_s **descriptorData)
{
	int fv_size = (*descriptorData)->descriptorSize_i;
	for(int i=0;i<fv_size;i++)
		(*descriptorData)->featureVector_pf[i] = 0.0;
}

/**********************************************************
Returns the feature vector formed by HOG
***********************************************************/

descriptor_s *getHOG_Descp(IplImage *inputImg, int method_no, dtct_s dtctInfo)
{
	Grad_s *imgGrad;
	imgHist_s *imgHist;
	descriptor_s *descriptorData;
	imgGrad = computeGradient(inputImg); //compute the gradient
	imgHist = computeHistogram(NULL,imgGrad,dtctInfo,method_no,inputImg->nChannels,inputImg->width,inputImg->height);
	descriptorData = normalizeWindow(0,0,&dtctInfo,imgHist,1);

	imgGrad->GradientRelease();
	free(imgGrad);

	imgHist->imgHistogramRelease();
    free(imgHist);

	return descriptorData;
}

/*********************************************************************
Function to apply different methods
**********************************************************************/
descriptor_s *computeDescriptor(IplImage *inputImg,char **histParams)
{
	dtct_s dtctInfo;

	if(atoi(histParams[0]) == 2 && atoi(histParams[5])<16)
		strcpy(histParams[5],"16");

	//int no_of_bins = atoi(histParams[9]);
	int method_no = atoi(histParams[0]);

	dtctInfo = setDescriptorParams(histParams[1],histParams[2],histParams[3],histParams[4],histParams[5]);
	dtctInfo.wDtct_i = inputImg->width;
	dtctInfo.hDtct_i = inputImg->height;
    //compute other descriptors
    descriptor_s * descriptorData = getHOG_Descp(inputImg, method_no, dtctInfo);
	return descriptorData;
}

bool checkFile(char opFileName[])
{
	return (bool)fopen(opFileName,"r");
}

/********************************************
 Main function
********************************************/
//command_line_argument: a.out arguments_file SVM_Prediction_Threshold  Testing_Category
//arguments file format
/*
* 10 //number of lines in this file
* pos_train_path
* neg_train_path
* pos_test_path
* neg_test_path
* filename_prefix_for_trainDataInput_to_svm_train
* filename_prefix_for_testDataInput_to_svm_predict
* filename_prefix_for_output_of_svm_predict
* method_id
* filename_prefix_for_concise_output_of_svm_predict and also file appending the results.
* God Knows! (the code doesn't have any usage of filepaths[10])
*
*/

string int2String(unsigned long long num)
{
    char str[64+1];//can handle upto 2^64 digits for unsigned long long
    sprintf(str,"%lld",num);
    return(string(str));
}

//get the descriptor libsvm
string float2String(double num)
{
    char strNum[308+1]; //10^308
    sprintf(strNum,"%.7f",num);

    //discard trailing zeroes
    int i=strlen(strNum);

    while(strNum[--i] == '0');
    if(strNum[i] != '.')
        ++i;
    //i = (strNum[i] == '.') ? i : ++i;
    strNum[i] = 0;

    return(string(strNum));
}

//convert the given descriptor into the libsvm format and return as a string
string getFV_LIBSVMFormat(float* desc, int size, int classlabel)
{
    string imgDesc(int2String(classlabel));
    imgDesc += " ";

    for(int i = 0; i < size; i++)
    {
        imgDesc += int2String(i+1);
        imgDesc += ":";
        imgDesc += float2String(desc[i]);
        imgDesc += " ";
    }
    imgDesc += "\n";

    return imgDesc;
}

bool fileExists(char *fileName)
{
	ifstream ifile(fileName);
	return (bool) ifile;
}

/***************************************************
Function to train the SVM with descriptor data
****************************************************/
void trainSVM(char* trainFeatFile, char* trainModelFile)
{
    if(fileExists(trainModelFile))
    {
        fprintf(stderr,"%s exists.  Skipping training.\n",trainModelFile);
    }
    else
    {
        //building model file
        char train_cmd[2*STR_SIZE];
        char trainMsgFile[1000];
        strcpy(trainMsgFile,trainModelFile);
        //get training info file from the model file
        char* modelPtr = strstr(trainMsgFile,".model");
        *modelPtr = '_';
        strcat(trainMsgFile,".txt");

        fprintf(stderr, "Training SVM....\n");
        sprintf(train_cmd, "./liblinear-1.93/train -B 1 %s %s", trainFeatFile, trainModelFile);
        strcat(strcat(train_cmd," > "), trainMsgFile);

        //sprintf(train_cmd,"svm-train -s 0 -b 1 %s",trainFile);
        //printf("%s\n", train_cmd);
        system(train_cmd);
    }
}

int main(int argc,char *argv[])
{
	if(argc != 6)
	{
		fprintf(stderr,"Wrong number of arguments :: Usage :: ./a.out desc_id pos_Training_Dir neg_Training_Dir descFile_save_Name modelFileName\n\n");
		exit(-1);
	}

	//argv[1] contains the descriptor id
	//argv[2] contains the path of the positive images & pos.txt
	//argv[3] contains the path of the negative images & neg.txt
	//argv[4] contains the filename to which descriptors will be written
	//argv[5] contains the model file containing the SVM-parameters

    char **histParams = 0;
    string class_Label = "0";

	histParams = new char*[6];
    histParams[0]= argv[1]; //descriptor id
    histParams[1]=(char*)"8"; //horizontal width of a cell in terms of pixels
    histParams[2]=(char*)"8"; //vertical width of a cell in terms of pixels
    histParams[3]=(char*)"2"; //horizontal width of a block in terms of cells
    histParams[4]=(char*)"2"; //vertical width of a block in terms of cells
    histParams[5]=(char*)orientBinCnt; //no.of orientation bins

    ofstream des;

    //open descriptor file dir
    if(fileExists(argv[4]))
    {
        fprintf(stdout,"%s already exists! Skipping description computation\n",argv[4]);
    }
    else
    {
        Mat trainImg;
        Mat img3 = Mat(128,64,CV_8UC1);

        //get the number of images
        FILE *fp = NULL;
        char op[50];
        long int numPosImg,numNegImg;

        //positive images
        string txtFileName = string(argv[2]) + string("pos.txt");
        if(access(txtFileName.c_str(), F_OK) == -1)//check for existence
        {
            //pos.txt doesn't exist
            fprintf(stderr,"%s doesn't exist!\n",txtFileName.c_str());
            exit(-1);
        }
        //number of positive images
        fp = popen(string(string("cat ") + txtFileName + string(" | wc")).c_str(),"r");
        fscanf(fp,"%s",op);
        numPosImg = atol(op);
        pclose(fp);

        //negative images
        txtFileName.clear();
        txtFileName = string(argv[3]) + string("neg.txt");
        if(access(txtFileName.c_str(), F_OK) == -1)
        {
            //neg.txt doesn't exist
            fprintf(stderr,"%s doesn't exist!\n",txtFileName.c_str());
            exit(-1);
        }
        //number of negative images
        fp = popen(string(string("cat ") + txtFileName + string(" | wc")).c_str(),"r");
        fscanf(fp,"%s",op);
        numNegImg = atol(op);
        pclose(fp);

        int label;
        string desc_libSVMFormat[numPosImg+numNegImg];

        //create the descriptors file
        FILE* descFile = fopen(argv[4],"w");
        if(!descFile)
        {
            fprintf(stderr,"%s cannot be opened :(\n",argv[4]) ;
            exit(-1);
        }

        //Descriptors for pos images
        string ymlFileName = string(argv[2]) + string("pos.yml");
        if(access(ymlFileName.c_str(),F_OK) == -1)
        {
            //pos.yml doesn't exist!
            fprintf(stderr, "%s doesn't exist!\n", ymlFileName.c_str());
            exit(-1);
        }
        fprintf(stderr,"Opening the positive image storage\n");
        FileStorage posStorage(ymlFileName.c_str(),FileStorage::READ);
        label = 1;

        //compute the descriptors
        fprintf(stderr,"Collecing the positive descriptors\n");
        //omp_set_num_threads(NUM_THREADS);
        //#pragma omp parallel for
        for(int cnt=0; cnt < numPosImg; cnt++)
        {
            //private variables
            string imgId="img";
            descriptor_s *descriptorData_curr;
            float *a;
            int ln;

            //get the image id that is used to hash into the storage
            imgId += int2String(cnt);
            fprintf(stderr,"%s: train positives: %s/%ld\n",argv[5], imgId.c_str(),numPosImg);

            //store the image in Mat
            posStorage[imgId]>>trainImg;

            //resize
            resize(trainImg,img3,img3.size(),0.0,0.0,1);

            //display
            if(DISPLAY)
            {
                imshow("pos",img3);
                waitKey(2);
            }

            //compute the descriptor
            IplImage image=img3.operator IplImage();
            descriptorData_curr = computeDescriptor(&image,histParams);
            ln=descriptorData_curr->descriptorSize_i;
            a = descriptorData_curr->featureVector_pf;

            //write it to a vector of string descriptor
            desc_libSVMFormat[cnt] = getFV_LIBSVMFormat(a, ln, label);

            //reset
            descriptorData_curr->descriptorRelease();
            free(descriptorData_curr);

            imgId = "img";
        }

        //reset
        posStorage.release();

//***********************************************************************************************************************

        //Descriptors for neg images
        ymlFileName.clear();
        ymlFileName = string(argv[3]) + string("neg.yml");
        if(access(ymlFileName.c_str(), F_OK) == -1)
        {
            //neg.yml doesn't exist!
            fprintf(stderr,"%s doesn't exist!\n",ymlFileName.c_str());
            exit(-1);
        }
        fprintf(stderr,"Opening the negative image storage\n");
        FileStorage negStorage(ymlFileName.c_str(),FileStorage::READ);

        //set
        label = 0;

        //compute the descriptors
        fprintf(stderr,"Collecing the negative descriptors\n");
        //omp_set_num_threads(NUM_THREADS);
        //#pragma omp parallel for
        for(int cnt=numPosImg; cnt < numNegImg+numPosImg; cnt++)
        {
            //private variables
            string imgId="img";
            //Mat img3=Mat(128,64,CV_8UC1);
            descriptor_s *descriptorData_curr;
            float *a;
            int ln;

            //get the image id that is used to hash into the storage
            imgId += int2String(cnt-numPosImg);
            fprintf(stderr,"%s: train negatives: %s/%ld\n",argv[5],imgId.c_str(),numNegImg);

            //store the image in Mat
            negStorage[imgId]>>trainImg;

            //resize
            resize(trainImg,img3,img3.size(),0.0,0.0,1);

            //display
            if(DISPLAY)
            {
                imshow("neg",img3);
                waitKey(2);
            }

            //compute the descriptor
            IplImage image=img3.operator IplImage();
            descriptorData_curr = computeDescriptor(&image,histParams);
            ln=descriptorData_curr->descriptorSize_i;
            a = descriptorData_curr->featureVector_pf;

            //write it to a vector of string descriptor
            desc_libSVMFormat[cnt] = getFV_LIBSVMFormat(a, ln, label);

            //reset
            descriptorData_curr->descriptorRelease();
            free(descriptorData_curr);

            imgId = "img";
        }
        //reset
        negStorage.release();

        fprintf(stderr,"Saving the descriptors...\n");

        //write the descriptors to the feature vectors file in one-shot
        for(int i = 0; i < numNegImg+numPosImg; i++)
            fprintf(descFile,"%s",desc_libSVMFormat[i].c_str());
    }

    if(fileExists(argv[5]))
        fprintf(stderr,"%s exists!  Skipping training.\n",argv[5]);
    else
        trainSVM(argv[4],argv[5]);

    delete [] histParams;
}
<commit_msg>Delete train.cpp<commit_after><|endoftext|>


<commit_before>/*
 * mod_compare - compare apache requests
 *
 * Copyright (C) 2013 Orange
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mod_migrate.hh"
#include "RequestInfo.hh"
#include "Utils.hh"

#include <http_config.h>
#include <assert.h>
#include <stdexcept>
#include <boost/thread/detail/singleton.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/tokenizer.hpp>
#include <iomanip>
#include <apache2/httpd.h>
#include <boost/regex.hpp>

namespace MigrateModule {

static bool setEnvVar(request_rec *pRequest, const MigrateConf::MigrateEnv &ctx, const std::string& toSet, int& count) {
    if (!toSet.empty()) {
        Log::debug("CE: URL match: Value to set: %s, varName: %s", toSet.c_str(), ctx.mVarName.c_str());
#ifndef UNIT_TESTING
        apr_table_set(pRequest->subprocess_env, ctx.mVarName.c_str(), toSet.c_str());
#endif
        return true;
    }
    return false;
}

/*
 * Parse the MigrateEnv objects and for each of them
 * If the regex matches (in the right scope), then it sets the environment variable
 */
int enrichContext(request_rec *pRequest, const RequestInfo &rInfo) {
    MigrateConf *conf = reinterpret_cast<MigrateConf *>(ap_get_module_config(pRequest->per_dir_config, &migrate_module));
    if (!conf || !conf->mDirName) {
        // Not a location that we treat, we decline the request
        return DECLINED;
    }

    // No filters for this path
    if (conf->mEnvLists.empty())
        return 0;
    int count = 0;
    const std::list<MigrateConf::MigrateEnv>& envList = conf->mEnvLists;

    // Iteration through context enrichment
    BOOST_FOREACH(const MigrateConf::MigrateEnv &ctx, conf->mEnvLists) {
        if (ctx.mApplicationScope & ApplicationScope::URL) {
            std::string toSet = boost::regex_replace(rInfo.mArgs, ctx.mMatchRegex, ctx.mSetValue, boost::match_default | boost::format_no_copy);
            count += (int)setEnvVar(pRequest, ctx, toSet, count);
        }
        if ((ctx.mApplicationScope & ApplicationScope::BODY) && !rInfo.mBody.empty()) {
            std::string toSet = regex_replace(rInfo.mBody, ctx.mMatchRegex, ctx.mSetValue, boost::match_default | boost::format_no_copy);
            count += (int)setEnvVar(pRequest, ctx, toSet, count);
        }
        if ((ctx.mApplicationScope & ApplicationScope::HEADER) && !rInfo.mHeader.empty()) {
            std::string toSet = regex_replace(rInfo.mHeader, ctx.mMatchRegex, ctx.mSetValue, boost::match_default | boost::format_no_copy);
            count += (int)setEnvVar(pRequest, ctx, toSet, count);
        }
    }
    return count;
}

/*
 * Callback to iterate over the headers tables
 * Pushes a copy of key => value in a list passed without typing as the first argument
 */
static int iterateOverHeadersCallBack(void *d, const char *key, const char *value) {
    std::string *headers = reinterpret_cast<std::string *>(d);
    headers->append(std::string(key)+std::string(": ")+std::string(value)+"\r\n");
    return 1;
}

/*
 * Translate_name level HOOK
 *   - Read the body of a request.
 *   - Analyse request (body and header) with a synchroneous call on RequestProcessor::enrichContext method
 *   - If enrichment criteria are satisfied, the request context is enriched
 *   - This context can be used by mod_rewrite to redirect/modify the request
 *   - A RequestInfo object (containing the body) is stored in the request_config array. This object
 *      will be used by the inputfilter named 'inputFilterBody2Brigade' that reinjects the body to the input filters that follow him
 *   - A shared pointer manages the requestcontext object lifespan.
 */
int translateHook(request_rec *pRequest) {
    if (!pRequest->per_dir_config)
        return DECLINED;
    MigrateConf *conf = reinterpret_cast<MigrateConf *>(ap_get_module_config(pRequest->per_dir_config, &migrate_module));
    if (!conf || !conf->mDirName) {
        // Not a location that we treat, we decline the request
        return DECLINED;
    }

    if (!pRequest->connection->pool) {
        Log::error(42, "No connection pool associated to the request");
        return DECLINED;
    }
    if (!pRequest->connection->bucket_alloc) {
        pRequest->connection->bucket_alloc = apr_bucket_alloc_create(pRequest->connection->pool);
        if (!pRequest->connection->bucket_alloc) {
            Log::error(42, "Request bucket allocation failed");
            return DECLINED;
        }
    }

    boost::shared_ptr<RequestInfo>* wrappedInfo = CommonModule::makeRequestInfo<RequestInfo,&migrate_module>(pRequest);
    RequestInfo *info = wrappedInfo->get();
    apr_bucket_brigade *bb = apr_brigade_create(pRequest->connection->pool, pRequest->connection->bucket_alloc);

    if (!bb) {
        Log::error(42, "[MIGRATE] Bucket brigade allocation failed");
        return DECLINED;
    }
    std::string body;
    while (!CommonModule::extractBrigadeContent(bb, pRequest->input_filters, info->mBody)){
        apr_brigade_cleanup(bb);
    }
    apr_brigade_cleanup(bb);
    // Body read :)

    // Copy headers in
    apr_table_do(&iterateOverHeadersCallBack, &info->mHeader, pRequest->headers_in, NULL);

    const char* lID = apr_table_get(pRequest->headers_in, CommonModule::c_UNIQUE_ID);
    // Copy Request ID in both headers
    if(lID == NULL) {
        apr_table_set(pRequest->headers_in, CommonModule::c_UNIQUE_ID, info->mId.c_str());
        apr_table_set(pRequest->headers_out, CommonModule::c_UNIQUE_ID, info->mId.c_str());
    }
    else {
        apr_table_set(pRequest->headers_out, CommonModule::c_UNIQUE_ID, lID);
    }

    // Synchronous context enrichment
    info->mConf = conf;
    info->mArgs = pRequest->args ? pRequest->args : "";
    enrichContext(pRequest, *info);
    pRequest->read_length = 0;

    return DECLINED;
}

/**
 * InputFilter which target is to fill the brigade passed as an argument with
 * the body read in the previous hook: 'translateName'
 */
apr_status_t inputFilterBody2Brigade(ap_filter_t *pF, apr_bucket_brigade *pB, ap_input_mode_t pMode, apr_read_type_e pBlock, apr_off_t pReadbytes)
{
    Log::debug("[MIGRATE] inputFilterBody2Brigade");
    request_rec *pRequest = pF->r;
    if (!pRequest || !pRequest->per_dir_config) {
        return ap_get_brigade(pF->next, pB, pMode, pBlock, pReadbytes);
    }

    // Retrieve request info from context
    boost::shared_ptr<RequestInfo> *shPtr = reinterpret_cast<boost::shared_ptr<RequestInfo> *>(ap_get_module_config(pRequest->request_config, &migrate_module));
    if (!shPtr) {
        // Happens after a rewrite on a location that we do not treat
        return ap_get_brigade(pF->next, pB, pMode, pBlock, pReadbytes);

    }
    RequestInfo *info = shPtr->get();

    if (pF->ctx != (void *) -1) {
        if (!pF->ctx) {
            pRequest->remaining = info->mBody.size();
        }
        long int read = (long int) pF->ctx;
        int bSize = info->mBody.size();
        int toRead = std::min((bSize - read), pReadbytes);
        if (toRead > 0) {
            apr_status_t st;
            if ((st = apr_brigade_write(pB, NULL, NULL, info->mBody.c_str() + read, toRead)) != APR_SUCCESS ) {
                Log::warn(1, "Failed to write request body in a brigade: %s",  info->mBody.c_str());
                return st;
            }
            read += toRead;
            pRequest->remaining -= toRead;
        }
        // Request context update
        if (read >= bSize) {
            pF->ctx = (void *) -1;
        } else {
            pF->ctx = (void*)(read);
        }

    }  else {
        return ap_get_brigade(pF->next, pB, pMode, pBlock, pReadbytes);
    }
    return APR_SUCCESS;
}

};
<commit_msg>now input filter return always ap_get_brigade<commit_after>/*
 * mod_compare - compare apache requests
 *
 * Copyright (C) 2013 Orange
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mod_migrate.hh"
#include "RequestInfo.hh"
#include "Utils.hh"

#include <http_config.h>
#include <assert.h>
#include <stdexcept>
#include <boost/thread/detail/singleton.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/tokenizer.hpp>
#include <iomanip>
#include <apache2/httpd.h>
#include <boost/regex.hpp>

namespace MigrateModule {

static bool setEnvVar(request_rec *pRequest, const MigrateConf::MigrateEnv &ctx, const std::string& toSet, int& count) {
    if (!toSet.empty()) {
        Log::debug("CE: URL match: Value to set: %s, varName: %s", toSet.c_str(), ctx.mVarName.c_str());
#ifndef UNIT_TESTING
        apr_table_set(pRequest->subprocess_env, ctx.mVarName.c_str(), toSet.c_str());
#endif
        return true;
    }
    return false;
}

/*
 * Parse the MigrateEnv objects and for each of them
 * If the regex matches (in the right scope), then it sets the environment variable
 */
int enrichContext(request_rec *pRequest, const RequestInfo &rInfo) {
    MigrateConf *conf = reinterpret_cast<MigrateConf *>(ap_get_module_config(pRequest->per_dir_config, &migrate_module));
    if (!conf || !conf->mDirName) {
        // Not a location that we treat, we decline the request
        return DECLINED;
    }

    // No filters for this path
    if (conf->mEnvLists.empty())
        return 0;
    int count = 0;
    const std::list<MigrateConf::MigrateEnv>& envList = conf->mEnvLists;

    // Iteration through context enrichment
    BOOST_FOREACH(const MigrateConf::MigrateEnv &ctx, conf->mEnvLists) {
        if (ctx.mApplicationScope & ApplicationScope::URL) {
            std::string toSet = boost::regex_replace(rInfo.mArgs, ctx.mMatchRegex, ctx.mSetValue, boost::match_default | boost::format_no_copy);
            count += (int)setEnvVar(pRequest, ctx, toSet, count);
        }
        if ((ctx.mApplicationScope & ApplicationScope::BODY) && !rInfo.mBody.empty()) {
            std::string toSet = regex_replace(rInfo.mBody, ctx.mMatchRegex, ctx.mSetValue, boost::match_default | boost::format_no_copy);
            count += (int)setEnvVar(pRequest, ctx, toSet, count);
        }
        if ((ctx.mApplicationScope & ApplicationScope::HEADER) && !rInfo.mHeader.empty()) {
            std::string toSet = regex_replace(rInfo.mHeader, ctx.mMatchRegex, ctx.mSetValue, boost::match_default | boost::format_no_copy);
            count += (int)setEnvVar(pRequest, ctx, toSet, count);
        }
    }
    return count;
}

/*
 * Callback to iterate over the headers tables
 * Pushes a copy of key => value in a list passed without typing as the first argument
 */
static int iterateOverHeadersCallBack(void *d, const char *key, const char *value) {
    std::string *headers = reinterpret_cast<std::string *>(d);
    headers->append(std::string(key)+std::string(": ")+std::string(value)+"\r\n");
    return 1;
}

/*
 * Translate_name level HOOK
 *   - Read the body of a request.
 *   - Analyse request (body and header) with a synchroneous call on RequestProcessor::enrichContext method
 *   - If enrichment criteria are satisfied, the request context is enriched
 *   - This context can be used by mod_rewrite to redirect/modify the request
 *   - A RequestInfo object (containing the body) is stored in the request_config array. This object
 *      will be used by the inputfilter named 'inputFilterBody2Brigade' that reinjects the body to the input filters that follow him
 *   - A shared pointer manages the requestcontext object lifespan.
 */
int translateHook(request_rec *pRequest) {
    if (!pRequest->per_dir_config)
        return DECLINED;
    MigrateConf *conf = reinterpret_cast<MigrateConf *>(ap_get_module_config(pRequest->per_dir_config, &migrate_module));
    if (!conf || !conf->mDirName) {
        // Not a location that we treat, we decline the request
        return DECLINED;
    }

    if (!pRequest->connection->pool) {
        Log::error(42, "No connection pool associated to the request");
        return DECLINED;
    }
    if (!pRequest->connection->bucket_alloc) {
        pRequest->connection->bucket_alloc = apr_bucket_alloc_create(pRequest->connection->pool);
        if (!pRequest->connection->bucket_alloc) {
            Log::error(42, "Request bucket allocation failed");
            return DECLINED;
        }
    }

    boost::shared_ptr<RequestInfo>* wrappedInfo = CommonModule::makeRequestInfo<RequestInfo,&migrate_module>(pRequest);
    RequestInfo *info = wrappedInfo->get();
    apr_bucket_brigade *bb = apr_brigade_create(pRequest->connection->pool, pRequest->connection->bucket_alloc);

    if (!bb) {
        Log::error(42, "[MIGRATE] Bucket brigade allocation failed");
        return DECLINED;
    }
    std::string body;
    while (!CommonModule::extractBrigadeContent(bb, pRequest->input_filters, info->mBody)){
        apr_brigade_cleanup(bb);
    }
    apr_brigade_cleanup(bb);
    // Body read :)

    // Copy headers in
    apr_table_do(&iterateOverHeadersCallBack, &info->mHeader, pRequest->headers_in, NULL);

    const char* lID = apr_table_get(pRequest->headers_in, CommonModule::c_UNIQUE_ID);
    // Copy Request ID in both headers
    if(lID == NULL) {
        apr_table_set(pRequest->headers_in, CommonModule::c_UNIQUE_ID, info->mId.c_str());
        apr_table_set(pRequest->headers_out, CommonModule::c_UNIQUE_ID, info->mId.c_str());
    }
    else {
        apr_table_set(pRequest->headers_out, CommonModule::c_UNIQUE_ID, lID);
    }

    // Synchronous context enrichment
    info->mConf = conf;
    info->mArgs = pRequest->args ? pRequest->args : "";
    enrichContext(pRequest, *info);
    pRequest->read_length = 0;

    return DECLINED;
}

/**
 * InputFilter which target is to fill the brigade passed as an argument with
 * the body read in the previous hook: 'translateName'
 */
apr_status_t inputFilterBody2Brigade(ap_filter_t *pF, apr_bucket_brigade *pB, ap_input_mode_t pMode, apr_read_type_e pBlock, apr_off_t pReadbytes)
{
    Log::debug("[MIGRATE] inputFilterBody2Brigade");
    request_rec *pRequest = pF->r;
    if (!pRequest || !pRequest->per_dir_config) {
        return ap_get_brigade(pF->next, pB, pMode, pBlock, pReadbytes);
    }

    // Retrieve request info from context
    boost::shared_ptr<RequestInfo> *shPtr = reinterpret_cast<boost::shared_ptr<RequestInfo> *>(ap_get_module_config(pRequest->request_config, &migrate_module));
    if (!shPtr) {
        // Happens after a rewrite on a location that we do not treat
        return ap_get_brigade(pF->next, pB, pMode, pBlock, pReadbytes);

    }
    RequestInfo *info = shPtr->get();

    if (pF->ctx != (void *) -1) {
        if (!pF->ctx) {
            pRequest->remaining = info->mBody.size();
        }
        long int read = (long int) pF->ctx;
        int bSize = info->mBody.size();
        int toRead = std::min((bSize - read), pReadbytes);
        if (toRead > 0) {
            apr_status_t st;
            if ((st = apr_brigade_write(pB, NULL, NULL, info->mBody.c_str() + read, toRead)) != APR_SUCCESS ) {
                Log::warn(1, "Failed to write request body in a brigade: %s",  info->mBody.c_str());
                return st;
            }
            read += toRead;
            pRequest->remaining -= toRead;
        }
        // Request context update
        if (read >= bSize) {
            pF->ctx = (void *) -1;
        } else {
            pF->ctx = (void*)(read);
        }

    }  else {
        return ap_get_brigade(pF->next, pB, pMode, pBlock, pReadbytes);
    }
    return ap_get_brigade(pF->next, pB, pMode, pBlock, pReadbytes);
}

};
<|endoftext|>