<commit_before>//..............................................................................
//
//  This file is part of the Jancy toolkit.
//
//  Jancy is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/jancy/license.txt
//
//..............................................................................

#include "pch.h"
#include "modulepane.h"
#include "mdichild.h"
#include "moc_modulepane.cpp"

ModulePane::ModulePane(QWidget *parent)
	: QTreeWidget(parent)
{
	document = 0;

	setColumnCount(1);
	header()->hide();

	QObject::connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
		this, SLOT(onItemDoubleClicked(QTreeWidgetItem *, int)));
}

bool ModulePane::build(jnc::Module* module, MdiChild* document)
{
	clear();

	jnc::GlobalNamespace* globalNamespace = module->getGlobalNamespace();
	addNamespace(0, globalNamespace);

	this->document = document;

	return true;
}

void ModulePane::clear()
{
	QTreeWidget::clear();
	document = 0;
}

void ModulePane::onItemDoubleClicked(QTreeWidgetItem *treeItem, int column)
{
	QVariant variant = treeItem->data(0, Qt::UserRole);
	if(variant.isNull())
		return;

	jnc::ModuleItemDecl* decl = (jnc::ModuleItemDecl*)variant.value<void*> ();
	if (!decl)
		return;

	document->selectLine(decl->getLine(), true);
	document->setFocus();
}

QTreeWidgetItem *ModulePane::insertItem(const QString &text, QTreeWidgetItem *parent)
{
	QTreeWidgetItem *item = new QTreeWidgetItem;
	item->setText(0, text);

	if (parent)
		parent->addChild(item);
	else
		addTopLevelItem(item);

	return item;
}

bool ModulePane::addItemAttributes(QTreeWidgetItem *parent, jnc::ModuleItemDecl *decl)
{
	jnc::AttributeBlock *attributeBlock = decl->getAttributeBlock();
	if (!attributeBlock)
		return false;

	QTreeWidgetItem *attributes = insertItem("attributes", parent);

	size_t count = attributeBlock->getAttributeCount();
	for (size_t i = 0; i < count; i++)
	{
		jnc::Attribute* attribute = attributeBlock->getAttribute(i);
		jnc::ModuleItemDecl* decl = attribute->getDecl();

		QTreeWidgetItem *item = insertItem(decl->getName(), attributes);
		item->setData(0, Qt::UserRole, qVariantFromValue((void*)decl));
	}

	expandItem(attributes);
	return true;
}

void ModulePane::addNamespace(QTreeWidgetItem *parent,
	jnc::GlobalNamespace *globalNamespace)
{
	jnc::ModuleItemKind itemKind = globalNamespace->getItemKind();

	QTreeWidgetItem *treeItem = 0;

	if (itemKind == jnc::ModuleItemKind_Scope)
	{
		treeItem = insertItem("scope", parent);
	}
	else if (!globalNamespace->getDecl()->getParentNamespace())
	{
		treeItem = insertItem("global", parent);
	}
	else
	{
		QString text;
		text.sprintf("namespace %s",
			(const char *)globalNamespace->getDecl()->getName());

		treeItem = insertItem(text, parent);
	}

	treeItem->setData(0, Qt::UserRole, qVariantFromValue((void*)globalNamespace->getDecl()));

	jnc::Namespace* nspace = globalNamespace->getNamespace();
	size_t count = nspace->getItemCount();
	for (size_t i = 0; i < count; i++) {
		jnc::ModuleItem *child = nspace->getItem(i);
		addItem(treeItem, child);
	}

	expandItem(treeItem);
}

void ModulePane::addItem(QTreeWidgetItem *parent, jnc::ModuleItem *item)
{
	jnc::ModuleItemKind itemKind = item->getItemKind();

	QString name;
	QTreeWidgetItem* treeItem;

	switch (itemKind)
	{
	case jnc::ModuleItemKind_Namespace:
		addNamespace(parent, (jnc::GlobalNamespace*)item);
		break;

	case jnc::ModuleItemKind_Type:
		addType(parent, (jnc::Type*)item);
		break;

	case jnc::ModuleItemKind_Typedef:
		addTypedef(parent, (jnc::Typedef*)item);
		break;

	case jnc::ModuleItemKind_Variable:
		addVariable(parent, (jnc::Variable*)item);
		break;

	case jnc::ModuleItemKind_Function:
		addFunction(parent, (jnc::Function*)item);
		break;

	case jnc::ModuleItemKind_Property:
		addProperty(parent, (jnc::Property*)item);
		break;

	case jnc::ModuleItemKind_EnumConst:
		addEnumConst(parent, (jnc::EnumConst*)item);
		break;

	case jnc::ModuleItemKind_Field:
		addField(parent, (jnc::Field*)item);
		break;

	case jnc::ModuleItemKind_Lazy:
		// don't display lazy items
		break;

	case jnc::ModuleItemKind_Alias:
		addAlias(parent, (jnc::Alias*)item);
		break;

	default:
		name.sprintf("item %p of kind %d", item, itemKind);

		treeItem = insertItem(name, parent);
		treeItem->setText(0, name);
	}
}

void ModulePane::addType(QTreeWidgetItem *parent, jnc::Type *type)
{
	QString itemName = (const char *)type->getTypeString();

	QTreeWidgetItem *item = insertItem(itemName, parent);

	if (type->getFlags() & jnc::ModuleItemFlag_LayoutReady)
	{
		QString toolTip = QString("%1 (sizeof = %2)").arg (type->getTypeString()).arg (type->getSize ());
		item->setToolTip(0, toolTip);
	}

	jnc::ModuleItemDecl* decl = NULL;
	jnc::TypeKind typeKind = type->getTypeKind();
	switch (typeKind)
	{
	case jnc::TypeKind_Enum:
		decl = ((jnc::EnumType *)type)->getDecl();
		addItemAttributes(item, decl);
		addEnumTypeMembers(item, (jnc::EnumType *)type);
		break;

	case jnc::TypeKind_Struct:
	case jnc::TypeKind_Union:
	case jnc::TypeKind_Class:
		decl = ((jnc::DerivableType *)type)->getDecl();
		addItemAttributes(item, decl);
		addDerivableTypeMembers(item, (jnc::DerivableType *)type);
		break;
	}

	item->setData(0, Qt::UserRole, qVariantFromValue((void*)decl));
}

void ModulePane::addTypedef(QTreeWidgetItem *parent, jnc::Typedef* tdef)
{
	QString name;
	name.sprintf("typedef %s %s %s",
		tdef->getType()->getTypeStringPrefix(),
		tdef->getDecl()->getName(),
		tdef->getType()->getTypeStringSuffix()
		);

	QTreeWidgetItem *item = insertItem(name, parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)tdef->getDecl()));
}

void ModulePane::addVariable(QTreeWidgetItem *parent, jnc::Variable *variable)
{
	addValue(parent, variable->getDecl()->getName(), variable->getType(), variable);
}

void ModulePane::addEnumConst(QTreeWidgetItem *parent, jnc::EnumConst *member)
{
	QTreeWidgetItem *item = insertItem((const char*) member->getDecl()->getName(), parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)member->getDecl()));
}

void ModulePane::addValue(QTreeWidgetItem *parent, const QString& name, jnc::Type* type, jnc::ModuleItem* moduleItem)
{
	QString itemName = QString("%1 %2 %3").arg (type->getTypeStringPrefix ()).arg (name).arg (type->getTypeStringSuffix ());
	QTreeWidgetItem *item = insertItem(itemName, parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)moduleItem->getDecl()));

	if (jnc::isClassType(type, jnc::ClassTypeKind_Reactor))
		addDerivableTypeMembers(item, (jnc::ClassType*)type);
}

void ModulePane::addEnumTypeMembers(QTreeWidgetItem *parent, jnc::EnumType* type)
{
	size_t count = type->getConstCount();
	for (size_t i = 0; i < count; i++)
	{
		jnc::EnumConst* member = type->getConst(i);
		addEnumConst(parent, member);
	}

	expandItem(parent);
}

void ModulePane::addDerivableTypeMembers(QTreeWidgetItem *parent, jnc::DerivableType *type)
{
	size_t count = type->getStaticVariableCount();
	for (size_t i = 0; i < count; i++)
		addVariable(parent, type->getStaticVariable(i));

	count = type->getFieldCount();
	for (size_t i = 0; i < count; i++)
		addField(parent, type->getField(i));

	if (type->getStaticConstructor())
		addItem(parent, type->getStaticConstructor());

	if (type->getConstructor())
		addOverloadableFunction(parent, type->getConstructor());

	if (type->getDestructor())
		addItem(parent, type->getDestructor());

	count = type->getPropertyCount();
	for (size_t i = 0; i < count; i++)
		addProperty(parent, type->getProperty(i));

	count = type->getMethodCount();
	for (size_t i = 0; i < count; i++)
		addFunction(parent, type->getMethod(i));

	expandItem(parent);
}

void ModulePane::addFunction(QTreeWidgetItem *parent, jnc::Function* function)
{
	jnc::FunctionType* type = function->getType();

	const char* name = function->getFunctionKind() == jnc::FunctionKind_Normal ?
		function->getDecl()->getName() :
		jnc::getFunctionKindString(function->getFunctionKind());

	QString itemName = QString("%1 %2%3").arg(type->getTypeStringPrefix(), name, type->getTypeStringSuffix());
	QTreeWidgetItem *item = insertItem(itemName, parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)function->getDecl()));
}

void ModulePane::addFunctionOverload(QTreeWidgetItem *parent, jnc::FunctionOverload* overload)
{
	size_t count = overload->getOverloadCount();

	const char* name = overload->getFunctionKind() == jnc::FunctionKind_Normal ?
		overload->getDecl()->getName() :
		jnc::getFunctionKindString(overload->getFunctionKind());

	QString itemName = QString("%1 (%2 overloads)").arg(name).arg(count);

	QTreeWidgetItem *item = insertItem(itemName, parent);
	for (size_t i = 0; i < count; i++)
	{
		jnc::Function* function = overload->getOverload(i);
		addFunction(item, function);
	}

	expandItem(item);
}

