<commit_before>#pragma once

#include <cstdint>

#include <cstdio>
#include <cstdlib>

#include <core/Console.hpp>

#include "BlockCache.hpp"
#include "BlockStorageDevice.hpp"
#include "Partition.hpp"
#include "DeviceManager.hpp"

struct PartitionInfo {
	std::uint64_t startSector;
	std::uint64_t nbSectors;
	int partno;
};

struct MBR {
	char bootstrap[436];
	char diskID[10];
	char MBRPartitionTable[64];
	char signature[2];
};

static_assert(sizeof(MBR) == 512, "Size is not correct");

struct MBRPartition {
	union {
		struct {
			uint8_t partEntry[16];
		};
		struct {
			std::uint8_t bootIndicator;
			std::uint8_t startHead;
			std::uint8_t startSector;
			std::uint8_t startCylinder;
			std::uint8_t SystemID;
			std::uint8_t endHead;
			std::uint8_t endSector;
			std::uint8_t endCylinder;
			std::uint32_t partitionStartLBA;
			std::uint32_t partitionSize;
		};
	};
};

class Disk {
public:
	Disk(BlockStorageDevice* storage) : storage(storage), parts(), cache(storage->getSectorSize()) {
		readMBR();
	}

	virtual ~Disk() {

	}

	PartitionInfo getPartitionInfo(int partno)  {
		if (partno < 0 || partno >= (int)parts.size()) {
			return PartitionInfo();
		} else {
			return parts[partno];
		}
	}

	Block* getBlock(std::uint64_t lba) {
		BlockIO bio;
		BlockIOSegment bioSeg1;
		Block* block = cache.getBlock(lba);
		if (block->valid) {
			return block;
		} else {
			bioSeg1.page = block->page;
			bioSeg1.offset = block->offset;
			bioSeg1.len = block->len;
			bio.segments.push_back(bioSeg1);
			bio.nb_sectors = 1;
			bio.start_sector = lba;
			bio.write = 0;
			storage->loadBlockIO(bio);

			block->valid = true;
			return block;
		}
	}

	std::uint64_t getSectorSize() {
		return storage->getSectorSize();
	}

private:

	void readMBR() {
		BlockDevice* dev = nullptr;

		char tmp[1024];
		sprintf(tmp, "Informations about '%s'\n", storage->getName().c_str());
		Console::write(tmp);

		PartitionInfo partFull = {0, storage->getSectorNumber(), 0};
		parts.push_back(partFull);
		dev = new Partition(this, 0, storage->getName());
		DeviceManager::registerBlockDevice(dev);
		sprintf(tmp, "Partition * size: %i sectors, start: %i\n",
				partFull.nbSectors, partFull.startSector);
		Console::write(tmp);

		Block* block = getBlock(0);
		MBR* mbr = (MBR*)(block->page->kernelMappAddr + block->offset);
		if ((mbr->signature[0] == (char)0x55) && (mbr->signature[1] == (char)0xAA)) {
			for (int partNum = 0; partNum < 4; partNum++) {
				MBRPartition part;
				for (int i = 0; i < 16; i++) {
					part.partEntry[i] = mbr->MBRPartitionTable[partNum*16+i];
				}

				PartitionInfo newPart = {part.partitionStartLBA, part.partitionSize, partNum+1};
				parts.push_back(newPart);
				char name[1024];
				sprintf(name, "%s%i", storage->getName(), partNum);
				dev = new Partition(this, partNum, name);
				DeviceManager::registerBlockDevice(dev);

				sprintf(tmp, "Partition %i size: %i sectors, start: %i\n", newPart.partno,
						newPart.nbSectors, newPart.startSector);
				Console::write(tmp);
			}
		} else {
			Console::write("No MBR found\n");
		}
	}

	BlockStorageDevice* storage;
	std::vector<PartitionInfo> parts;
	BlockCache cache;
};
<commit_msg>fix warning sprintf<commit_after>#pragma once

#include <cstdint>

#include <cstdio>
#include <cstdlib>

#include <core/Console.hpp>

#include "BlockCache.hpp"
#include "BlockStorageDevice.hpp"
#include "Partition.hpp"
#include "DeviceManager.hpp"

struct PartitionInfo {
	std::uint64_t startSector;
	std::uint64_t nbSectors;
	int partno;
};

struct MBR {
	char bootstrap[436];
	char diskID[10];
	char MBRPartitionTable[64];
	char signature[2];
};

static_assert(sizeof(MBR) == 512, "Size is not correct");

struct MBRPartition {
	union {
		struct {
			uint8_t partEntry[16];
		};
		struct {
			std::uint8_t bootIndicator;
			std::uint8_t startHead;
			std::uint8_t startSector;
			std::uint8_t startCylinder;
			std::uint8_t SystemID;
			std::uint8_t endHead;
			std::uint8_t endSector;
			std::uint8_t endCylinder;
			std::uint32_t partitionStartLBA;
			std::uint32_t partitionSize;
		};
	};
};

class Disk {
public:
	Disk(BlockStorageDevice* storage) : storage(storage), parts(), cache(storage->getSectorSize()) {
		readMBR();
	}

	virtual ~Disk() {

	}

	PartitionInfo getPartitionInfo(int partno)  {
		if (partno < 0 || partno >= (int)parts.size()) {
			return PartitionInfo();
		} else {
			return parts[partno];
		}
	}

	Block* getBlock(std::uint64_t lba) {
		BlockIO bio;
		BlockIOSegment bioSeg1;
		Block* block = cache.getBlock(lba);
		if (block->valid) {
			return block;
		} else {
			bioSeg1.page = block->page;
			bioSeg1.offset = block->offset;
			bioSeg1.len = block->len;
			bio.segments.push_back(bioSeg1);
			bio.nb_sectors = 1;
			bio.start_sector = lba;
			bio.write = 0;
			storage->loadBlockIO(bio);

			block->valid = true;
			return block;
		}
	}

	std::uint64_t getSectorSize() {
		return storage->getSectorSize();
	}

private:

	void readMBR() {
		BlockDevice* dev = nullptr;

		char tmp[1024];
		sprintf(tmp, "Informations about '%s'\n", storage->getName().c_str());
		Console::write(tmp);

		PartitionInfo partFull = {0, storage->getSectorNumber(), 0};
		parts.push_back(partFull);
		dev = new Partition(this, 0, storage->getName());
		DeviceManager::registerBlockDevice(dev);
		sprintf(tmp, "Partition * size: %llu sectors, start: %llu\n",
				partFull.nbSectors, partFull.startSector);
		Console::write(tmp);

		Block* block = getBlock(0);
		MBR* mbr = (MBR*)(block->page->kernelMappAddr + block->offset);
		if ((mbr->signature[0] == (char)0x55) && (mbr->signature[1] == (char)0xAA)) {
			for (int partNum = 0; partNum < 4; partNum++) {
				MBRPartition part;
				for (int i = 0; i < 16; i++) {
					part.partEntry[i] = mbr->MBRPartitionTable[partNum*16+i];
				}

				PartitionInfo newPart = {part.partitionStartLBA, part.partitionSize, partNum+1};
				parts.push_back(newPart);
				char name[1024];
				sprintf(name, "%s%i", storage->getName().c_str(), partNum);
				dev = new Partition(this, partNum, name);
				DeviceManager::registerBlockDevice(dev);

				sprintf(tmp, "Partition %i size: %llu sectors, start: %llu\n", newPart.partno,
						newPart.nbSectors, newPart.startSector);
				Console::write(tmp);
			}
		} else {
			Console::write("No MBR found\n");
		}
	}

	BlockStorageDevice* storage;
	std::vector<PartitionInfo> parts;
	BlockCache cache;
};
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <memory>

// template <class OuterAlloc, class... InnerAllocs>
// class scoped_allocator_adaptor
//     : public OuterAlloc
// {
// public:
//     typedef OuterAlloc outer_allocator_type;
//     typedef typename OuterTraits::size_type size_type;
//     typedef typename OuterTraits::difference_type difference_type;
//     typedef typename OuterTraits::pointer pointer;
//     typedef typename OuterTraits::const_pointer const_pointer;
//     typedef typename OuterTraits::void_pointer void_pointer;
//     typedef typename OuterTraits::const_void_pointer const_void_pointer;
// };

#include <scoped_allocator>
#include <type_traits>

#include "allocators.h"

int main()
{
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES

    static_assert((std::is_base_of<
        A1<int>,
        std::scoped_allocator_adaptor<A1<int>>
        >::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::outer_allocator_type,
        A1<int>>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::size_type,
        std::size_t>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::difference_type,
        std::ptrdiff_t>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::pointer,
        int*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::const_pointer,
        const int*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::void_pointer,
        void*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::const_void_pointer,
        const void*>::value), "");

    static_assert((std::is_base_of<
        A2<int>,
        std::scoped_allocator_adaptor<A2<int>, A1<int>>
        >::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::outer_allocator_type,
        A2<int>>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::size_type,
        unsigned>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::difference_type,
        int>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::pointer,
        int*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::const_pointer,
        const int*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::void_pointer,
        void*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::const_void_pointer,
        const void*>::value), "");

#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
}
<commit_msg>Test adjustment for recent changes in allocator_traits<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <memory>