void ModulePane::addOverloadableFunction(QTreeWidgetItem* parent, jnc::OverloadableFunction function)
{
	function->getItemKind() == jnc::ModuleItemKind_Function ?
		addFunction(parent, function.getFunction()) :
		addFunctionOverload(parent, function.getFunctionOverload());
}

void ModulePane::addProperty(QTreeWidgetItem *parent, jnc::Property* prop)
{
	QTreeWidgetItem *item = insertItem(prop->getDecl()->getName(), parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)prop->getDecl()));

	jnc::Function* getter = prop->getGetter();
	addFunction(item, getter);

	jnc::OverloadableFunction setter = prop->getSetter();
	if (setter)
		addOverloadableFunction(item, setter);

	expandItem(item);
}

void ModulePane::addAlias(QTreeWidgetItem* parent, jnc::Alias* alias)
{
	QString name;
	name.sprintf(
		"alias %s = %s",
		alias->getDecl()->getName(),
		alias->getInitializerString_v()
		);

	QTreeWidgetItem *item = insertItem(name, parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)alias->getDecl()));
}
<commit_msg>[jnc_test_qt] removed handing of ModuleItemKind_Lazy<commit_after>//..............................................................................
//
//  This file is part of the Jancy toolkit.
//
//  Jancy is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/jancy/license.txt
//
//..............................................................................

#include "pch.h"
#include "modulepane.h"
#include "mdichild.h"
#include "moc_modulepane.cpp"

ModulePane::ModulePane(QWidget *parent)
	: QTreeWidget(parent)
{
	document = 0;

	setColumnCount(1);
	header()->hide();

	QObject::connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
		this, SLOT(onItemDoubleClicked(QTreeWidgetItem *, int)));
}

bool ModulePane::build(jnc::Module* module, MdiChild* document)
{
	clear();

	jnc::GlobalNamespace* globalNamespace = module->getGlobalNamespace();
	addNamespace(0, globalNamespace);

	this->document = document;

	return true;
}

void ModulePane::clear()
{
	QTreeWidget::clear();
	document = 0;
}

void ModulePane::onItemDoubleClicked(QTreeWidgetItem *treeItem, int column)
{
	QVariant variant = treeItem->data(0, Qt::UserRole);
	if(variant.isNull())
		return;

	jnc::ModuleItemDecl* decl = (jnc::ModuleItemDecl*)variant.value<void*> ();
	if (!decl)
		return;

	document->selectLine(decl->getLine(), true);
	document->setFocus();
}

QTreeWidgetItem *ModulePane::insertItem(const QString &text, QTreeWidgetItem *parent)
{
	QTreeWidgetItem *item = new QTreeWidgetItem;
	item->setText(0, text);

	if (parent)
		parent->addChild(item);
	else
		addTopLevelItem(item);

	return item;
}

bool ModulePane::addItemAttributes(QTreeWidgetItem *parent, jnc::ModuleItemDecl *decl)
{
	jnc::AttributeBlock *attributeBlock = decl->getAttributeBlock();
	if (!attributeBlock)
		return false;

	QTreeWidgetItem *attributes = insertItem("attributes", parent);

	size_t count = attributeBlock->getAttributeCount();
	for (size_t i = 0; i < count; i++)
	{
		jnc::Attribute* attribute = attributeBlock->getAttribute(i);
		jnc::ModuleItemDecl* decl = attribute->getDecl();

		QTreeWidgetItem *item = insertItem(decl->getName(), attributes);
		item->setData(0, Qt::UserRole, qVariantFromValue((void*)decl));
	}

	expandItem(attributes);
	return true;
}

void ModulePane::addNamespace(QTreeWidgetItem *parent,
	jnc::GlobalNamespace *globalNamespace)
{
	jnc::ModuleItemKind itemKind = globalNamespace->getItemKind();

	QTreeWidgetItem *treeItem = 0;

	if (itemKind == jnc::ModuleItemKind_Scope)
	{
		treeItem = insertItem("scope", parent);
	}
	else if (!globalNamespace->getDecl()->getParentNamespace())
	{
		treeItem = insertItem("global", parent);
	}
	else
	{
		QString text;
		text.sprintf("namespace %s",
			(const char *)globalNamespace->getDecl()->getName());

		treeItem = insertItem(text, parent);
	}

	treeItem->setData(0, Qt::UserRole, qVariantFromValue((void*)globalNamespace->getDecl()));

	jnc::Namespace* nspace = globalNamespace->getNamespace();
	size_t count = nspace->getItemCount();
	for (size_t i = 0; i < count; i++) {
		jnc::ModuleItem *child = nspace->getItem(i);
		addItem(treeItem, child);
	}

	expandItem(treeItem);
}

void ModulePane::addItem(QTreeWidgetItem *parent, jnc::ModuleItem *item)
{
	jnc::ModuleItemKind itemKind = item->getItemKind();

	QString name;
	QTreeWidgetItem* treeItem;

	switch (itemKind)
	{
	case jnc::ModuleItemKind_Namespace:
		addNamespace(parent, (jnc::GlobalNamespace*)item);
		break;

	case jnc::ModuleItemKind_Type:
		addType(parent, (jnc::Type*)item);
		break;

	case jnc::ModuleItemKind_Typedef:
		addTypedef(parent, (jnc::Typedef*)item);
		break;

	case jnc::ModuleItemKind_Variable:
		addVariable(parent, (jnc::Variable*)item);
		break;

	case jnc::ModuleItemKind_Function:
		addFunction(parent, (jnc::Function*)item);
		break;

	case jnc::ModuleItemKind_Property:
		addProperty(parent, (jnc::Property*)item);
		break;

	case jnc::ModuleItemKind_EnumConst:
		addEnumConst(parent, (jnc::EnumConst*)item);
		break;

	case jnc::ModuleItemKind_Field:
		addField(parent, (jnc::Field*)item);
		break;

	case jnc::ModuleItemKind_Alias:
		addAlias(parent, (jnc::Alias*)item);
		break;

	default:
		name.sprintf("item %p of kind %d", item, itemKind);

		treeItem = insertItem(name, parent);
		treeItem->setText(0, name);
	}
}

void ModulePane::addType(QTreeWidgetItem *parent, jnc::Type *type)
{
	QString itemName = (const char*)type->getTypeString();

	QTreeWidgetItem *item = insertItem(itemName, parent);

	if (type->getFlags() & jnc::ModuleItemFlag_LayoutReady)
	{
		QString toolTip = QString("%1 (sizeof = %2)").arg (type->getTypeString()).arg (type->getSize ());
		item->setToolTip(0, toolTip);
	}

	jnc::ModuleItemDecl* decl = NULL;
	jnc::TypeKind typeKind = type->getTypeKind();
	switch (typeKind)
	{
	case jnc::TypeKind_Enum:
		decl = ((jnc::EnumType *)type)->getDecl();
		addItemAttributes(item, decl);
		addEnumTypeMembers(item, (jnc::EnumType *)type);
		break;

	case jnc::TypeKind_Struct:
	case jnc::TypeKind_Union:
	case jnc::TypeKind_Class:
		decl = ((jnc::DerivableType *)type)->getDecl();
		addItemAttributes(item, decl);
		addDerivableTypeMembers(item, (jnc::DerivableType *)type);
		break;
	}

	item->setData(0, Qt::UserRole, qVariantFromValue((void*)decl));
}

void ModulePane::addTypedef(QTreeWidgetItem *parent, jnc::Typedef* tdef)
{
	QString name;
	name.sprintf("typedef %s %s %s",
		tdef->getType()->getTypeStringPrefix(),
		tdef->getDecl()->getName(),
		tdef->getType()->getTypeStringSuffix()
		);

	QTreeWidgetItem *item = insertItem(name, parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)tdef->getDecl()));
}

void ModulePane::addVariable(QTreeWidgetItem *parent, jnc::Variable *variable)
{
	addValue(parent, variable->getDecl()->getName(), variable->getType(), variable);
}

void ModulePane::addEnumConst(QTreeWidgetItem *parent, jnc::EnumConst *member)
{
	QTreeWidgetItem *item = insertItem((const char*) member->getDecl()->getName(), parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)member->getDecl()));
}

void ModulePane::addValue(QTreeWidgetItem *parent, const QString& name, jnc::Type* type, jnc::ModuleItem* moduleItem)
{
	QString itemName = QString("%1 %2 %3").arg (type->getTypeStringPrefix ()).arg (name).arg (type->getTypeStringSuffix ());
	QTreeWidgetItem *item = insertItem(itemName, parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)moduleItem->getDecl()));

	if (jnc::isClassType(type, jnc::ClassTypeKind_Reactor))
		addDerivableTypeMembers(item, (jnc::ClassType*)type);
}

void ModulePane::addEnumTypeMembers(QTreeWidgetItem *parent, jnc::EnumType* type)
{
	size_t count = type->getConstCount();
	for (size_t i = 0; i < count; i++)
	{
		jnc::EnumConst* member = type->getConst(i);
		addEnumConst(parent, member);
	}

	expandItem(parent);
}

void ModulePane::addDerivableTypeMembers(QTreeWidgetItem *parent, jnc::DerivableType *type)
{
	size_t count = type->getStaticVariableCount();
	for (size_t i = 0; i < count; i++)
		addVariable(parent, type->getStaticVariable(i));

	count = type->getFieldCount();
	for (size_t i = 0; i < count; i++)
		addField(parent, type->getField(i));

	if (type->getStaticConstructor())
		addItem(parent, type->getStaticConstructor());

	if (type->getConstructor())
		addOverloadableFunction(parent, type->getConstructor());

	if (type->getDestructor())
		addItem(parent, type->getDestructor());

	count = type->getPropertyCount();
	for (size_t i = 0; i < count; i++)
		addProperty(parent, type->getProperty(i));

	count = type->getMethodCount();
	for (size_t i = 0; i < count; i++)
		addFunction(parent, type->getMethod(i));

	expandItem(parent);
}

void ModulePane::addFunction(QTreeWidgetItem *parent, jnc::Function* function)
{
	jnc::FunctionType* type = function->getType();

	const char* name = function->getFunctionKind() == jnc::FunctionKind_Normal ?
		function->getDecl()->getName() :
		jnc::getFunctionKindString(function->getFunctionKind());

	QString itemName = QString("%1 %2%3").arg(type->getTypeStringPrefix(), name, type->getTypeStringSuffix());
	QTreeWidgetItem *item = insertItem(itemName, parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)function->getDecl()));
}

void ModulePane::addFunctionOverload(QTreeWidgetItem *parent, jnc::FunctionOverload* overload)
{
	size_t count = overload->getOverloadCount();

	const char* name = overload->getFunctionKind() == jnc::FunctionKind_Normal ?
		overload->getDecl()->getName() :
		jnc::getFunctionKindString(overload->getFunctionKind());

	QString itemName = QString("%1 (%2 overloads)").arg(name).arg(count);

	QTreeWidgetItem *item = insertItem(itemName, parent);
	for (size_t i = 0; i < count; i++)
	{
		jnc::Function* function = overload->getOverload(i);
		addFunction(item, function);
	}

	expandItem(item);
}

void ModulePane::addOverloadableFunction(QTreeWidgetItem* parent, jnc::OverloadableFunction function)
{
	function->getItemKind() == jnc::ModuleItemKind_Function ?
		addFunction(parent, function.getFunction()) :
		addFunctionOverload(parent, function.getFunctionOverload());
}

void ModulePane::addProperty(QTreeWidgetItem *parent, jnc::Property* prop)
{
	QTreeWidgetItem *item = insertItem(prop->getDecl()->getName(), parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)prop->getDecl()));

	jnc::Function* getter = prop->getGetter();
	addFunction(item, getter);

	jnc::OverloadableFunction setter = prop->getSetter();
	if (setter)
		addOverloadableFunction(item, setter);

	expandItem(item);
}