// template <class OuterAlloc, class... InnerAllocs>
// class scoped_allocator_adaptor
//     : public OuterAlloc
// {
// public:
//     typedef OuterAlloc outer_allocator_type;
//     typedef typename OuterTraits::size_type size_type;
//     typedef typename OuterTraits::difference_type difference_type;
//     typedef typename OuterTraits::pointer pointer;
//     typedef typename OuterTraits::const_pointer const_pointer;
//     typedef typename OuterTraits::void_pointer void_pointer;
//     typedef typename OuterTraits::const_void_pointer const_void_pointer;
// };

#include <scoped_allocator>
#include <type_traits>

#include "allocators.h"

int main()
{
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES

    static_assert((std::is_base_of<
        A1<int>,
        std::scoped_allocator_adaptor<A1<int>>
        >::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::outer_allocator_type,
        A1<int>>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::size_type,
        std::make_unsigned<std::ptrdiff_t>::type>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::difference_type,
        std::ptrdiff_t>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::pointer,
        int*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::const_pointer,
        const int*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::void_pointer,
        void*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A1<int>>::const_void_pointer,
        const void*>::value), "");

    static_assert((std::is_base_of<
        A2<int>,
        std::scoped_allocator_adaptor<A2<int>, A1<int>>
        >::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::outer_allocator_type,
        A2<int>>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::size_type,
        unsigned>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::difference_type,
        int>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::pointer,
        int*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::const_pointer,
        const int*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::void_pointer,
        void*>::value), "");

    static_assert((std::is_same<
        std::scoped_allocator_adaptor<A2<int>, A1<int>>::const_void_pointer,
        const void*>::value), "");

#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
}
<|endoftext|>


<commit_before>/*
    kopetecommand.cpp - Command

    Copyright (c) 2003 by Jason Keirstead <jason@keirstead.org>

    *************************************************************************
    *                                                                       *
    * 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 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include <qstringlist.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kinputdialog.h>
#include <klocale.h>
#include <kmessagebox.h>

#include "kopetemessagemanagerfactory.h"
#include "kopeteview.h"
#include "kopetecommand.h"
#include "kopeteuiglobal.h"

KopeteCommand::KopeteCommand( QObject *parent, const QString &command, const char* handlerSlot,
	const QString &help, KopeteCommandHandler::CommandType type, const QString &formatString,
	uint minArgs, int maxArgs, const KShortcut &cut, const QString &pix )
	: KAction( command[0].upper() + command.right( command.length() - 1).lower(), pix, cut, parent,
	( command.lower() + QString::fromLatin1("_command") ).latin1() )
{
	init( command, handlerSlot, help, type, formatString, minArgs, maxArgs );
}

void KopeteCommand::init( const QString &command, const char* slot, const QString &help,
	KopeteCommandHandler::CommandType type, const QString &formatString, uint minArgs, int maxArgs )
{
	m_command = command;
	m_help = help;
	m_type = type;
	m_formatString = formatString;
	m_minArgs = minArgs;
	m_maxArgs = maxArgs;

	if(  m_type == KopeteCommandHandler::Normal )
	{
		QObject::connect( this, SIGNAL( handleCommand( const QString &, KopeteMessageManager *) ),
			parent(), slot );
	}

	QObject::connect( this, SIGNAL( activated() ), this, SLOT( slotAction() ) );
}

void KopeteCommand::slotAction()
{
	KopeteMessageManager *manager = KopeteMessageManagerFactory::factory()->activeView()->msgManager();

	QString args;
	if( m_minArgs > 0 )
	{
		args = KInputDialog::getText( i18n("Enter Arguments"), i18n("Enter the arguments to %1:").arg(m_command) );
	}

	processCommand( args, manager, true );
}

void KopeteCommand::processCommand( const QString &args, KopeteMessageManager *manager, bool gui )
{
	QStringList mArgs = KopeteCommandHandler::parseArguments( args );
	if( mArgs.count() < m_minArgs )
	{
		printError( i18n("\"%1\" requires at least %n argument.",
			"\"%1\" requires at least %n arguments.", m_minArgs)
			.arg( text() ), manager, gui );
	}
	else if( m_maxArgs > -1 && (int)mArgs.count() > m_maxArgs )
	{
		printError( i18n("\"%1\" has a maximum of %n argument.",
			"\"%1\" has a maximum of %n arguments.", m_minArgs)
			.arg( text() ), manager, gui );
	}
	else if( !KApplication::kApplication()->authorizeKAction( name() ) )
	{
		printError( i18n("You are not authorized to perform the command \"%1\".").arg(text()), manager, gui );
	}
	else
	{
		if( m_type == KopeteCommandHandler::UserAlias ||
			m_type == KopeteCommandHandler::SystemAlias )
		{
			QString formatString = m_formatString;
			if( formatString.contains( QString::fromLatin1("%s") ) )
				formatString.replace( QString::fromLatin1("%s"), args );
			else
			{
				while( mArgs.count() > 0 )
				{
					formatString = formatString.arg( mArgs.front() );
					mArgs.pop_front();
				}
			}

			kdDebug(14010) << "New Command after processing alias: " << formatString << endl;

			KopeteCommandHandler::commandHandler()->processMessage( QString::fromLatin1("/") + formatString, manager );
		}
		else
		{
			emit( handleCommand( args, manager ) );
		}
	}
}

void KopeteCommand::printError( const QString &error, KopeteMessageManager *manager, bool gui ) const
{
	if( gui )
	{
		KMessageBox::error( Kopete::UI::Global::mainWidget(), error, i18n("Command Error") );
	}
	else
	{
		KopeteMessage msg( manager->user(), manager->members(), error,
			KopeteMessage::Internal, KopeteMessage::PlainText );
		manager->appendMessage( msg );
	}
}

#include "kopetecommand.moc"
<commit_msg>Don't try to execute if they press cancel<commit_after>/*
    kopetecommand.cpp - Command

    Copyright (c) 2003 by Jason Keirstead <jason@keirstead.org>

    *************************************************************************
    *                                                                       *
    * 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 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include <qstringlist.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kinputdialog.h>
#include <klocale.h>
#include <kmessagebox.h>

#include "kopetemessagemanagerfactory.h"
#include "kopeteview.h"
#include "kopetecommand.h"
#include "kopeteuiglobal.h"

KopeteCommand::KopeteCommand( QObject *parent, const QString &command, const char* handlerSlot,
	const QString &help, KopeteCommandHandler::CommandType type, const QString &formatString,
	uint minArgs, int maxArgs, const KShortcut &cut, const QString &pix )
	: KAction( command[0].upper() + command.right( command.length() - 1).lower(), pix, cut, parent,
	( command.lower() + QString::fromLatin1("_command") ).latin1() )
{
	init( command, handlerSlot, help, type, formatString, minArgs, maxArgs );
}

void KopeteCommand::init( const QString &command, const char* slot, const QString &help,
	KopeteCommandHandler::CommandType type, const QString &formatString, uint minArgs, int maxArgs )
{
	m_command = command;
	m_help = help;
	m_type = type;
	m_formatString = formatString;
	m_minArgs = minArgs;
	m_maxArgs = maxArgs;

	if(  m_type == KopeteCommandHandler::Normal )
	{
		QObject::connect( this, SIGNAL( handleCommand( const QString &, KopeteMessageManager *) ),
			parent(), slot );
	}

	QObject::connect( this, SIGNAL( activated() ), this, SLOT( slotAction() ) );
}

void KopeteCommand::slotAction()
{
	KopeteMessageManager *manager = KopeteMessageManagerFactory::factory()->activeView()->msgManager();

	QString args;
	if( m_minArgs > 0 )
	{
		args = KInputDialog::getText( i18n("Enter Arguments"), i18n("Enter the arguments to %1:").arg(m_command) );
		if( args.isNull() )
			return;
	}

	processCommand( args, manager, true );
}

void KopeteCommand::processCommand( const QString &args, KopeteMessageManager *manager, bool gui )
{
	QStringList mArgs = KopeteCommandHandler::parseArguments( args );
	if( mArgs.count() < m_minArgs )
	{
		printError( i18n("\"%1\" requires at least %n argument.",
			"\"%1\" requires at least %n arguments.", m_minArgs)
			.arg( text() ), manager, gui );
	}
	else if( m_maxArgs > -1 && (int)mArgs.count() > m_maxArgs )
	{
		printError( i18n("\"%1\" has a maximum of %n argument.",
			"\"%1\" has a maximum of %n arguments.", m_minArgs)
			.arg( text() ), manager, gui );
	}
	else if( !KApplication::kApplication()->authorizeKAction( name() ) )
	{
		printError( i18n("You are not authorized to perform the command \"%1\".").arg(text()), manager, gui );
	}
	else
	{
		if( m_type == KopeteCommandHandler::UserAlias ||
			m_type == KopeteCommandHandler::SystemAlias )
		{
			QString formatString = m_formatString;
			if( formatString.contains( QString::fromLatin1("%s") ) )
				formatString.replace( QString::fromLatin1("%s"), args );
			else
			{
				while( mArgs.count() > 0 )
				{
					formatString = formatString.arg( mArgs.front() );
					mArgs.pop_front();
				}
			}

			kdDebug(14010) << "New Command after processing alias: " << formatString << endl;

			KopeteCommandHandler::commandHandler()->processMessage( QString::fromLatin1("/") + formatString, manager );
		}
		else
		{
			emit( handleCommand( args, manager ) );
		}
	}
}

void KopeteCommand::printError( const QString &error, KopeteMessageManager *manager, bool gui ) const
{
	if( gui )
	{
		KMessageBox::error( Kopete::UI::Global::mainWidget(), error, i18n("Command Error") );
	}
	else
	{
		KopeteMessage msg( manager->user(), manager->members(), error,
			KopeteMessage::Internal, KopeteMessage::PlainText );
		manager->appendMessage( msg );
	}
}

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


<commit_before>/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * 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 "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/pipe.h"
#include "perfetto/ext/base/subprocess.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/traced/traced.h"
#include "src/perfetto_cmd/perfetto_cmd.h"
#include "src/websocket_bridge/websocket_bridge.h"

#include <stdio.h>

#include <tuple>

namespace perfetto {
namespace {

struct Applet {
  using MainFunction = int (*)(int /*argc*/, char** /*argv*/);
  const char* name;
  MainFunction entrypoint;
};