void ModulePane::addAlias(QTreeWidgetItem* parent, jnc::Alias* alias)
{
	QString name;
	name.sprintf(
		"alias %s = %s",
		alias->getDecl()->getName(),
		alias->getInitializerString_v()
		);

	QTreeWidgetItem *item = insertItem(name, parent);
	item->setData(0, Qt::UserRole, qVariantFromValue((void*)alias->getDecl()));
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include "rtc_base/experiments/field_trial_parser.h"

#include <inttypes.h>

#include <algorithm>
#include <map>
#include <type_traits>
#include <utility>

#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"

namespace webrtc {
namespace {

int FindOrEnd(std::string str, size_t start, char delimiter) {
  size_t pos = str.find(delimiter, start);
  pos = (pos == std::string::npos) ? str.length() : pos;
  return static_cast<int>(pos);
}
}  // namespace

FieldTrialParameterInterface::FieldTrialParameterInterface(std::string key)
    : key_(key) {}
FieldTrialParameterInterface::~FieldTrialParameterInterface() {
  RTC_DCHECK(used_) << "Field trial parameter with key: '" << key_
                    << "' never used.";
}

void ParseFieldTrial(
    std::initializer_list<FieldTrialParameterInterface*> fields,
    std::string trial_string) {
  std::map<std::string, FieldTrialParameterInterface*> field_map;
  FieldTrialParameterInterface* keyless_field = nullptr;
  for (FieldTrialParameterInterface* field : fields) {
    field->MarkAsUsed();
    if (!field->sub_parameters_.empty()) {
      for (FieldTrialParameterInterface* sub_field : field->sub_parameters_) {
        RTC_DCHECK(!sub_field->key_.empty());
        sub_field->MarkAsUsed();
        field_map[sub_field->key_] = sub_field;
      }
      continue;
    }

    if (field->key_.empty()) {
      RTC_DCHECK(!keyless_field);
      keyless_field = field;
    } else {
      field_map[field->key_] = field;
    }
  }

  size_t i = 0;
  while (i < trial_string.length()) {
    int val_end = FindOrEnd(trial_string, i, ',');
    int colon_pos = FindOrEnd(trial_string, i, ':');
    int key_end = std::min(val_end, colon_pos);
    int val_begin = key_end + 1;
    std::string key = trial_string.substr(i, key_end - i);
    absl::optional<std::string> opt_value;
    if (val_end >= val_begin)
      opt_value = trial_string.substr(val_begin, val_end - val_begin);
    i = val_end + 1;
    auto field = field_map.find(key);
    if (field != field_map.end()) {
      if (!field->second->Parse(std::move(opt_value))) {
        RTC_LOG(LS_WARNING) << "Failed to read field with key: '" << key
                            << "' in trial: \"" << trial_string << "\"";
      }
    } else if (!opt_value && keyless_field && !key.empty()) {
      if (!keyless_field->Parse(key)) {
        RTC_LOG(LS_WARNING) << "Failed to read empty key field with value '"
                            << key << "' in trial: \"" << trial_string << "\"";
      }
    } else {
      RTC_LOG(LS_INFO) << "No field with key: '" << key
                       << "' (found in trial: \"" << trial_string << "\")";
    }
  }

  for (FieldTrialParameterInterface* field : fields) {
    field->ParseDone();
  }
}

template <>
absl::optional<bool> ParseTypedParameter<bool>(std::string str) {
  if (str == "true" || str == "1") {
    return true;
  } else if (str == "false" || str == "0") {
    return false;
  }
  return absl::nullopt;
}

template <>
absl::optional<double> ParseTypedParameter<double>(std::string str) {
  double value;
  char unit[2]{0, 0};
  if (sscanf(str.c_str(), "%lf%1s", &value, unit) >= 1) {
    if (unit[0] == '%')
      return value / 100;
    return value;
  } else {
    return absl::nullopt;
  }
}

template <>
absl::optional<int> ParseTypedParameter<int>(std::string str) {
  int64_t value;
  if (sscanf(str.c_str(), "%" SCNd64, &value) == 1) {
    if (rtc::IsValueInRangeForNumericType<int, int64_t>(value)) {
      return static_cast<int>(value);
    }
  }
  return absl::nullopt;
}

template <>
absl::optional<unsigned> ParseTypedParameter<unsigned>(std::string str) {
  int64_t value;
  if (sscanf(str.c_str(), "%" SCNd64, &value) == 1) {
    if (rtc::IsValueInRangeForNumericType<unsigned, int64_t>(value)) {
      return static_cast<unsigned>(value);
    }
  }
  return absl::nullopt;
}

template <>
absl::optional<std::string> ParseTypedParameter<std::string>(std::string str) {
  return std::move(str);
}

template <>
absl::optional<absl::optional<bool>> ParseTypedParameter<absl::optional<bool>>(
    std::string str) {
  return ParseOptionalParameter<bool>(str);
}
template <>
absl::optional<absl::optional<int>> ParseTypedParameter<absl::optional<int>>(
    std::string str) {
  return ParseOptionalParameter<int>(str);
}
template <>
absl::optional<absl::optional<unsigned>>
ParseTypedParameter<absl::optional<unsigned>>(std::string str) {
  return ParseOptionalParameter<unsigned>(str);
}
template <>
absl::optional<absl::optional<double>>
ParseTypedParameter<absl::optional<double>>(std::string str) {
  return ParseOptionalParameter<double>(str);
}

FieldTrialFlag::FieldTrialFlag(std::string key) : FieldTrialFlag(key, false) {}

FieldTrialFlag::FieldTrialFlag(std::string key, bool default_value)
    : FieldTrialParameterInterface(key), value_(default_value) {}

bool FieldTrialFlag::Get() const {
  return value_;
}

webrtc::FieldTrialFlag::operator bool() const {
  return value_;
}

bool FieldTrialFlag::Parse(absl::optional<std::string> str_value) {
  // Only set the flag if there is no argument provided.
  if (str_value) {
    absl::optional<bool> opt_value = ParseTypedParameter<bool>(*str_value);
    if (!opt_value)
      return false;
    value_ = *opt_value;
  } else {
    value_ = true;
  }
  return true;
}

AbstractFieldTrialEnum::AbstractFieldTrialEnum(
    std::string key,
    int default_value,
    std::map<std::string, int> mapping)
    : FieldTrialParameterInterface(key),
      value_(default_value),
      enum_mapping_(mapping) {
  for (auto& key_val : enum_mapping_)
    valid_values_.insert(key_val.second);
}
AbstractFieldTrialEnum::AbstractFieldTrialEnum(const AbstractFieldTrialEnum&) =
    default;
AbstractFieldTrialEnum::~AbstractFieldTrialEnum() = default;

bool AbstractFieldTrialEnum::Parse(absl::optional<std::string> str_value) {
  if (str_value) {
    auto it = enum_mapping_.find(*str_value);
    if (it != enum_mapping_.end()) {
      value_ = it->second;
      return true;
    }
    absl::optional<int> value = ParseTypedParameter<int>(*str_value);
    if (value.has_value() &&
        (valid_values_.find(*value) != valid_values_.end())) {
      value_ = *value;
      return true;
    }
  }
  return false;
}

template class FieldTrialParameter<bool>;
template class FieldTrialParameter<double>;
template class FieldTrialParameter<int>;
template class FieldTrialParameter<unsigned>;
template class FieldTrialParameter<std::string>;

template class FieldTrialConstrained<double>;
template class FieldTrialConstrained<int>;
template class FieldTrialConstrained<unsigned>;

template class FieldTrialOptional<double>;
template class FieldTrialOptional<int>;
template class FieldTrialOptional<unsigned>;
template class FieldTrialOptional<bool>;
template class FieldTrialOptional<std::string>;

}  // namespace webrtc
<commit_msg>Improve field trial error message.<commit_after>/*
 *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include "rtc_base/experiments/field_trial_parser.h"

#include <inttypes.h>

#include <algorithm>
#include <map>
#include <type_traits>
#include <utility>

#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"

namespace webrtc {
namespace {

int FindOrEnd(std::string str, size_t start, char delimiter) {
  size_t pos = str.find(delimiter, start);
  pos = (pos == std::string::npos) ? str.length() : pos;
  return static_cast<int>(pos);
}
}  // namespace

FieldTrialParameterInterface::FieldTrialParameterInterface(std::string key)
    : key_(key) {}
FieldTrialParameterInterface::~FieldTrialParameterInterface() {
  RTC_DCHECK(used_) << "Field trial parameter with key: '" << key_
                    << "' never used.";
}

void ParseFieldTrial(
    std::initializer_list<FieldTrialParameterInterface*> fields,
    std::string trial_string) {
  std::map<std::string, FieldTrialParameterInterface*> field_map;
  FieldTrialParameterInterface* keyless_field = nullptr;
  for (FieldTrialParameterInterface* field : fields) {
    field->MarkAsUsed();
    if (!field->sub_parameters_.empty()) {
      for (FieldTrialParameterInterface* sub_field : field->sub_parameters_) {
        RTC_DCHECK(!sub_field->key_.empty());
        sub_field->MarkAsUsed();
        field_map[sub_field->key_] = sub_field;
      }
      continue;
    }

    if (field->key_.empty()) {
      RTC_DCHECK(!keyless_field);
      keyless_field = field;
    } else {
      field_map[field->key_] = field;
    }
  }

  size_t i = 0;
  while (i < trial_string.length()) {
    int val_end = FindOrEnd(trial_string, i, ',');
    int colon_pos = FindOrEnd(trial_string, i, ':');
    int key_end = std::min(val_end, colon_pos);
    int val_begin = key_end + 1;
    std::string key = trial_string.substr(i, key_end - i);
    absl::optional<std::string> opt_value;
    if (val_end >= val_begin)
      opt_value = trial_string.substr(val_begin, val_end - val_begin);
    i = val_end + 1;
    auto field = field_map.find(key);
    if (field != field_map.end()) {
      if (!field->second->Parse(std::move(opt_value))) {
        RTC_LOG(LS_WARNING) << "Failed to read field with key: '" << key
                            << "' in trial: \"" << trial_string << "\"";
      }
    } else if (!opt_value && keyless_field && !key.empty()) {
      if (!keyless_field->Parse(key)) {
        RTC_LOG(LS_WARNING) << "Failed to read empty key field with value '"
                            << key << "' in trial: \"" << trial_string << "\"";
      }
    } else {
      RTC_LOG(LS_INFO) << "No field with key: '" << key
                       << "' (found in trial: \"" << trial_string << "\")";
      std::string valid_keys;
      for (const auto& f : field_map) {
        valid_keys += f.first;
        valid_keys += ", ";
      }
      RTC_LOG(LS_INFO) << "Valid keys are: " << valid_keys;
    }
  }

  for (FieldTrialParameterInterface* field : fields) {
    field->ParseDone();
  }
}

template <>
absl::optional<bool> ParseTypedParameter<bool>(std::string str) {
  if (str == "true" || str == "1") {
    return true;
  } else if (str == "false" || str == "0") {
    return false;
  }
  return absl::nullopt;
}

template <>
absl::optional<double> ParseTypedParameter<double>(std::string str) {
  double value;
  char unit[2]{0, 0};
  if (sscanf(str.c_str(), "%lf%1s", &value, unit) >= 1) {
    if (unit[0] == '%')
      return value / 100;
    return value;
  } else {
    return absl::nullopt;
  }
}

template <>
absl::optional<int> ParseTypedParameter<int>(std::string str) {
  int64_t value;
  if (sscanf(str.c_str(), "%" SCNd64, &value) == 1) {
    if (rtc::IsValueInRangeForNumericType<int, int64_t>(value)) {
      return static_cast<int>(value);
    }
  }
  return absl::nullopt;
}

template <>
absl::optional<unsigned> ParseTypedParameter<unsigned>(std::string str) {
  int64_t value;
  if (sscanf(str.c_str(), "%" SCNd64, &value) == 1) {
    if (rtc::IsValueInRangeForNumericType<unsigned, int64_t>(value)) {
      return static_cast<unsigned>(value);
    }
  }
  return absl::nullopt;
}

template <>
absl::optional<std::string> ParseTypedParameter<std::string>(std::string str) {
  return std::move(str);
}

template <>
absl::optional<absl::optional<bool>> ParseTypedParameter<absl::optional<bool>>(
    std::string str) {
  return ParseOptionalParameter<bool>(str);
}
template <>
absl::optional<absl::optional<int>> ParseTypedParameter<absl::optional<int>>(
    std::string str) {
  return ParseOptionalParameter<int>(str);
}
template <>
absl::optional<absl::optional<unsigned>>
ParseTypedParameter<absl::optional<unsigned>>(std::string str) {
  return ParseOptionalParameter<unsigned>(str);
}
template <>
absl::optional<absl::optional<double>>
ParseTypedParameter<absl::optional<double>>(std::string str) {
  return ParseOptionalParameter<double>(str);
}

FieldTrialFlag::FieldTrialFlag(std::string key) : FieldTrialFlag(key, false) {}

FieldTrialFlag::FieldTrialFlag(std::string key, bool default_value)
    : FieldTrialParameterInterface(key), value_(default_value) {}

bool FieldTrialFlag::Get() const {
  return value_;
}

webrtc::FieldTrialFlag::operator bool() const {
  return value_;
}

bool FieldTrialFlag::Parse(absl::optional<std::string> str_value) {
  // Only set the flag if there is no argument provided.
  if (str_value) {
    absl::optional<bool> opt_value = ParseTypedParameter<bool>(*str_value);
    if (!opt_value)
      return false;
    value_ = *opt_value;
  } else {
    value_ = true;
  }
  return true;
}

AbstractFieldTrialEnum::AbstractFieldTrialEnum(
    std::string key,
    int default_value,
    std::map<std::string, int> mapping)
    : FieldTrialParameterInterface(key),
      value_(default_value),
      enum_mapping_(mapping) {
  for (auto& key_val : enum_mapping_)
    valid_values_.insert(key_val.second);
}
AbstractFieldTrialEnum::AbstractFieldTrialEnum(const AbstractFieldTrialEnum&) =
    default;
AbstractFieldTrialEnum::~AbstractFieldTrialEnum() = default;

bool AbstractFieldTrialEnum::Parse(absl::optional<std::string> str_value) {
  if (str_value) {
    auto it = enum_mapping_.find(*str_value);
    if (it != enum_mapping_.end()) {
      value_ = it->second;
      return true;
    }
    absl::optional<int> value = ParseTypedParameter<int>(*str_value);
    if (value.has_value() &&
        (valid_values_.find(*value) != valid_values_.end())) {
      value_ = *value;
      return true;
    }
  }
  return false;
}

template class FieldTrialParameter<bool>;
template class FieldTrialParameter<double>;
template class FieldTrialParameter<int>;
template class FieldTrialParameter<unsigned>;
template class FieldTrialParameter<std::string>;

template class FieldTrialConstrained<double>;
template class FieldTrialConstrained<int>;
template class FieldTrialConstrained<unsigned>;

template class FieldTrialOptional<double>;
template class FieldTrialOptional<int>;
template class FieldTrialOptional<unsigned>;
template class FieldTrialOptional<bool>;
template class FieldTrialOptional<std::string>;

}  // namespace webrtc
<|endoftext|>


<commit_before>/*************************************************************************/
/*  dictionary.cpp                                                       */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "dictionary.h"

#include "ordered_hash_map.h"
#include "safe_refcount.h"
#include "variant.h"

struct _DictionaryVariantHash {

	static _FORCE_INLINE_ uint32_t hash(const Variant &p_variant) { return p_variant.hash(); }
};

struct DictionaryPrivate {

	SafeRefCount refcount;
	OrderedHashMap<Variant, Variant, _DictionaryVariantHash> variant_map;
};

void Dictionary::get_key_list(List<Variant> *p_keys) const {

	if (_p->variant_map.empty())
		return;

	for (OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::Element E = _p->variant_map.front(); E; E = E.next()) {
		p_keys->push_back(E.key());
	}
}

Variant &Dictionary::operator[](const Variant &p_key) {

	return _p->variant_map[p_key];
}

const Variant &Dictionary::operator[](const Variant &p_key) const {

	return _p->variant_map[p_key];
}
const Variant *Dictionary::getptr(const Variant &p_key) const {

	OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::ConstElement E = ((const OrderedHashMap<Variant, Variant, _DictionaryVariantHash> *)&_p->variant_map)->find(p_key);

	if (!E)
		return NULL;
	return &E.get();
}

Variant *Dictionary::getptr(const Variant &p_key) {

	OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::Element E = _p->variant_map.find(p_key);

	if (!E)
		return NULL;
	return &E.get();
}

Variant Dictionary::get_valid(const Variant &p_key) const {

	OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::ConstElement E = ((const OrderedHashMap<Variant, Variant, _DictionaryVariantHash> *)&_p->variant_map)->find(p_key);

	if (!E)
		return Variant();
	return E.get();
}

int Dictionary::size() const {

	return _p->variant_map.size();
}
bool Dictionary::empty() const {

	return !_p->variant_map.size();
}

bool Dictionary::has(const Variant &p_key) const {

	return _p->variant_map.has(p_key);
}

bool Dictionary::has_all(const Array &p_keys) const {
	for (int i = 0; i < p_keys.size(); i++) {
		if (!has(p_keys[i])) {
			return false;
		}
	}
	return true;
}

void Dictionary::erase(const Variant &p_key) {

	_p->variant_map.erase(p_key);
}

bool Dictionary::operator==(const Dictionary &p_dictionary) const {

	return _p == p_dictionary._p;
}

void Dictionary::_ref(const Dictionary &p_from) const {

	//make a copy first (thread safe)
	if (!p_from._p->refcount.ref())
		return; // couldn't copy

	//if this is the same, unreference the other one
	if (p_from._p == _p) {
		_p->refcount.unref();
		return;
	}
	if (_p)
		_unref();
	_p = p_from._p;
}

void Dictionary::clear() {

	_p->variant_map.clear();
}

void Dictionary::_unref() const {

	ERR_FAIL_COND(!_p);
	if (_p->refcount.unref()) {
		memdelete(_p);
	}
	_p = NULL;
}
uint32_t Dictionary::hash() const {

	uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);

	List<Variant> keys;
	get_key_list(&keys);

	for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {

		h = hash_djb2_one_32(E->get().hash(), h);
		h = hash_djb2_one_32(operator[](E->get()).hash(), h);
	}

	return h;
}

Array Dictionary::keys() const {

	Array varr;
	varr.resize(size());
	if (_p->variant_map.empty())
		return varr;

	int i = 0;
	for (OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::Element E = _p->variant_map.front(); E; E = E.next()) {
		varr[i] = E.key();
		i++;
	}

	return varr;
}

Array Dictionary::values() const {

	Array varr;
	varr.resize(size());
	if (_p->variant_map.empty())
		return varr;

	int i = 0;
	for (OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::Element E = _p->variant_map.front(); E; E = E.next()) {
		varr[i] = E.get();
		i++;
	}

	return varr;
}

const Variant *Dictionary::next(const Variant *p_key) const {

	if (p_key == NULL) {
		// caller wants to get the first element
		if (_p->variant_map.front())
			return &_p->variant_map.front().key();
		return NULL;
	}
	OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::Element E = _p->variant_map.find(*p_key);

	if (E && E.next())
		return &E.next().key();
	return NULL;
}

Dictionary Dictionary::duplicate() const {

	Dictionary n;

	List<Variant> keys;
	get_key_list(&keys);

	for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
		n[E->get()] = operator[](E->get());
	}

	return n;
}

void Dictionary::operator=(const Dictionary &p_dictionary) {

	_ref(p_dictionary);
}

Dictionary::Dictionary(const Dictionary &p_from) {
	_p = NULL;
	_ref(p_from);
}

Dictionary::Dictionary() {

	_p = memnew(DictionaryPrivate);
	_p->refcount.init();
}
Dictionary::~Dictionary() {

	_unref();
}
<commit_msg>Use the appropriate Variant hash and compare functions for Dictionaries<commit_after>/*************************************************************************/
/*  dictionary.cpp                                                       */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "dictionary.h"

#include "ordered_hash_map.h"
#include "safe_refcount.h"
#include "variant.h"

struct DictionaryPrivate {

	SafeRefCount refcount;
	OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map;
};

void Dictionary::get_key_list(List<Variant> *p_keys) const {

	if (_p->variant_map.empty())
		return;

	for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
		p_keys->push_back(E.key());
	}
}

Variant &Dictionary::operator[](const Variant &p_key) {

	return _p->variant_map[p_key];
}

const Variant &Dictionary::operator[](const Variant &p_key) const {

	return _p->variant_map[p_key];
}
const Variant *Dictionary::getptr(const Variant &p_key) const {

	OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);

	if (!E)
		return NULL;
	return &E.get();
}

Variant *Dictionary::getptr(const Variant &p_key) {

	OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(p_key);

	if (!E)
		return NULL;
	return &E.get();
}

Variant Dictionary::get_valid(const Variant &p_key) const {

	OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);

	if (!E)
		return Variant();
	return E.get();
}

int Dictionary::size() const {

	return _p->variant_map.size();
}
bool Dictionary::empty() const {

	return !_p->variant_map.size();
}

bool Dictionary::has(const Variant &p_key) const {

	return _p->variant_map.has(p_key);
}

bool Dictionary::has_all(const Array &p_keys) const {
	for (int i = 0; i < p_keys.size(); i++) {
		if (!has(p_keys[i])) {
			return false;
		}
	}
	return true;
}

void Dictionary::erase(const Variant &p_key) {

	_p->variant_map.erase(p_key);
}

bool Dictionary::operator==(const Dictionary &p_dictionary) const {

	return _p == p_dictionary._p;
}

void Dictionary::_ref(const Dictionary &p_from) const {

	//make a copy first (thread safe)
	if (!p_from._p->refcount.ref())
		return; // couldn't copy

	//if this is the same, unreference the other one
	if (p_from._p == _p) {
		_p->refcount.unref();
		return;
	}
	if (_p)
		_unref();
	_p = p_from._p;
}

void Dictionary::clear() {

	_p->variant_map.clear();
}

void Dictionary::_unref() const {

	ERR_FAIL_COND(!_p);
	if (_p->refcount.unref()) {
		memdelete(_p);
	}
	_p = NULL;
}
uint32_t Dictionary::hash() const {

	uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);

	List<Variant> keys;
	get_key_list(&keys);

	for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {

		h = hash_djb2_one_32(E->get().hash(), h);
		h = hash_djb2_one_32(operator[](E->get()).hash(), h);
	}

	return h;
}

Array Dictionary::keys() const {

	Array varr;
	varr.resize(size());
	if (_p->variant_map.empty())
		return varr;

	int i = 0;
	for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
		varr[i] = E.key();
		i++;
	}

	return varr;
}

Array Dictionary::values() const {

	Array varr;
	varr.resize(size());
	if (_p->variant_map.empty())
		return varr;

	int i = 0;
	for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
		varr[i] = E.get();
		i++;
	}

	return varr;
}

const Variant *Dictionary::next(const Variant *p_key) const {

	if (p_key == NULL) {
		// caller wants to get the first element
		if (_p->variant_map.front())
			return &_p->variant_map.front().key();
		return NULL;
	}
	OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(*p_key);

	if (E && E.next())
		return &E.next().key();
	return NULL;
}

Dictionary Dictionary::duplicate() const {

	Dictionary n;

	List<Variant> keys;
	get_key_list(&keys);

	for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
		n[E->get()] = operator[](E->get());
	}

	return n;
}

void Dictionary::operator=(const Dictionary &p_dictionary) {

	_ref(p_dictionary);
}

Dictionary::Dictionary(const Dictionary &p_from) {
	_p = NULL;
	_ref(p_from);
}

Dictionary::Dictionary() {

	_p = memnew(DictionaryPrivate);
	_p->refcount.init();
}
Dictionary::~Dictionary() {

	_unref();
}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//_________________________________________________________________________//
//                                                                         //
//  TOF sdigit: member variables                                           //
//  fSector  : TOF sector                                                  //
//  fPlate   : TOF plate                                                   //
//  fStrip   : strips number                                               //
//  fPadx    : pad number along x                                          //
//  fPadz    : pad number along z                                          //
//  fTdc     : TArrayI of TDC values                                       //
//  fAdc     : TArrayI of ADC values                                       //
//                                                                         //
//  Getters, setters and member functions  defined here                    //
//                                                                         //
// -- Authors: F. Pierella, A. Seganti, D. Vicinanza                       //
//_________________________________________________________________________//

#include "AliTOFGeometry.h"
#include "AliTOFSDigit.h"

ClassImp(AliTOFSDigit)

////////////////////////////////////////////////////////////////////////
AliTOFSDigit::AliTOFSDigit():
  fSector(-1),
  fPlate(-1),
  fStrip(-1),
  fPadx(-1),
  fPadz(-1),
  fNDigits(0),
  fTdc(0x0),
  fAdc(0x0),
  fTracks(0x0)
{
  //
  // default ctor
  //
}

////////////////////////////////////////////////////////////////////////
AliTOFSDigit::AliTOFSDigit(Int_t tracknum, Int_t * const vol,Int_t * const digit):
  TObject(),
  fSector(-1),
  fPlate(-1),
  fStrip(-1),
  fPadx(-1),
  fPadz(-1),
  fNDigits(0),
  fTdc(0x0),
  fAdc(0x0),
  fTracks(0x0)
{
  //
  // Constructor of digit object
  //

  fSector = vol[0];
  fPlate  = vol[1];
  fStrip  = vol[2];
  fPadx   = vol[3];
  fPadz   = vol[4];
  fNDigits = 1;
  fTdc = new TArrayI(fNDigits);
  (*fTdc)[0] = digit[0];
  fAdc = new TArrayI(fNDigits);
  (*fAdc)[0] = digit[1];
  fTracks = new TArrayI(kMAXDIGITS*fNDigits);
  (*fTracks)[0] = tracknum;
  for (Int_t i = 1; i <kMAXDIGITS*fNDigits; i++) {
    (*fTracks)[i] = -1;
  }
}

////////////////////////////////////////////////////////////////////////
AliTOFSDigit::AliTOFSDigit(const AliTOFSDigit & digit):
  TObject(digit),
  fSector(digit.fSector),
  fPlate(digit.fPlate),
  fStrip(digit.fStrip),
  fPadx(digit.fPadx),
  fPadz(digit.fPadz),
  fNDigits(digit.fNDigits),
  fTdc(0x0),
  fAdc(0x0),
  fTracks(0x0)
{
  //
  // copy ctor for AliTOFSDigit object
  //
  fTdc = new TArrayI(*digit.fTdc);
  fAdc = new TArrayI(*digit.fAdc);
  fTracks = new TArrayI(*digit.fTracks);
}

////////////////////////////////////////////////////////////////////////
AliTOFSDigit& AliTOFSDigit::operator=(const AliTOFSDigit & digit)
{
  //
  // copy ctor for AliTOFSDigit object
  //

  if (this == &digit)
    return *this;

  TObject::operator=(digit);
  fSector = digit.fSector;
  fPlate  = digit.fPlate;
  fStrip  = digit.fStrip;
  fPadx   = digit.fPadx;
  fPadz   = digit.fPadz;
  fNDigits = digit.fNDigits;
  fTdc = digit.fTdc;
  fAdc = digit.fAdc;
  fTracks = digit.fTracks;
  return *this;

}

////////////////////////////////////////////////////////////////////////
AliTOFSDigit::AliTOFSDigit(Int_t sector, Int_t plate, Int_t strip, Int_t padx,
			   Int_t padz, Int_t tdc, Int_t adc):
  fSector(sector),
  fPlate(plate),
  fStrip(strip),
  fPadx(padx),
  fPadz(padz),
  fNDigits(1),
  fTdc(0x0),
  fAdc(0x0),
  fTracks(0x0)
{
  //
  // Constructor for sdigit
  //
  fTdc = new TArrayI(fNDigits);
  (*fTdc)[0] = tdc;
  fAdc = new TArrayI(fNDigits);
  (*fAdc)[0] = adc;
  // no tracks were specified, set them to -1
  fTracks = new TArrayI(kMAXDIGITS*fNDigits);
  for (Int_t i = 0; i <kMAXDIGITS*fNDigits; i++) {
    (*fTracks)[i] = -1;
  }
}