const Applet g_applets[]{
    {"traced", ServiceMain},
    {"traced_probes", ProbesMain},
    {"perfetto", PerfettoCmdMain},
    {"trigger_perfetto", TriggerPerfettoMain},
    {"websocket_bridge", WebsocketBridgeMain},
};

void PrintUsage() {
  printf(R"(Welcome to Perfetto tracing!

Tracebox is a bundle containing all the tracing services and the perfetto
cmdline client in one binary. It can be used either to spawn manually the
various subprocess or in "autostart" mode, which will take care of starting
and tearing down the services for you.

Usage in autostart mode:
  tracebox -t 10s -o trace_file.perfetto-trace sched/sched_switch
  See tracebox --help for more options.

Usage in manual mode:
  tracebox applet_name [args ...]  (e.g. ./tracebox traced --help)
  Applets:)");

  for (const Applet& applet : g_applets)
    printf(" %s", applet.name);

  printf(R"(

See also:
  * https://perfetto.dev/docs/
  * The config editor in the record page of https://ui.perfetto.dev/
)");
}

int TraceboxMain(int argc, char** argv) {
  // Manual mode: if either the 1st argument (argv[1]) or the exe name (argv[0])
  // match the name of an applet, directly invoke that without further
  // modifications.

  // Extract the file name from argv[0].
  char* slash = strrchr(argv[0], '/');
  char* argv0 = slash ? slash + 1 : argv[0];

  for (const Applet& applet : g_applets) {
    if (!strcmp(argv0, applet.name))
      return applet.entrypoint(argc, argv);
    if (argc > 1 && !strcmp(argv[1], applet.name))
      return applet.entrypoint(argc - 1, &argv[1]);
  }

  // If no matching applet is found, switch to the autostart mode. In this mode
  // we make tracebox behave like the cmdline client (without needing to prefix
  // it with "perfetto"), but will also start traced and traced_probes.
  // As part of this we also use a different namespace for the producer/consumer
  // sockets, to avoid clashing with the system daemon.

  if (argc <= 1) {
    PrintUsage();
    return 1;
  }

  auto pid_str = std::to_string(static_cast<uint64_t>(base::GetProcessId()));
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  // Use an unlinked abstract domain socket on Linux/Android.
  std::string consumer_socket = "@traced-c-" + pid_str;
  std::string producer_socket = "@traced-p-" + pid_str;
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
  std::string consumer_socket = "/tmp/traced-c-" + pid_str;
  std::string producer_socket = "/tmp/traced-p-" + pid_str;
#else
  PERFETTO_FATAL("The autostart mode is not supported on this platform");
#endif

  // If the caller has set the PERFETTO_*_SOCK_NAME, respect those.
  const char* env;
  if ((env = getenv("PERFETTO_CONSUMER_SOCK_NAME")))
    consumer_socket = env;
  if ((env = getenv("PERFETTO_PRODUCER_SOCK_NAME")))
    producer_socket = env;

  base::SetEnv("PERFETTO_CONSUMER_SOCK_NAME", consumer_socket);
  base::SetEnv("PERFETTO_PRODUCER_SOCK_NAME", producer_socket);

  PerfettoCmd perfetto_cmd;

  // If the cmdline parsing fails, stop here, no need to spawn services.
  // It will daemonize if --background. In that case the subprocesses will be
  // spawned by the damonized cmdline client, which is what we want so killing
  // the backgrounded cmdline client will also kill the other services, as they
  // will live in the same background session.
  auto opt_res = perfetto_cmd.ParseCmdlineAndMaybeDaemonize(argc, argv);
  if (opt_res.has_value())
    return *opt_res;

  std::string self_path = base::GetCurExecutablePath();
  base::Subprocess traced({self_path, "traced"});
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // |traced_sync_pipe| is used to synchronize with traced socket creation.
  // traced will write "1" and close the FD when the IPC socket is listening
  // (or traced crashed).
  base::Pipe traced_sync_pipe = base::Pipe::Create();
  int traced_fd = *traced_sync_pipe.wr;
  base::SetEnv("TRACED_NOTIFY_FD", std::to_string(traced_fd));
  traced.args.preserve_fds.emplace_back(traced_fd);
  // Create a new process group so CTRL-C is delivered only to the cmdline
  // process (the tracebox one) and not to traced. traced will still exit once
  // the main process exits, but this allows graceful stopping of the trace
  // without abruptedly killing traced{,probes} when hitting CTRL+C.
  traced.args.posix_proc_group_id = 0;  // 0 = start a new process group.
#endif
  traced.Start();

#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  traced_sync_pipe.wr.reset();

  std::string traced_notify_msg;
  base::ReadPlatformHandle(*traced_sync_pipe.rd, &traced_notify_msg);
  if (traced_notify_msg != "1")
    PERFETTO_FATAL("The tracing service failed unexpectedly. Check the logs");
#endif

  base::Subprocess traced_probes(
      {self_path, "traced_probes", "--reset-ftrace"});
  // Put traced_probes in the same process group as traced. Same reason (CTRL+C)
  // but it's not worth creating a new group.
  traced_probes.args.posix_proc_group_id = traced.pid();
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // |traced_probes_sync_pipe| is used to synchronize with traced socket
  // creation. traced will write "1" and close the FD when the IPC socket is
  // listening (or traced crashed).
  base::Pipe traced_probes_sync_pipe = base::Pipe::Create();
  int traced_probes_fd = *traced_probes_sync_pipe.wr;
  base::SetEnv("TRACED_PROBES_NOTIFY_FD", std::to_string(traced_probes_fd));
  traced_probes.args.preserve_fds.emplace_back(traced_probes_fd);
#endif
  traced_probes.Start();

#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  traced_probes_sync_pipe.wr.reset();

  std::string traced_probes_notify_msg;
  base::ReadPlatformHandle(*traced_probes_sync_pipe.rd,
                           &traced_probes_notify_msg);
  if (traced_probes_notify_msg != "1")
    PERFETTO_FATAL(
        "The traced_proces service failed unexpectedly. Check the logs");
#endif

  perfetto_cmd.ConnectToServiceRunAndMaybeNotify();
  return 0;
}

}  // namespace
}  // namespace perfetto

int main(int argc, char** argv) {
  return perfetto::TraceboxMain(argc, argv);
}
<commit_msg>tracebox: fix "traced_proces" typo in error message.<commit_after>/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * 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 "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/pipe.h"
#include "perfetto/ext/base/subprocess.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/traced/traced.h"
#include "src/perfetto_cmd/perfetto_cmd.h"
#include "src/websocket_bridge/websocket_bridge.h"

#include <stdio.h>

#include <tuple>

namespace perfetto {
namespace {

struct Applet {
  using MainFunction = int (*)(int /*argc*/, char** /*argv*/);
  const char* name;
  MainFunction entrypoint;
};

const Applet g_applets[]{
    {"traced", ServiceMain},
    {"traced_probes", ProbesMain},
    {"perfetto", PerfettoCmdMain},
    {"trigger_perfetto", TriggerPerfettoMain},
    {"websocket_bridge", WebsocketBridgeMain},
};

void PrintUsage() {
  printf(R"(Welcome to Perfetto tracing!

Tracebox is a bundle containing all the tracing services and the perfetto
cmdline client in one binary. It can be used either to spawn manually the
various subprocess or in "autostart" mode, which will take care of starting
and tearing down the services for you.

Usage in autostart mode:
  tracebox -t 10s -o trace_file.perfetto-trace sched/sched_switch
  See tracebox --help for more options.

Usage in manual mode:
  tracebox applet_name [args ...]  (e.g. ./tracebox traced --help)
  Applets:)");

  for (const Applet& applet : g_applets)
    printf(" %s", applet.name);

  printf(R"(

See also:
  * https://perfetto.dev/docs/
  * The config editor in the record page of https://ui.perfetto.dev/
)");
}

int TraceboxMain(int argc, char** argv) {
  // Manual mode: if either the 1st argument (argv[1]) or the exe name (argv[0])
  // match the name of an applet, directly invoke that without further
  // modifications.

  // Extract the file name from argv[0].
  char* slash = strrchr(argv[0], '/');
  char* argv0 = slash ? slash + 1 : argv[0];

  for (const Applet& applet : g_applets) {
    if (!strcmp(argv0, applet.name))
      return applet.entrypoint(argc, argv);
    if (argc > 1 && !strcmp(argv[1], applet.name))
      return applet.entrypoint(argc - 1, &argv[1]);
  }

  // If no matching applet is found, switch to the autostart mode. In this mode
  // we make tracebox behave like the cmdline client (without needing to prefix
  // it with "perfetto"), but will also start traced and traced_probes.
  // As part of this we also use a different namespace for the producer/consumer
  // sockets, to avoid clashing with the system daemon.

  if (argc <= 1) {
    PrintUsage();
    return 1;
  }

  auto pid_str = std::to_string(static_cast<uint64_t>(base::GetProcessId()));
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  // Use an unlinked abstract domain socket on Linux/Android.
  std::string consumer_socket = "@traced-c-" + pid_str;
  std::string producer_socket = "@traced-p-" + pid_str;
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
  std::string consumer_socket = "/tmp/traced-c-" + pid_str;
  std::string producer_socket = "/tmp/traced-p-" + pid_str;
#else
  PERFETTO_FATAL("The autostart mode is not supported on this platform");
#endif

  // If the caller has set the PERFETTO_*_SOCK_NAME, respect those.
  const char* env;
  if ((env = getenv("PERFETTO_CONSUMER_SOCK_NAME")))
    consumer_socket = env;
  if ((env = getenv("PERFETTO_PRODUCER_SOCK_NAME")))
    producer_socket = env;

  base::SetEnv("PERFETTO_CONSUMER_SOCK_NAME", consumer_socket);
  base::SetEnv("PERFETTO_PRODUCER_SOCK_NAME", producer_socket);

  PerfettoCmd perfetto_cmd;

  // If the cmdline parsing fails, stop here, no need to spawn services.
  // It will daemonize if --background. In that case the subprocesses will be
  // spawned by the damonized cmdline client, which is what we want so killing
  // the backgrounded cmdline client will also kill the other services, as they
  // will live in the same background session.
  auto opt_res = perfetto_cmd.ParseCmdlineAndMaybeDaemonize(argc, argv);
  if (opt_res.has_value())
    return *opt_res;

  std::string self_path = base::GetCurExecutablePath();
  base::Subprocess traced({self_path, "traced"});
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // |traced_sync_pipe| is used to synchronize with traced socket creation.
  // traced will write "1" and close the FD when the IPC socket is listening
  // (or traced crashed).
  base::Pipe traced_sync_pipe = base::Pipe::Create();
  int traced_fd = *traced_sync_pipe.wr;
  base::SetEnv("TRACED_NOTIFY_FD", std::to_string(traced_fd));
  traced.args.preserve_fds.emplace_back(traced_fd);
  // Create a new process group so CTRL-C is delivered only to the cmdline
  // process (the tracebox one) and not to traced. traced will still exit once
  // the main process exits, but this allows graceful stopping of the trace
  // without abruptedly killing traced{,probes} when hitting CTRL+C.
  traced.args.posix_proc_group_id = 0;  // 0 = start a new process group.
#endif
  traced.Start();

#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  traced_sync_pipe.wr.reset();

  std::string traced_notify_msg;
  base::ReadPlatformHandle(*traced_sync_pipe.rd, &traced_notify_msg);
  if (traced_notify_msg != "1")
    PERFETTO_FATAL("The tracing service failed unexpectedly. Check the logs");
#endif

  base::Subprocess traced_probes(
      {self_path, "traced_probes", "--reset-ftrace"});
  // Put traced_probes in the same process group as traced. Same reason (CTRL+C)
  // but it's not worth creating a new group.
  traced_probes.args.posix_proc_group_id = traced.pid();
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // |traced_probes_sync_pipe| is used to synchronize with traced socket
  // creation. traced will write "1" and close the FD when the IPC socket is
  // listening (or traced crashed).
  base::Pipe traced_probes_sync_pipe = base::Pipe::Create();
  int traced_probes_fd = *traced_probes_sync_pipe.wr;
  base::SetEnv("TRACED_PROBES_NOTIFY_FD", std::to_string(traced_probes_fd));
  traced_probes.args.preserve_fds.emplace_back(traced_probes_fd);
#endif
  traced_probes.Start();

#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  traced_probes_sync_pipe.wr.reset();

  std::string traced_probes_notify_msg;
  base::ReadPlatformHandle(*traced_probes_sync_pipe.rd,
                           &traced_probes_notify_msg);
  if (traced_probes_notify_msg != "1")
    PERFETTO_FATAL(
        "The traced_probes service failed unexpectedly. Check the logs");
#endif

  perfetto_cmd.ConnectToServiceRunAndMaybeNotify();
  return 0;
}

}  // namespace
}  // namespace perfetto

int main(int argc, char** argv) {
  return perfetto::TraceboxMain(argc, argv);
}
<|endoftext|>


<commit_before><commit_msg>statically assert that ODBC uses UTF-16<commit_after><|endoftext|>


<commit_before>// Standard tutorial macro for performing an inverted  hypothesis test
//
// This macro will perform a scan of tehe p-values for computing the limit
//

#include "TFile.h"
#include "RooWorkspace.h"
#include "RooAbsPdf.h"
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooStats/ModelConfig.h"
#include "TGraphErrors.h"
#include "TGraphAsymmErrors.h"
#include "TCanvas.h"
#include "TLine.h"

#include "RooStats/HybridCalculator.h"
#include "RooStats/FrequentistCalculator.h"
#include "RooStats/ToyMCSampler.h"
#include "RooStats/HypoTestPlot.h"

#include "RooStats/NumEventsTestStat.h"
#include "RooStats/ProfileLikelihoodTestStat.h"
#include "RooStats/SimpleLikelihoodRatioTestStat.h"
#include "RooStats/RatioOfProfiledLikelihoodsTestStat.h"
#include "RooStats/MaxLikelihoodEstimateTestStat.h"

#include "RooStats/HypoTestInverter.h"
#include "RooStats/HypoTestInverterResult.h"
#include "RooStats/HypoTestInverterPlot.h"

using namespace RooFit;
using namespace RooStats;

bool plotHypoTestResult = true;
bool useProof = true;
bool optimize = false;
bool writeResult = false;
int nworkers = 2;

// internal routine to run the inverter
HypoTestInverterResult * RunInverter(RooWorkspace * w, const char * modelSBName, const char * modelBName, const char * dataName,
                                     int type,  int testStatType, int npoints, double poimin, double poimax, int ntoys,
                                     bool useCls, bool useNumberCounting, const char * nuisPriorName);