////////////////////////////////////////////////////////////////////////
void AliTOFSDigit::GetLocation(Int_t *Loc) const
{
  //
  // Get the coordinates of the digit
  // in terms of Sector - Plate - Strip - Pad
  //

  Loc[0]=fSector;
  Loc[1]=fPlate;
  Loc[2]=fStrip;
  Loc[3]=fPadx;
  Loc[4]=fPadz;
}

////////////////////////////////////////////////////////////////////////
void AliTOFSDigit::Update(Float_t tdcbin, Int_t tdc, Int_t adc, Int_t track)
{
  //
  // Add charge and track
  //

  Int_t sameTime = -1;
  Float_t tdcwindow = AliTOFGeometry::DeadTime()/tdcbin;
  for (Int_t i = 0; i < fNDigits; i++) {
    if (TMath::Abs(tdc-fTdc->At(i)) < tdcwindow) {
      sameTime = i;
      break;
    }
  }

  if (sameTime >= 0) { // another time measurement happens during the
		       // dead time of the hit pad => it corresponds
		       // to the same time measurement
    (*fAdc)[sameTime] += adc;

    // update track index array in case the current digit track index
    // is different from -1
    if (track!=-1) {

      //Find the first -1 value of the track index array and replace
      //it by the current digit track index
      for (Int_t iTrack=0; iTrack<kMAXDIGITS; iTrack++) {
	if (track==(*fTracks)[sameTime*kMAXDIGITS+iTrack]) break;
	if ((*fTracks)[sameTime*kMAXDIGITS+iTrack] == -1) {
	  (*fTracks)[sameTime*kMAXDIGITS+iTrack] = track;
	  break;
	}
	// write warning about many tracks going to this pad
	if (iTrack == kMAXDIGITS-1) {
	  printf("W-AliTOFSDigit::Update: Many different tracks in the same TOF pad (%2d %1d %2d %1d %2d)\n",
		 fSector,fPlate,fStrip,fPadz,fPadx);
	  //ToAliWarning(PrintPad());
	}
      }
    }

  } else { // they are two different time measurements

    // add new time slot
    fNDigits++;
    fTdc->Set(fNDigits);
    (*fTdc)[fNDigits-1] = tdc;
    fAdc->Set(fNDigits);
    (*fAdc)[fNDigits-1] = adc;
    fTracks->Set(fNDigits*kMAXDIGITS);
    (*fTracks)[(fNDigits-1)*kMAXDIGITS] = track;
    for (Int_t i = 1; i <kMAXDIGITS; i++)
      (*fTracks)[(fNDigits-1)*kMAXDIGITS+i] = -1;

  }

}

////////////////////////////////////////////////////////////////////////
void AliTOFSDigit::Update(AliTOFSDigit * const sdig)
{

  //
  // Perform the sum with sdig
  //

  Float_t tdcbin = AliTOFGeometry::TdcBinWidth();// [ps] hardwired for the time being

  Int_t track = -1;
  Int_t adc = -1;
  Int_t tdc = -1;

  // start loop on all sdig locations
  Int_t nlocations = sdig->GetNDigits();
  for (Int_t j = 0; j < nlocations; j++) {
    tdc = (Int_t)sdig->GetTdc(j);
    adc = (Int_t)sdig->GetAdc(j);

    // getting here only the first track number
    //Int_t track = GetTrack(j,0);

    // getting here all the track numbers
    for (Int_t iTrack = 0; iTrack<kMAXDIGITS; iTrack++) {
      track = sdig->GetTrack(j,iTrack);
      Update(tdcbin, tdc, adc, track);
    } // end loop on tracks

  } // end loop on sdig locations

}

////////////////////////////////////////////////////////////////////////
AliTOFSDigit::~AliTOFSDigit()
{
  //
  // dtor
  //
  delete fTdc;
  delete fAdc;
  delete fTracks;
}

////////////////////////////////////////////////////////////////////////

Int_t AliTOFSDigit::GetTotPad() const
{
  //
  // Get the "total" index of the pad inside a Sector
  // starting from the digits data.
  //

  Int_t pad = AliTOFGeometry::NpadZ()*fPadx + fPadz;
  Int_t before=0;

  switch(fPlate){
  case 0:
    //before = 0;
    break;
  case 1:
    before = AliTOFGeometry::NStripC();
    break;
  case 2:
    before = AliTOFGeometry::NStripB() +   AliTOFGeometry::NStripC();
    break;
  case 3:
    before = AliTOFGeometry::NStripA() +   AliTOFGeometry::NStripB() + AliTOFGeometry::NStripC();
    break;
  case 4:
    before = AliTOFGeometry::NStripA() + 2*AliTOFGeometry::NStripB() + AliTOFGeometry::NStripC();
    break;
  }

  Int_t strip = fStrip + before;
  Int_t padTot = AliTOFGeometry::NpadXStrip()*strip + pad;
  return padTot;
}
<commit_msg>Reduced printout messages (AliInfo->AliDebug(1))<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//_________________________________________________________________________//
//                                                                         //
//  TOF sdigit: member variables                                           //
//  fSector  : TOF sector                                                  //
//  fPlate   : TOF plate                                                   //
//  fStrip   : strips number                                               //
//  fPadx    : pad number along x                                          //
//  fPadz    : pad number along z                                          //
//  fTdc     : TArrayI of TDC values                                       //
//  fAdc     : TArrayI of ADC values                                       //
//                                                                         //
//  Getters, setters and member functions  defined here                    //
//                                                                         //
// -- Authors: F. Pierella, A. Seganti, D. Vicinanza                       //
//_________________________________________________________________________//

#include "AliLog.h"

#include "AliTOFGeometry.h"
#include "AliTOFSDigit.h"

ClassImp(AliTOFSDigit)

////////////////////////////////////////////////////////////////////////
AliTOFSDigit::AliTOFSDigit():
  fSector(-1),
  fPlate(-1),
  fStrip(-1),
  fPadx(-1),
  fPadz(-1),
  fNDigits(0),
  fTdc(0x0),
  fAdc(0x0),
  fTracks(0x0)
{
  //
  // default ctor
  //
}

////////////////////////////////////////////////////////////////////////
AliTOFSDigit::AliTOFSDigit(Int_t tracknum, Int_t * const vol,Int_t * const digit):
  TObject(),
  fSector(-1),
  fPlate(-1),
  fStrip(-1),
  fPadx(-1),
  fPadz(-1),
  fNDigits(0),
  fTdc(0x0),
  fAdc(0x0),
  fTracks(0x0)
{
  //
  // Constructor of digit object
  //

  fSector = vol[0];
  fPlate  = vol[1];
  fStrip  = vol[2];
  fPadx   = vol[3];
  fPadz   = vol[4];
  fNDigits = 1;
  fTdc = new TArrayI(fNDigits);
  (*fTdc)[0] = digit[0];
  fAdc = new TArrayI(fNDigits);
  (*fAdc)[0] = digit[1];
  fTracks = new TArrayI(kMAXDIGITS*fNDigits);
  (*fTracks)[0] = tracknum;
  for (Int_t i = 1; i <kMAXDIGITS*fNDigits; i++) {
    (*fTracks)[i] = -1;
  }
}

////////////////////////////////////////////////////////////////////////
AliTOFSDigit::AliTOFSDigit(const AliTOFSDigit & digit):
  TObject(digit),
  fSector(digit.fSector),
  fPlate(digit.fPlate),
  fStrip(digit.fStrip),
  fPadx(digit.fPadx),
  fPadz(digit.fPadz),
  fNDigits(digit.fNDigits),
  fTdc(0x0),
  fAdc(0x0),
  fTracks(0x0)
{
  //
  // copy ctor for AliTOFSDigit object
  //
  fTdc = new TArrayI(*digit.fTdc);
  fAdc = new TArrayI(*digit.fAdc);
  fTracks = new TArrayI(*digit.fTracks);
}

////////////////////////////////////////////////////////////////////////
AliTOFSDigit& AliTOFSDigit::operator=(const AliTOFSDigit & digit)
{
  //
  // copy ctor for AliTOFSDigit object
  //

  if (this == &digit)
    return *this;

  TObject::operator=(digit);
  fSector = digit.fSector;
  fPlate  = digit.fPlate;
  fStrip  = digit.fStrip;
  fPadx   = digit.fPadx;
  fPadz   = digit.fPadz;
  fNDigits = digit.fNDigits;
  fTdc = digit.fTdc;
  fAdc = digit.fAdc;
  fTracks = digit.fTracks;
  return *this;

}

////////////////////////////////////////////////////////////////////////
AliTOFSDigit::AliTOFSDigit(Int_t sector, Int_t plate, Int_t strip, Int_t padx,
			   Int_t padz, Int_t tdc, Int_t adc):
  fSector(sector),
  fPlate(plate),
  fStrip(strip),
  fPadx(padx),
  fPadz(padz),
  fNDigits(1),
  fTdc(0x0),
  fAdc(0x0),
  fTracks(0x0)
{
  //
  // Constructor for sdigit
  //
  fTdc = new TArrayI(fNDigits);
  (*fTdc)[0] = tdc;
  fAdc = new TArrayI(fNDigits);
  (*fAdc)[0] = adc;
  // no tracks were specified, set them to -1
  fTracks = new TArrayI(kMAXDIGITS*fNDigits);
  for (Int_t i = 0; i <kMAXDIGITS*fNDigits; i++) {
    (*fTracks)[i] = -1;
  }
}

////////////////////////////////////////////////////////////////////////
void AliTOFSDigit::GetLocation(Int_t *Loc) const
{
  //
  // Get the coordinates of the digit
  // in terms of Sector - Plate - Strip - Pad
  //

  Loc[0]=fSector;
  Loc[1]=fPlate;
  Loc[2]=fStrip;
  Loc[3]=fPadx;
  Loc[4]=fPadz;
}

////////////////////////////////////////////////////////////////////////
void AliTOFSDigit::Update(Float_t tdcbin, Int_t tdc, Int_t adc, Int_t track)
{
  //
  // Add charge and track
  //

  Int_t sameTime = -1;
  Float_t tdcwindow = AliTOFGeometry::DeadTime()/tdcbin;
  for (Int_t i = 0; i < fNDigits; i++) {
    if (TMath::Abs(tdc-fTdc->At(i)) < tdcwindow) {
      sameTime = i;
      break;
    }
  }

  if (sameTime >= 0) { // another time measurement happens during the
		       // dead time of the hit pad => it corresponds
		       // to the same time measurement
    (*fAdc)[sameTime] += adc;

    // update track index array in case the current digit track index
    // is different from -1
    if (track!=-1) {

      //Find the first -1 value of the track index array and replace
      //it by the current digit track index
      for (Int_t iTrack=0; iTrack<kMAXDIGITS; iTrack++) {
	if (track==(*fTracks)[sameTime*kMAXDIGITS+iTrack]) break;
	if ((*fTracks)[sameTime*kMAXDIGITS+iTrack] == -1) {
	  (*fTracks)[sameTime*kMAXDIGITS+iTrack] = track;
	  break;
	}
	// write warning about many tracks going to this pad at same time
	if (iTrack == kMAXDIGITS-1) {
	  AliDebug(1,Form("Update: Many different tracks in the same TOF pad"
			  " (%2d %1d %2d %1d %2d)\n",
			  fSector,fPlate,fStrip,fPadz,fPadx));
	  //ToAliWarning(PrintPad());
	}
      }
    }

  } else { // they are two different time measurements

    // add new time slot
    fNDigits++;
    fTdc->Set(fNDigits);
    (*fTdc)[fNDigits-1] = tdc;
    fAdc->Set(fNDigits);
    (*fAdc)[fNDigits-1] = adc;
    fTracks->Set(fNDigits*kMAXDIGITS);
    (*fTracks)[(fNDigits-1)*kMAXDIGITS] = track;
    for (Int_t i = 1; i <kMAXDIGITS; i++)
      (*fTracks)[(fNDigits-1)*kMAXDIGITS+i] = -1;

  }

}

////////////////////////////////////////////////////////////////////////
void AliTOFSDigit::Update(AliTOFSDigit * const sdig)
{

  //
  // Perform the sum with sdig
  //

  Float_t tdcbin = AliTOFGeometry::TdcBinWidth();// [ps] hardwired for the time being

  Int_t track = -1;
  Int_t adc = -1;
  Int_t tdc = -1;

  // start loop on all sdig locations
  Int_t nlocations = sdig->GetNDigits();
  for (Int_t j = 0; j < nlocations; j++) {
    tdc = (Int_t)sdig->GetTdc(j);
    adc = (Int_t)sdig->GetAdc(j);

    // getting here only the first track number
    //Int_t track = GetTrack(j,0);

    // getting here all the track numbers
    for (Int_t iTrack = 0; iTrack<kMAXDIGITS; iTrack++) {
      track = sdig->GetTrack(j,iTrack);
      Update(tdcbin, tdc, adc, track);
    } // end loop on tracks

  } // end loop on sdig locations

}

////////////////////////////////////////////////////////////////////////
AliTOFSDigit::~AliTOFSDigit()
{
  //
  // dtor
  //
  delete fTdc;
  delete fAdc;
  delete fTracks;
}

////////////////////////////////////////////////////////////////////////

Int_t AliTOFSDigit::GetTotPad() const
{
  //
  // Get the "total" index of the pad inside a Sector
  // starting from the digits data.
  //

  Int_t pad = AliTOFGeometry::NpadZ()*fPadx + fPadz;
  Int_t before=0;

  switch(fPlate){
  case 0:
    //before = 0;
    break;
  case 1:
    before = AliTOFGeometry::NStripC();
    break;
  case 2:
    before = AliTOFGeometry::NStripB() +   AliTOFGeometry::NStripC();
    break;
  case 3:
    before = AliTOFGeometry::NStripA() +   AliTOFGeometry::NStripB() + AliTOFGeometry::NStripC();
    break;
  case 4:
    before = AliTOFGeometry::NStripA() + 2*AliTOFGeometry::NStripB() + AliTOFGeometry::NStripC();
    break;
  }

  Int_t strip = fStrip + before;
  Int_t padTot = AliTOFGeometry::NpadXStrip()*strip + pad;
  return padTot;
}
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2009 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "gdlhandler.h"

#include "gluonobject.h"
#include "gluonobjectfactory.h"
#include "debughelper.h"

#include <QtCore/QStringList>

using namespace GluonCore;

template<> GDLHandler* Singleton<GDLHandler>::m_instance = 0;

GDLHandler::GDLHandler()
{
}

GDLHandler::~GDLHandler()
{
}

GluonObject *
GDLHandler::instantiateObject( QString className )
{
    GluonObject* newObject = GluonObjectFactory::instance()->instantiateObjectByName( className );
    if( !newObject )
        newObject = new GluonObject();

    return newObject;
}

GluonObject *
GDLHandler::createObject( QStringList objectStringList, QObject* parent )
{
    DEBUG_BLOCK
    GluonObject* createdObject = 0;
    int index = 0;
    QString currentPropertyName;
    foreach( const QString & item, objectStringList )
    {
        switch( index )
        {
            case 0:
                // Object type
                createdObject = instantiateObject( item );
                createdObject->setParent( parent );
                //DEBUG_TEXT(QString("Instantiated object of type %1").arg(createdObject->metaObject()->className()));
                break;
            case 1:
                // Object name
                createdObject->setName( item );
                break;
            default:
                // Everything else
                if( currentPropertyName.isEmpty() )
                {
                    if( item.startsWith( '{' ) )
                    {
                        // Items are parented automatically - see case 0 above
                        QList<GluonObject*> childList = parseGDL( item, createdObject );
                    }
                    else
                    {
                        currentPropertyName = item;
                    }
                }
                else
                {
                    // Set the property with the current string as the value, and finally clear the property name
                    createdObject->setPropertyFromString( currentPropertyName, item );
                    currentPropertyName.clear();
                }
                break;
        }
        ++index;
    }
    return createdObject;
}

QList<QStringList>
GDLHandler::tokenizeObject( QString objectString )
{
    QList<QStringList> tokenizedObject;

    bool inItem = false;
    bool inObjectDefinition = false;
    bool inObjectName = false;
    bool inObjectType = false;

    bool inPropertyName = false;
    bool inPropertyValue = false;
    bool multilineProperty = false;
    bool inChild = false;
    bool childEnded = false;

    bool beingEscaped = false;
    int extraBracketCounter = 0;
    QString currentString;
    QStringList currentItem;

    QString::const_iterator i;
    for( i = objectString.begin(); i != objectString.end(); ++i )
    {
        if( !inItem )
        {
            if( i->isSpace() )
            {
                // Just do nothing - whitespace should be ignored outside of items
            }
            else if( i->toLower() == '{' )
            {
                inItem = true;
            }
        }
        else
        {
            if( !inPropertyValue && !inPropertyName && !inChild && !inObjectDefinition )
            {
                if( !currentString.isEmpty() )
                {
                    currentItem.append( currentString.trimmed() );
                    currentString.clear();
                }

                // Ignore whitespace as instructed, rar!
                if( !i->isSpace() )
                {
                    if( i->toLower() == '}' )
                    {
                        // Once we hit an end, we should stop looking at this item
                        // In other words - add the item to the list of items and make a new stringlist to work on...
                        QStringList theItem( currentItem );
                        tokenizedObject.append( theItem );
                        currentItem.clear();
                    }
                    else if( i->toLower() == '{' )
                    {
                        // If we hit a start while already inside an item, we should simply start adding stuff
                        // until we hit the correct ending again
                        inChild = true;
                    }
                    else
                    {
                        // Once you hit something, start reading the object definition
                        inObjectDefinition = true;
                    }
                }
            }

            if( inObjectDefinition )
            {
                if( !inPropertyName && !inObjectName && !inObjectType )
                {
                    // Ignore spaces between the start { and the object type
                    if( !i->isSpace() )
                        inObjectType = true;
                }

                if( inObjectType )
                {
                    if( i->toLower() == '(' )
                    {
                        currentItem.append( currentString.trimmed() );
                        currentString.clear();
                        inObjectType = false;
                        inObjectName = true;
                    }
                    else
                    {
                        currentString += i->unicode();
                    }
                }
                else if( inObjectName )
                {
                    if( i->toLower() == ')' )
                    {
                        currentItem.append( currentString.trimmed() );
                        currentString.clear();
                        inObjectName = false;
                        inPropertyName = true;
                    }
                    else
                    {
                        currentString += i->unicode();
                    }
                }
                else if( inPropertyName )
                {
                    if( !i->isSpace() )
                        inObjectDefinition = false;
                }
            }
            else if( inChild )
            {
                if( childEnded )
                {
                    if( !i->isSpace() )
                    {
                        inChild = false;
                    }
                }
                else
                {
                    if( i->toLower() == '\\' && !beingEscaped )
                    {
                        beingEscaped = true;
                    }
                    else
                    {
                        currentString += i->unicode();
                        if( !beingEscaped )
                        {
                            if( i->toLower() == '{' )
                            {
                                ++extraBracketCounter;
                            }

                            if( i->toLower() == '}' )
                            {
                                --extraBracketCounter;
                                if( extraBracketCounter == -1 )
                                {
                                    // Ready to look for more values!
                                    extraBracketCounter = 0;
                                    childEnded = true;
                                    inPropertyName = true;
                                    currentItem.append( '{' + currentString.trimmed() );
                                    currentString.clear();
                                }
                            }
                        }
                        else
                        {
                            beingEscaped = false;
                        }
                    }
                }
            }

            if( !inObjectDefinition && !inChild )
            {
                if( inPropertyName )
                {
                    // Read name until we hit a space, and after that, start reading the value...
                    if( i->toLower() == '{' )
                    {
                        inChild = true;
                        childEnded = false;
                    }
                    else if( i->toLower() == '}' )
                    {
                        inPropertyName = false;
                        // Rewind the pointer to make it possible to catch the end brackets above
                        --i;
                    }
                    else if( !i->isSpace() )
                    {
                        currentString += i->unicode();
                    }
                    else
                    {
                        currentItem.append( currentString.trimmed() );
                        currentString.clear();
                        inPropertyName = false;
                        inPropertyValue = true;
                    }
                }
                else if( inPropertyValue )
                {
                    if( *i == '<' && *(i + 1) == '<' && *(i + 2) == '<'  )
                    {
                        multilineProperty = !multilineProperty;
                        i = i + 2;
                    }
                    else if( i->toLower() == '\\' && !beingEscaped )
                    {
                        beingEscaped = true;
                    }
                    else
                    {
                        // Read the value until the value ends!
                        currentString += i->unicode();
                        if( !beingEscaped && !multilineProperty && i->toLower() == ')' )
                        {
                            currentItem.append( currentString.trimmed() );
                            currentString.clear();
                            inPropertyValue = false;
                            inPropertyName = true;
                            // Make sure you don't start looking for property names again until you've got something that
                            // isn't a space (since the propertyname search doesn't know how to handle that)
                            forever
                            {
                                if( i == objectString.end() )
                                    break;
                                ++i;
                                if( i->isSpace() )
                                    continue;
                                --i;
                                break;
                            }
                        }
                        beingEscaped = false;
                    }
                }
            }
        }
    }

    return tokenizedObject;
}