void StandardHypoTestInvDemo(const char * fileName =0,
                             const char * wsName = "combined",
                             const char * modelSBName = "ModelConfig",
                             const char * modelBName = "",
                             const char * dataName = "obsData",
                             int calculatorType = 0,
                             int testStatType = 3,
                             bool useCls = true ,
                             int npoints = 5,
                             double poimin = 0,
                             double poimax = 5,
                             int ntoys=1000,
                             bool useNumberCounting = false,
                             const char * nuisPriorName = 0)
{
/*

   Other Parameter to pass in tutorial
   apart from standard for filename, ws, modelconfig and data

    type = 0 Freq calculator
    type = 1 Hybrid

    testStatType = 0 LEP
                 = 1 Tevatron
                 = 2 Profile Likelihood
                 = 3 Profile Likelihood one sided (i.e. = 0 if mu < mu_hat)

    useCLs          scan for CLs (otherwise for CLs+b)

    npoints:        number of points to scan , for autoscan set npoints = -1

    poimin,poimax:  min/max value to scan in case of fixed scans
                    (if min >= max, try to find automatically)

    ntoys:         number of toys to use

    useNumberCounting:  set to true when using number counting events

    nuisPriorName:   name of prior for the nnuisance. This is often expressed as constraint term in the global model
                     It is needed only when using the HybridCalculator (type=1)
                     If not given by default the prior pdf from ModelConfig is used.

    extra options are available as global paramters of the macro. They are:

    plotHypoTestResult   plot result of tests at each point (TS distributions)
    useProof = true;
    writeResult = true;
    nworkers = 4;

   */

   if (fileName==0) {
      fileName = "results/example_combined_GaussExample_model.root";
      std::cout << "Use standard file generated with HistFactory :" << fileName << std::endl;
   }
   TFile * file = new TFile(fileName);

   RooWorkspace * w = dynamic_cast<RooWorkspace*>( file->Get(wsName) );
   HypoTestInverterResult * r = 0;
   std::cout << w << "\t" << fileName << std::endl;
   if (w != NULL) {
      r = RunInverter(w, modelSBName, modelBName, dataName, calculatorType, testStatType, npoints, poimin, poimax,
                      ntoys, useCls, useNumberCounting, nuisPriorName );
      if (!r) {
         std::cerr << "Error running the HypoTestInverter - Exit " << std::endl;
         return;
      }
   }
   else
   {
      // case workspace is not present look for the inverter result
      std::cout << "Reading an HypoTestInverterResult with name " << wsName << " from file " << fileName << std::endl;
      r = dynamic_cast<HypoTestInverterResult*>( file->Get(wsName) ); //
      if (!r) {
         std::cerr << "File " << fileName << " does not contain a workspace or an HypoTestInverterResult - Exit "
                   << std::endl;
         file->ls();
         return;
      }
   }

   double upperLimit = r->UpperLimit();
   double ulError = r->UpperLimitEstimatedError();

   std::cout << "The computed upper limit is: " << upperLimit << " +/- " << ulError << std::endl;

   const int nEntries = r->ArraySize();

   const char *  typeName = (calculatorType == 0) ? "Frequentist" : "Hybrid";
   const char * resultName = (w) ? w->GetName() : r->GetName();
   TString plotTitle = TString::Format("%s CL Scan for workspace %s",typeName,resultName);
   HypoTestInverterPlot *plot = new HypoTestInverterPlot("HTI_Result_Plot",plotTitle,r);
   plot->Draw("CLb 2CL");  // plot all and Clb

   if (plotHypoTestResult) {
      TCanvas * c2 = new TCanvas();
      c2->Divide( 2, TMath::Ceil(nEntries/2));
      for (int i=0; i<nEntries; i++) {
         c2->cd(i+1);
         SamplingDistPlot * pl = plot->MakeTestStatPlot(i);
         pl->SetLogYaxis(true);
         pl->Draw();
      }
   }

   std::cout << " expected limit (median) " <<  r->GetExpectedUpperLimit(0) << std::endl;
   std::cout << " expected limit (-1 sig) " << r->GetExpectedUpperLimit(-1) << std::endl;
   std::cout << " expected limit (+1 sig) " << r->GetExpectedUpperLimit(1) << std::endl;

   if (w != NULL && writeResult) {

      // write to a file the results
      const char *  calcType = (calculatorType == 0) ? "Freq" : "Hybr";
      const char *  limitType = (useCls) ? "CLs" : "Cls+b";
      const char * scanType = (npoints < 0) ? "auto" : "grid";
      TString resultFileName = TString::Format("%s_%s_%s_ts%d_",calcType,limitType,scanType,testStatType);
      resultFileName += fileName;

      TFile * fileOut = new TFile(resultFileName,"RECREATE");
      r->Write();
      fileOut->Close();
   }

}

// internal routine to run the inverter
HypoTestInverterResult *  RunInverter(RooWorkspace * w, const char * modelSBName, const char * modelBName,
                                      const char * dataName, int type,  int testStatType,
                                      int npoints, double poimin, double poimax,
                                      int ntoys, bool useCls, bool useNumberCounting, const char * nuisPriorName )
{

   std::cout << "Running HypoTestInverter on the workspace " << w->GetName() << std::endl;

   w->Print();

   RooAbsData * data = w->data(dataName);
   if (!data) {
      Error("StandardHypoTestDemo","Not existing data %s",dataName);
      return 0;
   }
   else
      std::cout << "Using data set " << dataName << std::endl;

   // get models from WS
   // get the modelConfig out of the file
   ModelConfig* bModel = (ModelConfig*) w->obj(modelBName);
   ModelConfig* sbModel = (ModelConfig*) w->obj(modelSBName);

   if (!sbModel) {
      Error("StandardHypoTestDemo","Not existing ModelConfig %s",modelSBName);
      return 0;
   }
   // check the model
   if (!sbModel->GetPdf()) {
      Error("StandardHypoTestDemo","Model %s has no pdf ",modelSBName);
      return 0;
   }
   if (!sbModel->GetParametersOfInterest()) {
      Error("StandardHypoTestDemo","Model %s has no poi ",modelSBName);
      return 0;
   }
   if (!sbModel->GetParametersOfInterest()) {
      Error("StandardHypoTestInvDemo","Model %s has no poi ",modelSBName);
      return 0;
   }
   if (!sbModel->GetSnapshot() ) {
      Info("StandardHypoTestInvDemo","Model %s has no snapshot  - make one using model poi",modelSBName);
      sbModel->SetSnapshot( *sbModel->GetParametersOfInterest() );
   }

   if (!bModel || bModel == sbModel) {
      Info("StandardHypoTestInvDemo","The background model %s does not exist",modelBName);
      Info("StandardHypoTestInvDemo","Copy it from ModelConfig %s and set POI to zero",modelSBName);
      bModel = (ModelConfig*) sbModel->Clone();
      bModel->SetName(TString(modelSBName)+TString("_with_poi_0"));
      RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first());
      if (!var) return 0;
      double oldval = var->getVal();
      var->setVal(0);
      bModel->SetSnapshot( RooArgSet(*var)  );
      var->setVal(oldval);
   }
   else {
      if (!bModel->GetSnapshot() ) {
         Info("StandardHypoTestInvDemo","Model %s has no snapshot  - make one using model poi and 0 values ",modelBName);
         RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first());
         if (var) {
            double oldval = var->getVal();
            var->setVal(0);
            bModel->SetSnapshot( RooArgSet(*var)  );
            var->setVal(oldval);
         }
         else {
            Error("StandardHypoTestInvDemo","Model %s has no valid poi",modelBName);
            return 0;
         }
      }
   }

   SimpleLikelihoodRatioTestStat slrts(*sbModel->GetPdf(),*bModel->GetPdf());
   if (sbModel->GetSnapshot()) slrts.SetNullParameters(*sbModel->GetSnapshot());
   if (bModel->GetSnapshot()) slrts.SetAltParameters(*bModel->GetSnapshot());

   // ratio of profile likelihood - need to pass snapshot for the alt
   RatioOfProfiledLikelihoodsTestStat
      ropl(*sbModel->GetPdf(), *bModel->GetPdf(), bModel->GetSnapshot());
   ropl.SetSubtractMLE(false);

   ProfileLikelihoodTestStat profll(*sbModel->GetPdf());
   if (testStatType == 3) profll.SetOneSided(1);
   if (optimize) profll.SetReuseNLL(true);

   TestStatistic * testStat = &slrts;
   if (testStatType == 1) testStat = &ropl;
   if (testStatType == 2 || testStatType == 3) testStat = &profll;

   HypoTestCalculatorGeneric *  hc = 0;
   if (type == 0) hc = new FrequentistCalculator(*data, *bModel, *sbModel);
   else hc = new HybridCalculator(*data, *bModel, *sbModel);

   ToyMCSampler *toymcs = (ToyMCSampler*)hc->GetTestStatSampler();
   if (useNumberCounting) toymcs->SetNEventsPerToy(1);
   toymcs->SetTestStatistic(testStat);
   if (optimize) toymcs->SetUseMultiGen(true);

   if (type == 1) {
      HybridCalculator *hhc = (HybridCalculator*) hc;
      hhc->SetToys(ntoys,ntoys);

      // check for nuisance prior pdf in case of nuisance parameters
      if (bModel->GetNuisanceParameters() || sbModel->GetNuisanceParameters() ) {
         RooAbsPdf * nuisPdf = 0;
         if (nuisPriorName) nuisPdf = w->pdf(nuisPriorName);
         // use prior defined first in bModel (then in SbModel)
         if (!nuisPdf)  {
            Info("StandardHypoTestInvDemo","No nuisance pdf given for the HybridCalculator - try to use the prior pdf from the model");
            nuisPdf = (bModel->GetPriorPdf() ) ?  bModel->GetPriorPdf() : sbModel->GetPriorPdf();
         }
         if (!nuisPdf) {
            Error("StandardHypoTestInvDemo","Cannnot run Hybrid calculator because no prior on the nuisance parameter is specified");
            return 0;
         }
         const RooArgSet * nuisParams = (bModel->GetNuisanceParameters() ) ? bModel->GetNuisanceParameters() : sbModel->GetNuisanceParameters();
         RooArgSet * np = nuisPdf->getObservables(*nuisParams);
         if (np->getSize() == 0) {
            Warning("StandardHypoTestInvDemo","Prior nuisance does not depend on nuisance parameters. They will be smeared in their full range");
         }
         delete np;
         hhc->ForcePriorNuisanceAlt(*nuisPdf);
         hhc->ForcePriorNuisanceNull(*nuisPdf);
      }
   }
   else
      ((FrequentistCalculator*) hc)->SetToys(ntoys,ntoys);

   // Get the result
   RooMsgService::instance().getStream(1).removeTopic(RooFit::NumIntegration);

   TStopwatch tw; tw.Start();
   const RooArgSet * poiSet = sbModel->GetParametersOfInterest();
   RooRealVar *poi = (RooRealVar*)poiSet->first();

   // fit the data first
   sbModel->GetPdf()->fitTo(*data);
   double poihat  = poi->getVal();

   HypoTestInverter calc(*hc);
   calc.SetConfidenceLevel(0.95);

   calc.UseCLs(useCls);
   calc.SetVerbose(true);

   // can speed up using proof-lite
   if (useProof && nworkers > 1) {
      ProofConfig pc(*w, nworkers, "", kFALSE);
      toymcs->SetProofConfig(&pc);    // enable proof
   }

   if (npoints > 0) {
      if (poimin >= poimax) {
         // if no min/max given scan between MLE and +4 sigma
         poimin = int(poihat);
         poimax = int(poihat +  4 * poi->getError());
      }
      std::cout << "Doing a fixed scan  in interval : " << poimin << " , " << poimax << std::endl;
      calc.SetFixedScan(npoints,poimin,poimax);
   }
   else {
      //poi->setMax(10*int( (poihat+ 10 *poi->getError() )/10 ) );
      std::cout << "Doing an  automatic scan  in interval : " << poi->getMin() << " , " << poi->getMax() << std::endl;
   }

   HypoTestInverterResult * r = calc.GetInterval();

   return r;
}

void ReadResult(const char * fileName, const char * resultName="", bool useCLs=true) {
   // read a previous stored result from a file given the result name

   StandardHypoTestInvDemo(fileName, resultName,"","","",0,0,useCLs);
}

int main() {
   StandardHypoTestInvDemo();
}
<commit_msg>add rebuild option for expected limit and bands<commit_after>// Standard tutorial macro for performing an inverted  hypothesis test
//
// This macro will perform a scan of tehe p-values for computing the limit
//

#include "TFile.h"
#include "RooWorkspace.h"
#include "RooAbsPdf.h"
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooStats/ModelConfig.h"
#include "TGraphErrors.h"
#include "TGraphAsymmErrors.h"
#include "TCanvas.h"
#include "TLine.h"

#include "RooStats/HybridCalculator.h"
#include "RooStats/FrequentistCalculator.h"
#include "RooStats/ToyMCSampler.h"
#include "RooStats/HypoTestPlot.h"

#include "RooStats/NumEventsTestStat.h"
#include "RooStats/ProfileLikelihoodTestStat.h"
#include "RooStats/SimpleLikelihoodRatioTestStat.h"
#include "RooStats/RatioOfProfiledLikelihoodsTestStat.h"
#include "RooStats/MaxLikelihoodEstimateTestStat.h"

#include "RooStats/HypoTestInverter.h"
#include "RooStats/HypoTestInverterResult.h"
#include "RooStats/HypoTestInverterPlot.h"

using namespace RooFit;
using namespace RooStats;

bool plotHypoTestResult = true;
bool useProof = true;
bool optimize = false;
bool writeResult = false;
int nworkers = 4;
bool rebuild = false;
int nToyToRebuild = 100;

// internal routine to run the inverter
HypoTestInverterResult * RunInverter(RooWorkspace * w, const char * modelSBName, const char * modelBName, const char * dataName,
                                     int type,  int testStatType, int npoints, double poimin, double poimax, int ntoys,
                                     bool useCls, bool useNumberCounting, const char * nuisPriorName);

void StandardHypoTestInvDemo(const char * fileName =0,
                             const char * wsName = "combined",
                             const char * modelSBName = "ModelConfig",
                             const char * modelBName = "",
                             const char * dataName = "obsData",
                             int calculatorType = 0,
                             int testStatType = 3,
                             bool useCls = true ,
                             int npoints = 5,
                             double poimin = 0,
                             double poimax = 5,
                             int ntoys=1000,
                             bool useNumberCounting = false,
                             const char * nuisPriorName = 0)
{
/*

   Other Parameter to pass in tutorial
   apart from standard for filename, ws, modelconfig and data

    type = 0 Freq calculator
    type = 1 Hybrid

    testStatType = 0 LEP
                 = 1 Tevatron
                 = 2 Profile Likelihood
                 = 3 Profile Likelihood one sided (i.e. = 0 if mu < mu_hat)

    useCLs          scan for CLs (otherwise for CLs+b)

    npoints:        number of points to scan , for autoscan set npoints = -1

    poimin,poimax:  min/max value to scan in case of fixed scans
                    (if min >= max, try to find automatically)

    ntoys:         number of toys to use

    useNumberCounting:  set to true when using number counting events

    nuisPriorName:   name of prior for the nnuisance. This is often expressed as constraint term in the global model
                     It is needed only when using the HybridCalculator (type=1)
                     If not given by default the prior pdf from ModelConfig is used.

    extra options are available as global paramters of the macro. They are:

    plotHypoTestResult   plot result of tests at each point (TS distributions)
    useProof = true;
    writeResult = true;
    nworkers = 4;

   */

   if (fileName==0) {
      fileName = "results/example_combined_GaussExample_model.root";
      std::cout << "Use standard file generated with HistFactory :" << fileName << std::endl;
   }
   TFile * file = new TFile(fileName);

   RooWorkspace * w = dynamic_cast<RooWorkspace*>( file->Get(wsName) );
   HypoTestInverterResult * r = 0;
   std::cout << w << "\t" << fileName << std::endl;
   if (w != NULL) {
      r = RunInverter(w, modelSBName, modelBName, dataName, calculatorType, testStatType, npoints, poimin, poimax,
                      ntoys, useCls, useNumberCounting, nuisPriorName );
      if (!r) {
         std::cerr << "Error running the HypoTestInverter - Exit " << std::endl;
         return;
      }
   }
   else
   {
      // case workspace is not present look for the inverter result
      std::cout << "Reading an HypoTestInverterResult with name " << wsName << " from file " << fileName << std::endl;
      r = dynamic_cast<HypoTestInverterResult*>( file->Get(wsName) ); //
      if (!r) {
         std::cerr << "File " << fileName << " does not contain a workspace or an HypoTestInverterResult - Exit "
                   << std::endl;
         file->ls();
         return;
      }
   }

   double upperLimit = r->UpperLimit();
   double ulError = r->UpperLimitEstimatedError();

   std::cout << "The computed upper limit is: " << upperLimit << " +/- " << ulError << std::endl;

   const int nEntries = r->ArraySize();

   const char *  typeName = (calculatorType == 0) ? "Frequentist" : "Hybrid";
   const char * resultName = (w) ? w->GetName() : r->GetName();
   TString plotTitle = TString::Format("%s CL Scan for workspace %s",typeName,resultName);
   HypoTestInverterPlot *plot = new HypoTestInverterPlot("HTI_Result_Plot",plotTitle,r);
   plot->Draw("CLb 2CL");  // plot all and Clb

   if (plotHypoTestResult) {
      TCanvas * c2 = new TCanvas();
      c2->Divide( 2, TMath::Ceil(nEntries/2));
      for (int i=0; i<nEntries; i++) {
         c2->cd(i+1);
         SamplingDistPlot * pl = plot->MakeTestStatPlot(i);
         pl->SetLogYaxis(true);
         pl->Draw();
      }
   }

   std::cout << " expected limit (median) " <<  r->GetExpectedUpperLimit(0) << std::endl;
   std::cout << " expected limit (-1 sig) " << r->GetExpectedUpperLimit(-1) << std::endl;
   std::cout << " expected limit (+1 sig) " << r->GetExpectedUpperLimit(1) << std::endl;

   if (w != NULL && writeResult) {

      // write to a file the results
      const char *  calcType = (calculatorType == 0) ? "Freq" : "Hybr";
      const char *  limitType = (useCls) ? "CLs" : "Cls+b";
      const char * scanType = (npoints < 0) ? "auto" : "grid";
      TString resultFileName = TString::Format("%s_%s_%s_ts%d_",calcType,limitType,scanType,testStatType);
      resultFileName += fileName;

      TFile * fileOut = new TFile(resultFileName,"RECREATE");
      r->Write();
      fileOut->Close();
   }

}