QList<GluonObject*>
GDLHandler::parseGDL( const QString parseThis, QObject* parent )
{
    QList<GluonObject*> thisObjectList;

    QList<QStringList> tokenizedObject = tokenizeObject( parseThis );

    foreach( const QStringList & item, tokenizedObject )
    {
        GluonObject* currentObject = createObject( item, parent );
        thisObjectList.append( currentObject );
        currentObject->sanitize();
    }

    return thisObjectList;
}

QString
GDLHandler::serializeGDL( QList<const GluonObject*> serializeThis )
{
    QString serializedData;

    foreach( const GluonObject * theObject, serializeThis )
    serializedData += theObject->toGDL();

    return serializedData;
}

#include "gdlhandler.moc"
<commit_msg>Ignore comment lines in GDL<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2009 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "gdlhandler.h"

#include "gluonobject.h"
#include "gluonobjectfactory.h"
#include "debughelper.h"

#include <QtCore/QStringList>

using namespace GluonCore;

template<> GDLHandler* Singleton<GDLHandler>::m_instance = 0;

GDLHandler::GDLHandler()
{
}

GDLHandler::~GDLHandler()
{
}

GluonObject *
GDLHandler::instantiateObject( QString className )
{
    GluonObject* newObject = GluonObjectFactory::instance()->instantiateObjectByName( className );
    if( !newObject )
        newObject = new GluonObject();

    return newObject;
}

GluonObject *
GDLHandler::createObject( QStringList objectStringList, QObject* parent )
{
    DEBUG_BLOCK
    GluonObject* createdObject = 0;
    int index = 0;
    QString currentPropertyName;
    foreach( const QString & item, objectStringList )
    {
        switch( index )
        {
            case 0:
                // Object type
                createdObject = instantiateObject( item );
                createdObject->setParent( parent );
                //DEBUG_TEXT(QString("Instantiated object of type %1").arg(createdObject->metaObject()->className()));
                break;
            case 1:
                // Object name
                createdObject->setName( item );
                break;
            default:
                // Everything else
                if( currentPropertyName.isEmpty() )
                {
                    if( item.startsWith( '{' ) )
                    {
                        // Items are parented automatically - see case 0 above
                        QList<GluonObject*> childList = parseGDL( item, createdObject );
                    }
                    else
                    {
                        currentPropertyName = item;
                    }
                }
                else
                {
                    // Set the property with the current string as the value, and finally clear the property name
                    createdObject->setPropertyFromString( currentPropertyName, item );
                    currentPropertyName.clear();
                }
                break;
        }
        ++index;
    }
    return createdObject;
}

QList<QStringList>
GDLHandler::tokenizeObject( QString objectString )
{
    QList<QStringList> tokenizedObject;

    bool inItem = false;
    bool inObjectDefinition = false;
    bool inObjectName = false;
    bool inObjectType = false;

    bool inPropertyName = false;
    bool inPropertyValue = false;
    bool multilineProperty = false;
    bool inChild = false;
    bool childEnded = false;

    bool beingEscaped = false;
    int extraBracketCounter = 0;
    QString currentString;
    QStringList currentItem;

    QString::const_iterator i;
    for( i = objectString.begin(); i != objectString.end(); ++i )
    {
        if( !inItem )
        {
            if( i->isSpace() )
            {
                // Just do nothing - whitespace should be ignored outside of items
            }
            else if( i->toLower() == '{' )
            {
                inItem = true;
            }
        }
        else
        {
            if( !inPropertyValue && !inPropertyName && !inChild && !inObjectDefinition )
            {
                if( !currentString.isEmpty() )
                {
                    currentItem.append( currentString.trimmed() );
                    currentString.clear();
                }

                // Ignore whitespace as instructed, rar!
                if( !i->isSpace() && (*i) != '#' )
                {
                    if( i->toLower() == '}' )
                    {
                        // Once we hit an end, we should stop looking at this item
                        // In other words - add the item to the list of items and make a new stringlist to work on...
                        QStringList theItem( currentItem );
                        tokenizedObject.append( theItem );
                        currentItem.clear();
                    }
                    else if( i->toLower() == '{' )
                    {
                        // If we hit a start while already inside an item, we should simply start adding stuff
                        // until we hit the correct ending again
                        inChild = true;
                    }
                    else
                    {
                        // Once you hit something, start reading the object definition
                        inObjectDefinition = true;
                    }
                }
            }

            if( inObjectDefinition )
            {
                if( !inPropertyName && !inObjectName && !inObjectType )
                {
                    // Ignore spaces between the start { and the object type
                    if( !i->isSpace() )
                        inObjectType = true;
                }

                if( inObjectType )
                {
                    if( i->toLower() == '(' )
                    {
                        currentItem.append( currentString.trimmed() );
                        currentString.clear();
                        inObjectType = false;
                        inObjectName = true;
                    }
                    else
                    {
                        currentString += i->unicode();
                    }
                }
                else if( inObjectName )
                {
                    if( i->toLower() == ')' )
                    {
                        currentItem.append( currentString.trimmed() );
                        currentString.clear();
                        inObjectName = false;
                        inPropertyName = true;
                    }
                    else
                    {
                        currentString += i->unicode();
                    }
                }
                else if( inPropertyName )
                {
                    if( !i->isSpace() )
                        inObjectDefinition = false;
                }
            }
            else if( inChild )
            {
                if( childEnded )
                {
                    if( !i->isSpace() )
                    {
                        inChild = false;
                    }
                }
                else
                {
                    if( i->toLower() == '\\' && !beingEscaped )
                    {
                        beingEscaped = true;
                    }
                    else
                    {
                        currentString += i->unicode();
                        if( !beingEscaped )
                        {
                            if( i->toLower() == '{' )
                            {
                                ++extraBracketCounter;
                            }

                            if( i->toLower() == '}' )
                            {
                                --extraBracketCounter;
                                if( extraBracketCounter == -1 )
                                {
                                    // Ready to look for more values!
                                    extraBracketCounter = 0;
                                    childEnded = true;
                                    inPropertyName = true;
                                    currentItem.append( '{' + currentString.trimmed() );
                                    currentString.clear();
                                }
                            }
                        }
                        else
                        {
                            beingEscaped = false;
                        }
                    }
                }
            }

            if( !inObjectDefinition && !inChild )
            {
                if( inPropertyName )
                {
                    // Read name until we hit a space, and after that, start reading the value...
                    if( i->toLower() == '{' )
                    {
                        inChild = true;
                        childEnded = false;
                    }
                    else if( i->toLower() == '}' )
                    {
                        inPropertyName = false;
                        // Rewind the pointer to make it possible to catch the end brackets above
                        --i;
                    }
                    else if( !i->isSpace() )
                    {
                        currentString += i->unicode();
                    }
                    else
                    {
                        currentItem.append( currentString.trimmed() );
                        currentString.clear();
                        inPropertyName = false;
                        inPropertyValue = true;
                    }
                }
                else if( inPropertyValue )
                {
                    if( *i == '<' && *(i + 1) == '<' && *(i + 2) == '<'  )
                    {
                        multilineProperty = !multilineProperty;
                        i = i + 2;
                    }
                    else if( i->toLower() == '\\' && !beingEscaped )
                    {
                        beingEscaped = true;
                    }
                    else
                    {
                        // Read the value until the value ends!
                        currentString += i->unicode();
                        if( !beingEscaped && !multilineProperty && i->toLower() == ')' )
                        {
                            currentItem.append( currentString.trimmed() );
                            currentString.clear();
                            inPropertyValue = false;
                            inPropertyName = true;
                            // Make sure you don't start looking for property names again until you've got something that
                            // isn't a space (since the propertyname search doesn't know how to handle that)
                            forever
                            {
                                if( i == objectString.end() )
                                    break;
                                ++i;
                                if( i->isSpace() )
                                    continue;
                                --i;
                                break;
                            }
                        }
                        beingEscaped = false;
                    }
                }
            }
        }
    }

    return tokenizedObject;
}

QList<GluonObject*>
GDLHandler::parseGDL( const QString parseThis, QObject* parent )
{
    QList<GluonObject*> thisObjectList;

    QList<QStringList> tokenizedObject = tokenizeObject( parseThis );

    foreach( const QStringList & item, tokenizedObject )
    {
        GluonObject* currentObject = createObject( item, parent );
        thisObjectList.append( currentObject );
        currentObject->sanitize();
    }

    return thisObjectList;
}

QString
GDLHandler::serializeGDL( QList<const GluonObject*> serializeThis )
{
    QString serializedData;

    foreach( const GluonObject * theObject, serializeThis )
    serializedData += theObject->toGDL();

    return serializedData;
}

#include "gdlhandler.moc"
<|endoftext|>