// internal routine to run the inverter
HypoTestInverterResult *  RunInverter(RooWorkspace * w, const char * modelSBName, const char * modelBName,
                                      const char * dataName, int type,  int testStatType,
                                      int npoints, double poimin, double poimax,
                                      int ntoys, bool useCls, bool useNumberCounting, const char * nuisPriorName )
{

   std::cout << "Running HypoTestInverter on the workspace " << w->GetName() << std::endl;

   w->Print();

   RooAbsData * data = w->data(dataName);
   if (!data) {
      Error("StandardHypoTestDemo","Not existing data %s",dataName);
      return 0;
   }
   else
      std::cout << "Using data set " << dataName << std::endl;

   // get models from WS
   // get the modelConfig out of the file
   ModelConfig* bModel = (ModelConfig*) w->obj(modelBName);
   ModelConfig* sbModel = (ModelConfig*) w->obj(modelSBName);

   if (!sbModel) {
      Error("StandardHypoTestDemo","Not existing ModelConfig %s",modelSBName);
      return 0;
   }
   // check the model
   if (!sbModel->GetPdf()) {
      Error("StandardHypoTestDemo","Model %s has no pdf ",modelSBName);
      return 0;
   }
   if (!sbModel->GetParametersOfInterest()) {
      Error("StandardHypoTestDemo","Model %s has no poi ",modelSBName);
      return 0;
   }
   if (!sbModel->GetParametersOfInterest()) {
      Error("StandardHypoTestInvDemo","Model %s has no poi ",modelSBName);
      return 0;
   }
   if (!sbModel->GetSnapshot() ) {
      Info("StandardHypoTestInvDemo","Model %s has no snapshot  - make one using model poi",modelSBName);
      sbModel->SetSnapshot( *sbModel->GetParametersOfInterest() );
   }

   if (!bModel || bModel == sbModel) {
      Info("StandardHypoTestInvDemo","The background model %s does not exist",modelBName);
      Info("StandardHypoTestInvDemo","Copy it from ModelConfig %s and set POI to zero",modelSBName);
      bModel = (ModelConfig*) sbModel->Clone();
      bModel->SetName(TString(modelSBName)+TString("_with_poi_0"));
      RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first());
      if (!var) return 0;
      double oldval = var->getVal();
      var->setVal(0);
      bModel->SetSnapshot( RooArgSet(*var)  );
      var->setVal(oldval);
   }
   else {
      if (!bModel->GetSnapshot() ) {
         Info("StandardHypoTestInvDemo","Model %s has no snapshot  - make one using model poi and 0 values ",modelBName);
         RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first());
         if (var) {
            double oldval = var->getVal();
            var->setVal(0);
            bModel->SetSnapshot( RooArgSet(*var)  );
            var->setVal(oldval);
         }
         else {
            Error("StandardHypoTestInvDemo","Model %s has no valid poi",modelBName);
            return 0;
         }
      }
   }

   SimpleLikelihoodRatioTestStat slrts(*sbModel->GetPdf(),*bModel->GetPdf());
   if (sbModel->GetSnapshot()) slrts.SetNullParameters(*sbModel->GetSnapshot());
   if (bModel->GetSnapshot()) slrts.SetAltParameters(*bModel->GetSnapshot());

   // ratio of profile likelihood - need to pass snapshot for the alt
   RatioOfProfiledLikelihoodsTestStat
      ropl(*sbModel->GetPdf(), *bModel->GetPdf(), bModel->GetSnapshot());
   ropl.SetSubtractMLE(false);

   ProfileLikelihoodTestStat profll(*sbModel->GetPdf());
   if (testStatType == 3) profll.SetOneSided(1);
   if (optimize) profll.SetReuseNLL(true);

   TestStatistic * testStat = &slrts;
   if (testStatType == 1) testStat = &ropl;
   if (testStatType == 2 || testStatType == 3) testStat = &profll;

   HypoTestCalculatorGeneric *  hc = 0;
   if (type == 0) hc = new FrequentistCalculator(*data, *bModel, *sbModel);
   else hc = new HybridCalculator(*data, *bModel, *sbModel);

   ToyMCSampler *toymcs = (ToyMCSampler*)hc->GetTestStatSampler();
   if (useNumberCounting) toymcs->SetNEventsPerToy(1);
   toymcs->SetTestStatistic(testStat);
   if (optimize) toymcs->SetUseMultiGen(true);

   if (type == 1) {
      HybridCalculator *hhc = (HybridCalculator*) hc;
      hhc->SetToys(ntoys,ntoys);

      // check for nuisance prior pdf in case of nuisance parameters
      if (bModel->GetNuisanceParameters() || sbModel->GetNuisanceParameters() ) {
         RooAbsPdf * nuisPdf = 0;
         if (nuisPriorName) nuisPdf = w->pdf(nuisPriorName);
         // use prior defined first in bModel (then in SbModel)
         if (!nuisPdf)  {
            Info("StandardHypoTestInvDemo","No nuisance pdf given for the HybridCalculator - try to use the prior pdf from the model");
            nuisPdf = (bModel->GetPriorPdf() ) ?  bModel->GetPriorPdf() : sbModel->GetPriorPdf();
         }
         if (!nuisPdf) {
            Error("StandardHypoTestInvDemo","Cannnot run Hybrid calculator because no prior on the nuisance parameter is specified");
            return 0;
         }
         const RooArgSet * nuisParams = (bModel->GetNuisanceParameters() ) ? bModel->GetNuisanceParameters() : sbModel->GetNuisanceParameters();
         RooArgSet * np = nuisPdf->getObservables(*nuisParams);
         if (np->getSize() == 0) {
            Warning("StandardHypoTestInvDemo","Prior nuisance does not depend on nuisance parameters. They will be smeared in their full range");
         }
         delete np;
         hhc->ForcePriorNuisanceAlt(*nuisPdf);
         hhc->ForcePriorNuisanceNull(*nuisPdf);
      }
   }
   else
      ((FrequentistCalculator*) hc)->SetToys(ntoys,ntoys);

   // Get the result
   RooMsgService::instance().getStream(1).removeTopic(RooFit::NumIntegration);

   TStopwatch tw; tw.Start();
   const RooArgSet * poiSet = sbModel->GetParametersOfInterest();
   RooRealVar *poi = (RooRealVar*)poiSet->first();

   // fit the data first
   sbModel->GetPdf()->fitTo(*data);
   double poihat  = poi->getVal();

   HypoTestInverter calc(*hc);
   calc.SetConfidenceLevel(0.95);

   calc.UseCLs(useCls);
   calc.SetVerbose(true);

   // can speed up using proof-lite
   if (useProof && nworkers > 1) {
      ProofConfig pc(*w, nworkers, "", kFALSE);
      toymcs->SetProofConfig(&pc);    // enable proof
   }

   if (npoints > 0) {
      if (poimin >= poimax) {
         // if no min/max given scan between MLE and +4 sigma
         poimin = int(poihat);
         poimax = int(poihat +  4 * poi->getError());
      }
      std::cout << "Doing a fixed scan  in interval : " << poimin << " , " << poimax << std::endl;
      calc.SetFixedScan(npoints,poimin,poimax);
   }
   else {
      //poi->setMax(10*int( (poihat+ 10 *poi->getError() )/10 ) );
      std::cout << "Doing an  automatic scan  in interval : " << poi->getMin() << " , " << poi->getMax() << std::endl;
   }

   HypoTestInverterResult * r = calc.GetInterval();

   if (rebuild) {
      calc.SetCloseProof(1);
      SamplingDistribution * limDist = calc.GetUpperLimitDistribution(true,nToyToRebuild);
      if (limDist) {
         std::cout << "expected up limit " << limDist->InverseCDF(0.5) << " +/- "
                   << limDist->InverseCDF(0.16) << "  "
                   << limDist->InverseCDF(0.84) << "\n";
      }
      else
         std::cout << "ERROR : failed to re-build distributions " << std::endl;
   }

   //update r to a new re-freshed copied
   r = calc.GetInterval();

   return r;
}

void ReadResult(const char * fileName, const char * resultName="", bool useCLs=true) {
   // read a previous stored result from a file given the result name

   StandardHypoTestInvDemo(fileName, resultName,"","","",0,0,useCLs);
}

int main() {
   StandardHypoTestInvDemo();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016-2017, Loic Blot <loic.blot@unix-experience.fr>
 * 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "ratpclient.h"
#include <algorithm>
#include <cassert>
#include <iostream>

namespace winterwind
{
namespace extras
{

static const std::string url_rer = "https://www.ratp.fr/horaires?networks=rer&line_busratp=&name_line_busratp=&id_line_busratp=&line_noctilien=&name_line_noctilien=&id_line_noctilien=&type=now&op=Rechercher&stop_point_rer=";
static const std::string xpath_rer = "/html/body/div[1]/main/div[1]/div/div[1]/div[1]/div/div/div/div[4]/div[3]/ul/li/span[position() = 2 or position() = 3]";

static const RATPScheduleList EMPTY_SCHEDULE_LIST = {};
static constexpr uint32_t RATP_CACHE_TIME = 60;

const RATPScheduleList &RATPClient::get_next_trains(const RATPClient::Line line,
	const std::string &stop,
	const uint8_t direction)
{
	assert(line < RATP_LINE_MAX);
	assert(direction > 0 && direction < 3);

	if (m_stop_cache.find(line) == m_stop_cache.end()) {
		m_stop_cache[line] = RATPStopMap();
	}

	const auto stop_itr = m_stop_cache[line].find(stop);
	if (stop_itr != m_stop_cache[line].end()) {
		if (time(NULL) - stop_itr->second.entry_time < RATP_CACHE_TIME) {
			return stop_itr->second.schedules;
		}
	}

	std::string html_stop = stop;
	std::replace(html_stop.begin(), html_stop.end(), ' ', '+');
	std::string url = url_rer + html_stop + "&line_rer=";
	if (line == LINE_RER_A) {
		url += "A";
	}
	else if (line == LINE_RER_B) {
		url += "B";
	}

	std::vector<std::string> res;
	get_html_tag_value(url, xpath_rer, res, XMLParser::Flag::FLAG_XML_WITHOUT_TAGS);
	if (res.size() == 0) {
		return EMPTY_SCHEDULE_LIST;
	}

	if (stop_itr == m_stop_cache[line].end()) {
		m_stop_cache[line][stop] = RATPStop();
		m_stop_cache[line][stop].train_stop = stop;
	}

	m_stop_cache[line][stop].entry_time = time(NULL);
	m_stop_cache[line][stop].schedules = {};

	RATPSchedule tmp_schedule;
	uint16_t offset = 0;
	// We do explicit copy because we remove spaces
	for (std::string s : res) {
		s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
		s.erase(std::remove(s.begin(), s.end(), '\n'), s.end());
		if (offset % 2 == 0) {
			tmp_schedule = {};
			tmp_schedule.destination = s;
		} else {
			tmp_schedule.hour = s;
			m_stop_cache[line][stop].schedules.push_back(tmp_schedule);
			std::cout << tmp_schedule.destination << ": " << tmp_schedule.hour << std::endl;
		}

		offset++;
	}

	return m_stop_cache[line][stop].schedules;
}
}
}
<commit_msg>Another RATP client fix<commit_after>/*
 * Copyright (c) 2016-2017, Loic Blot <loic.blot@unix-experience.fr>
 * 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "ratpclient.h"
#include <algorithm>
#include <cassert>
#include <iostream>

namespace winterwind
{
namespace extras
{

static const std::string url_rer = "https://www.ratp.fr/horaires?networks=rer&line_busratp=&name_line_busratp=&id_line_busratp=&line_noctilien=&name_line_noctilien=&id_line_noctilien=&type=now&op=Rechercher&stop_point_rer=";
static const std::string xpath_rer_dir1 = "/html/body/div[1]/main/div[1]/div/div[1]/div[1]/div/div/div/div[4]/div[2]/ul/li/span[position() = 2 or position() = 3]";
static const std::string xpath_rer_dir2 = "/html/body/div[1]/main/div[1]/div/div[1]/div[1]/div/div/div/div[4]/div[3]/ul/li/span[position() = 2 or position() = 3]";

static const RATPScheduleList EMPTY_SCHEDULE_LIST = {};
static constexpr uint32_t RATP_CACHE_TIME = 60;

const RATPScheduleList &RATPClient::get_next_trains(const RATPClient::Line line,
	const std::string &stop,
	const uint8_t direction)
{
	assert(line < RATP_LINE_MAX);
	assert(direction > 0 && direction < 3);

	if (m_stop_cache.find(line) == m_stop_cache.end()) {
		m_stop_cache[line] = RATPStopMap();
	}

	const auto stop_itr = m_stop_cache[line].find(stop);
	if (stop_itr != m_stop_cache[line].end()) {
		if (time(NULL) - stop_itr->second.entry_time < RATP_CACHE_TIME) {
			return stop_itr->second.schedules;
		}
	}

	std::string html_stop = stop;
	std::replace(html_stop.begin(), html_stop.end(), ' ', '+');
	std::string url = url_rer + html_stop + "&line_rer=";
	if (line == LINE_RER_A) {
		url += "A";
	}
	else if (line == LINE_RER_B) {
		url += "B";
	}

	const std::string &xpath_rer = (direction == 1 ? xpath_rer_dir1 : xpath_rer_dir2);
	std::vector<std::string> res;
	get_html_tag_value(url, xpath_rer, res, XMLParser::Flag::FLAG_XML_WITHOUT_TAGS);
	if (res.size() == 0) {
		return EMPTY_SCHEDULE_LIST;
	}

	if (stop_itr == m_stop_cache[line].end()) {
		m_stop_cache[line][stop] = RATPStop();
		m_stop_cache[line][stop].train_stop = stop;
	}

	m_stop_cache[line][stop].entry_time = time(NULL);
	m_stop_cache[line][stop].schedules = {};

	RATPSchedule tmp_schedule;
	uint16_t offset = 0;
	// We do explicit copy because we remove spaces
	for (std::string s : res) {
		s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
		s.erase(std::remove(s.begin(), s.end(), '\n'), s.end());
		if (offset % 2 == 0) {
			tmp_schedule = {};
			tmp_schedule.destination = s;
		} else {
			tmp_schedule.hour = s;
			m_stop_cache[line][stop].schedules.push_back(tmp_schedule);
		}

		offset++;
	}

	return m_stop_cache[line][stop].schedules;
}
}
}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -ast-dump %s | FileCheck %s

template<int N = 0>
void pr43370() {
  int arr[2];
  __atomic_store_n(arr, 0, 0);
}
void useage(){
  pr43370();
}

// CHECK:FunctionTemplateDecl 0x{{[0-9a-f]+}} <{{[^:]+}}:3:1, line:7:1> line:4:6 pr43370
// CHECK: AtomicExpr
// CHECK-NEXT: ImplicitCastExpr
// CHECK-SAME: <ArrayToPointerDecay>
// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <line:4:1, line:7:1> line:4:6 used pr43370
// CHECK: AtomicExpr
// CHECK-NEXT: ImplicitCastExpr
// CHECK-SAME: <ArrayToPointerDecay>
<commit_msg>Fix test atomic-expr.cpp after R372422<commit_after>// RUN: %clang_cc1 -ast-dump %s | FileCheck %s

template<int N = 0>
void pr43370() {
  int arr[2];
  __atomic_store_n(arr, 0, 0);
}
void useage(){
  pr43370();
}

// CHECK:FunctionTemplateDecl 0x{{[0-9a-f]+}} <{{[^,]+}}, line:7:1> line:4:6 pr43370
// CHECK: AtomicExpr
// CHECK-NEXT: ImplicitCastExpr
// CHECK-SAME: <ArrayToPointerDecay>
// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <line:4:1, line:7:1> line:4:6 used pr43370
// CHECK: AtomicExpr
// CHECK-NEXT: ImplicitCastExpr
// CHECK-SAME: <ArrayToPointerDecay>
<|endoftext|>


<commit_before>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER 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 <Object/StringObject.hh>
#include <Object/Value.hh>

namespace Tadpole::Value {

bool Value::is_equal_as_string(Object::StringObject* s) const noexcept {
  return as_string()->is_equal(s);
}

bool Value::is_equal_as_string(const str_t& s) const noexcept {
  return as_string()->is_equal(s);
}

bool Value::is_equal_as_string(strv_t s) const noexcept {
  return as_string()->is_equal(s);
}

bool Value::is_equal_as_string(const char* s) const noexcept {
  return as_string()->is_equal(s);
}

bool Value::operator==(const Value& r) const noexcept { return false; }
bool Value::operator!=(const Value& r) const noexcept { return false; }

bool Value::is_truthy() const {
  switch (type_) {
  case ValueType::NIL: return false;
  case ValueType::BOOLEAN: return as_.boolean;
  case ValueType::NUMERIC: return as_.numeric != 0;
  case ValueType::OBJECT: return as_.object->is_truthy();
  default: break;
  }
  return false;
}

str_t Value::stringify() const {
  switch (type_) {
  case ValueType::NIL: return "nil";
  case ValueType::BOOLEAN: return as_.boolean ? "true" : "false";
  case ValueType::NUMERIC: return Common::as_string(as_.numeric);
  case ValueType::OBJECT: return as_.object->stringify();
  default: break;
  }
  return "<value>";
}

}
<commit_msg>:construction: chore(value): add equal operations for value<commit_after>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER 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 <Object/StringObject.hh>
#include <Object/Value.hh>

namespace Tadpole::Value {

bool Value::is_equal_as_string(Object::StringObject* s) const noexcept {
  return as_string()->is_equal(s);
}

bool Value::is_equal_as_string(const str_t& s) const noexcept {
  return as_string()->is_equal(s);
}

bool Value::is_equal_as_string(strv_t s) const noexcept {
  return as_string()->is_equal(s);
}

bool Value::is_equal_as_string(const char* s) const noexcept {
  return as_string()->is_equal(s);
}

bool Value::operator==(const Value& r) const noexcept {
  if (this == &r)
    return true;
  if (type_ != r.type_)
    return false;

  switch (type_) {
  case ValueType::NIL: return true;
  case ValueType::BOOLEAN: return as_.boolean == r.as_.boolean;
  case ValueType::NUMERIC: return as_.numeric == r.as_.numeric;
  case ValueType::OBJECT: return as_.object->is_equal_to(r.as_.object);
  default:  break;
  }
  return false;
}

bool Value::operator!=(const Value& r) const noexcept { return false; }

bool Value::is_truthy() const {
  switch (type_) {
  case ValueType::NIL: return false;
  case ValueType::BOOLEAN: return as_.boolean;
  case ValueType::NUMERIC: return as_.numeric != 0;
  case ValueType::OBJECT: return as_.object->is_truthy();
  default: break;
  }
  return false;
}

str_t Value::stringify() const {
  switch (type_) {
  case ValueType::NIL: return "nil";
  case ValueType::BOOLEAN: return as_.boolean ? "true" : "false";
  case ValueType::NUMERIC: return Common::as_string(as_.numeric);
  case ValueType::OBJECT: return as_.object->stringify();
  default: break;
  }
  return "<value>";
}

}
<|endoftext|>