<commit_before>#include "GSH_OpenGL.h"
#include <assert.h>
#include <sstream>

static const char* s_andFunction =
"float and(int a, int b)\r\n"
"{\r\n"
"	int r = 0;\r\n"
"	int ha, hb;\r\n"
"	\r\n"
"	int m = int(min(float(a), float(b)));\r\n"
"	\r\n"
"	for(int k = 1; k <= m; k *= 2)\r\n"
"	{\r\n"
"		ha = a / 2;\r\n"
"		hb = b / 2;\r\n"
"		if(((a - ha * 2) != 0) && ((b - hb * 2) != 0))\r\n"
"		{\r\n"
"			r += k;\r\n"
"		}\r\n"
"		a = ha;\r\n"
"		b = hb;\r\n"
"	}\r\n"
"	\r\n"
"	return float(r);\r\n"
"}\r\n";

static const char* s_orFunction =
"float or(int a, int b)\r\n"
"{\r\n"
"	int r = 0;\r\n"
"	int ha, hb;\r\n"
"	\r\n"
"	int m = int(max(float(a), float(b)));\r\n"
"	\r\n"
"	for(int k = 1; k <= m; k *= 2)\r\n"
"	{\r\n"
"		ha = a / 2;\r\n"
"		hb = b / 2;\r\n"
"		if(((a - ha * 2) != 0) || ((b - hb * 2) != 0))\r\n"
"		{\r\n"
"			r += k;\r\n"
"		}\r\n"
"		a = ha;\r\n"
"		b = hb;\r\n"
"	}\r\n"
"	\r\n"
"	return float(r);\r\n"
"}\r\n";

Framework::OpenGl::ProgramPtr CGSH_OpenGL::GenerateShader(const SHADERCAPS& caps)
{
	auto vertexShader = GenerateVertexShader(caps);
	auto fragmentShader = GenerateFragmentShader(caps);

	auto result = std::make_shared<Framework::OpenGl::CProgram>();

	result->AttachShader(vertexShader);
	result->AttachShader(fragmentShader);

	bool linkResult = result->Link();
	assert(linkResult);

	assert(glGetError() == GL_NO_ERROR);

	return result;
}

Framework::OpenGl::CShader CGSH_OpenGL::GenerateVertexShader(const SHADERCAPS& caps)
{
	std::stringstream shaderBuilder;
	shaderBuilder << "void main()"													<< std::endl;
	shaderBuilder << "{"															<< std::endl;
	shaderBuilder << "	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;"	<< std::endl;
	shaderBuilder << "	gl_FrontColor = gl_Color;"									<< std::endl;
	shaderBuilder << "	gl_Position = ftransform();"								<< std::endl;
	shaderBuilder << "	gl_FogFragCoord = gl_FogCoord;"								<< std::endl;
	shaderBuilder << "}"															<< std::endl;

	auto shaderSource = shaderBuilder.str();

	Framework::OpenGl::CShader result(GL_VERTEX_SHADER);
	result.SetSource(shaderSource.c_str(), shaderSource.size());
	bool compilationResult = result.Compile();
	assert(compilationResult);

	assert(glGetError() == GL_NO_ERROR);

	return result;
}

Framework::OpenGl::CShader CGSH_OpenGL::GenerateFragmentShader(const SHADERCAPS& caps)
{
	std::stringstream shaderBuilder;

	//Unused uniforms will get optimized away
	shaderBuilder << "uniform sampler2D g_texture;"															<< std::endl;
	shaderBuilder << "uniform sampler2D g_palette;"															<< std::endl;
	shaderBuilder << "uniform vec2 g_textureSize;"															<< std::endl;
	shaderBuilder << "uniform vec2 g_texelSize;"															<< std::endl;
	shaderBuilder << "uniform vec2 g_clampMin;"																<< std::endl;
	shaderBuilder << "uniform vec2 g_clampMax;"																<< std::endl;

	if(caps.texClampS == TEXTURE_CLAMP_MODE_REGION_REPEAT || caps.texClampT == TEXTURE_CLAMP_MODE_REGION_REPEAT)
	{
		shaderBuilder << s_andFunction << std::endl;
		shaderBuilder << s_orFunction << std::endl;
	}

	shaderBuilder << "void main()"																			<< std::endl;
	shaderBuilder << "{"																					<< std::endl;
	shaderBuilder << "	vec4 texCoord = gl_TexCoord[0];"													<< std::endl;
	shaderBuilder << "	texCoord.st /= texCoord.q;"															<< std::endl;

	if((caps.texClampS != TEXTURE_CLAMP_MODE_STD) || (caps.texClampT != TEXTURE_CLAMP_MODE_STD))
	{
		shaderBuilder << "	texCoord.st *= g_textureSize.st;"													<< std::endl;
		shaderBuilder << GenerateTexCoordClampingSection(static_cast<TEXTURE_CLAMP_MODE>(caps.texClampS), "s");
		shaderBuilder << GenerateTexCoordClampingSection(static_cast<TEXTURE_CLAMP_MODE>(caps.texClampT), "t");
		shaderBuilder << "	texCoord.st /= g_textureSize.st;"													<< std::endl;
	}

	shaderBuilder << "	vec4 textureColor = vec4(1, 1, 1, 1);"												<< std::endl;
	if(caps.isIndexedTextureSource())
	{
		if(!caps.texBilinearFilter)
		{
			shaderBuilder << "	float colorIndex = texture2D(g_texture, texCoord.st).a * 255.0;"				<< std::endl;
			if(caps.texSourceMode == TEXTURE_SOURCE_MODE_IDX4)
			{
				shaderBuilder << "	textureColor = texture2D(g_palette, vec2(colorIndex / 16.0, 1));"			<< std::endl;
			}
			else if(caps.texSourceMode == TEXTURE_SOURCE_MODE_IDX8)
			{
				shaderBuilder << "	textureColor = texture2D(g_palette, vec2(colorIndex / 256.0, 1));"			<< std::endl;
			}
		}
		else
		{
			shaderBuilder << "	float tlIdx = texture2D(g_texture, texCoord.st                                     ).a * 255.0;"	<< std::endl;
			shaderBuilder << "	float trIdx = texture2D(g_texture, texCoord.st + vec2(g_texelSize.x, 0)            ).a * 255.0;"	<< std::endl;
			shaderBuilder << "	float blIdx = texture2D(g_texture, texCoord.st + vec2(0, g_texelSize.y)            ).a * 255.0;"	<< std::endl;
			shaderBuilder << "	float brIdx = texture2D(g_texture, texCoord.st + vec2(g_texelSize.x, g_texelSize.y)).a * 255.0;"	<< std::endl;

			if(caps.texSourceMode == TEXTURE_SOURCE_MODE_IDX4)
			{
				shaderBuilder << "	vec4 tl = texture2D(g_palette, vec2(tlIdx / 16.0, 1));"									<< std::endl;
				shaderBuilder << "	vec4 tr = texture2D(g_palette, vec2(trIdx / 16.0, 1));"									<< std::endl;
				shaderBuilder << "	vec4 bl = texture2D(g_palette, vec2(blIdx / 16.0, 1));"									<< std::endl;
				shaderBuilder << "	vec4 br = texture2D(g_palette, vec2(brIdx / 16.0, 1));"									<< std::endl;
			}
			else if(caps.texSourceMode == TEXTURE_SOURCE_MODE_IDX8)
			{
				shaderBuilder << "	vec4 tl = texture2D(g_palette, vec2(tlIdx / 256.0, 1));"								<< std::endl;
				shaderBuilder << "	vec4 tr = texture2D(g_palette, vec2(trIdx / 256.0, 1));"								<< std::endl;
				shaderBuilder << "	vec4 bl = texture2D(g_palette, vec2(blIdx / 256.0, 1));"								<< std::endl;
				shaderBuilder << "	vec4 br = texture2D(g_palette, vec2(brIdx / 256.0, 1));"								<< std::endl;
			}

			shaderBuilder << "	vec2 f = fract(texCoord.xy * g_textureSize);"												<< std::endl;
			shaderBuilder << "	vec4 tA = mix(tl, tr, f.x);"																<< std::endl;
			shaderBuilder << "	vec4 tB = mix(bl, br, f.x);"																<< std::endl;
			shaderBuilder << "	textureColor = mix(tA, tB, f.y);"															<< std::endl;
		}
	}
	else if(caps.texSourceMode == TEXTURE_SOURCE_MODE_STD)
	{
		shaderBuilder << "	textureColor = texture2D(g_texture, texCoord.st);"								<< std::endl;
	}

	if(!caps.texHasAlpha)
	{
		shaderBuilder << "	textureColor.a = 1.0;" << std::endl;
	}

	switch(caps.texFunction)
	{
	default:
		assert(0);
	case TEX0_FUNCTION_MODULATE:
		shaderBuilder << "	textureColor *= gl_Color;"														<< std::endl;
		break;
	case TEX0_FUNCTION_DECAL:
		break;
	}

	if(caps.hasFog)
	{
		shaderBuilder << "	gl_FragColor = vec4(mix(textureColor.rgb, gl_Fog.color.rgb, gl_FogFragCoord), textureColor.a);" << std::endl;
	}
	else
	{
		shaderBuilder << "	gl_FragColor = textureColor;"																	<< std::endl;
	}

	shaderBuilder << "}"																					<< std::endl;

	auto shaderSource = shaderBuilder.str();

	Framework::OpenGl::CShader result(GL_FRAGMENT_SHADER);
	result.SetSource(shaderSource.c_str(), shaderSource.size());
	bool compilationResult = result.Compile();
	assert(compilationResult);

	assert(glGetError() == GL_NO_ERROR);

	return result;
}

std::string CGSH_OpenGL::GenerateTexCoordClampingSection(TEXTURE_CLAMP_MODE clampMode, const char* coordinate)
{
	std::stringstream shaderBuilder;

	switch(clampMode)
	{
	case TEXTURE_CLAMP_MODE_REGION_CLAMP:
		shaderBuilder << "	texCoord." << coordinate << " = min(g_clampMax." << coordinate << ", " <<
			"max(g_clampMin." << coordinate << ", texCoord." << coordinate << "));" << std::endl;
		break;
	case TEXTURE_CLAMP_MODE_REGION_REPEAT:
		shaderBuilder << "	texCoord." << coordinate << " = or(int(and(int(texCoord." << coordinate << "), " <<
			"int(g_clampMin." << coordinate << "))), int(g_clampMax." << coordinate << "));";
		break;
	case TEXTURE_CLAMP_MODE_REGION_REPEAT_SIMPLE:
		shaderBuilder << "	texCoord." << coordinate << " = mod(texCoord." << coordinate << ", " <<
			"g_clampMin." << coordinate << ") + g_clampMax." << coordinate << ";" << std::endl;
		break;
	}

	std::string shaderSource = shaderBuilder.str();
	return shaderSource;
}
<commit_msg>Added proper support for HIGHLIGHT and HIGHLIGHT2 texture functions.<commit_after>#include "GSH_OpenGL.h"
#include <assert.h>
#include <sstream>

static const char* s_andFunction =
"float and(int a, int b)\r\n"
"{\r\n"
"	int r = 0;\r\n"
"	int ha, hb;\r\n"
"	\r\n"
"	int m = int(min(float(a), float(b)));\r\n"
"	\r\n"
"	for(int k = 1; k <= m; k *= 2)\r\n"
"	{\r\n"
"		ha = a / 2;\r\n"
"		hb = b / 2;\r\n"
"		if(((a - ha * 2) != 0) && ((b - hb * 2) != 0))\r\n"
"		{\r\n"
"			r += k;\r\n"
"		}\r\n"
"		a = ha;\r\n"
"		b = hb;\r\n"
"	}\r\n"
"	\r\n"
"	return float(r);\r\n"
"}\r\n";

static const char* s_orFunction =
"float or(int a, int b)\r\n"
"{\r\n"
"	int r = 0;\r\n"
"	int ha, hb;\r\n"
"	\r\n"
"	int m = int(max(float(a), float(b)));\r\n"
"	\r\n"
"	for(int k = 1; k <= m; k *= 2)\r\n"
"	{\r\n"
"		ha = a / 2;\r\n"
"		hb = b / 2;\r\n"
"		if(((a - ha * 2) != 0) || ((b - hb * 2) != 0))\r\n"
"		{\r\n"
"			r += k;\r\n"
"		}\r\n"
"		a = ha;\r\n"
"		b = hb;\r\n"
"	}\r\n"
"	\r\n"
"	return float(r);\r\n"
"}\r\n";

Framework::OpenGl::ProgramPtr CGSH_OpenGL::GenerateShader(const SHADERCAPS& caps)
{
	auto vertexShader = GenerateVertexShader(caps);
	auto fragmentShader = GenerateFragmentShader(caps);

	auto result = std::make_shared<Framework::OpenGl::CProgram>();

	result->AttachShader(vertexShader);
	result->AttachShader(fragmentShader);

	bool linkResult = result->Link();
	assert(linkResult);

	assert(glGetError() == GL_NO_ERROR);

	return result;
}

Framework::OpenGl::CShader CGSH_OpenGL::GenerateVertexShader(const SHADERCAPS& caps)
{
	std::stringstream shaderBuilder;
	shaderBuilder << "void main()"													<< std::endl;
	shaderBuilder << "{"															<< std::endl;
	shaderBuilder << "	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;"	<< std::endl;
	shaderBuilder << "	gl_FrontColor = gl_Color;"									<< std::endl;
	shaderBuilder << "	gl_Position = ftransform();"								<< std::endl;
	shaderBuilder << "	gl_FogFragCoord = gl_FogCoord;"								<< std::endl;
	shaderBuilder << "}"															<< std::endl;

	auto shaderSource = shaderBuilder.str();

	Framework::OpenGl::CShader result(GL_VERTEX_SHADER);
	result.SetSource(shaderSource.c_str(), shaderSource.size());
	bool compilationResult = result.Compile();
	assert(compilationResult);

	assert(glGetError() == GL_NO_ERROR);

	return result;
}

Framework::OpenGl::CShader CGSH_OpenGL::GenerateFragmentShader(const SHADERCAPS& caps)
{
	std::stringstream shaderBuilder;

	//Unused uniforms will get optimized away
	shaderBuilder << "uniform sampler2D g_texture;"															<< std::endl;
	shaderBuilder << "uniform sampler2D g_palette;"															<< std::endl;
	shaderBuilder << "uniform vec2 g_textureSize;"															<< std::endl;
	shaderBuilder << "uniform vec2 g_texelSize;"															<< std::endl;
	shaderBuilder << "uniform vec2 g_clampMin;"																<< std::endl;
	shaderBuilder << "uniform vec2 g_clampMax;"																<< std::endl;

	if(caps.texClampS == TEXTURE_CLAMP_MODE_REGION_REPEAT || caps.texClampT == TEXTURE_CLAMP_MODE_REGION_REPEAT)
	{
		shaderBuilder << s_andFunction << std::endl;
		shaderBuilder << s_orFunction << std::endl;
	}

	shaderBuilder << "void main()"																			<< std::endl;
	shaderBuilder << "{"																					<< std::endl;
	shaderBuilder << "	vec4 texCoord = gl_TexCoord[0];"													<< std::endl;
	shaderBuilder << "	texCoord.st /= texCoord.q;"															<< std::endl;

	if((caps.texClampS != TEXTURE_CLAMP_MODE_STD) || (caps.texClampT != TEXTURE_CLAMP_MODE_STD))
	{
		shaderBuilder << "	texCoord.st *= g_textureSize.st;"													<< std::endl;
		shaderBuilder << GenerateTexCoordClampingSection(static_cast<TEXTURE_CLAMP_MODE>(caps.texClampS), "s");
		shaderBuilder << GenerateTexCoordClampingSection(static_cast<TEXTURE_CLAMP_MODE>(caps.texClampT), "t");
		shaderBuilder << "	texCoord.st /= g_textureSize.st;"													<< std::endl;
	}

	shaderBuilder << "	vec4 textureColor = vec4(1, 1, 1, 1);"												<< std::endl;
	if(caps.isIndexedTextureSource())
	{
		if(!caps.texBilinearFilter)
		{
			shaderBuilder << "	float colorIndex = texture2D(g_texture, texCoord.st).a * 255.0;"				<< std::endl;
			if(caps.texSourceMode == TEXTURE_SOURCE_MODE_IDX4)
			{
				shaderBuilder << "	textureColor = texture2D(g_palette, vec2(colorIndex / 16.0, 1));"			<< std::endl;
			}
			else if(caps.texSourceMode == TEXTURE_SOURCE_MODE_IDX8)
			{
				shaderBuilder << "	textureColor = texture2D(g_palette, vec2(colorIndex / 256.0, 1));"			<< std::endl;
			}
		}
		else
		{
			shaderBuilder << "	float tlIdx = texture2D(g_texture, texCoord.st                                     ).a * 255.0;"	<< std::endl;
			shaderBuilder << "	float trIdx = texture2D(g_texture, texCoord.st + vec2(g_texelSize.x, 0)            ).a * 255.0;"	<< std::endl;
			shaderBuilder << "	float blIdx = texture2D(g_texture, texCoord.st + vec2(0, g_texelSize.y)            ).a * 255.0;"	<< std::endl;
			shaderBuilder << "	float brIdx = texture2D(g_texture, texCoord.st + vec2(g_texelSize.x, g_texelSize.y)).a * 255.0;"	<< std::endl;

			if(caps.texSourceMode == TEXTURE_SOURCE_MODE_IDX4)
			{
				shaderBuilder << "	vec4 tl = texture2D(g_palette, vec2(tlIdx / 16.0, 1));"									<< std::endl;
				shaderBuilder << "	vec4 tr = texture2D(g_palette, vec2(trIdx / 16.0, 1));"									<< std::endl;
				shaderBuilder << "	vec4 bl = texture2D(g_palette, vec2(blIdx / 16.0, 1));"									<< std::endl;
				shaderBuilder << "	vec4 br = texture2D(g_palette, vec2(brIdx / 16.0, 1));"									<< std::endl;
			}
			else if(caps.texSourceMode == TEXTURE_SOURCE_MODE_IDX8)
			{
				shaderBuilder << "	vec4 tl = texture2D(g_palette, vec2(tlIdx / 256.0, 1));"								<< std::endl;
				shaderBuilder << "	vec4 tr = texture2D(g_palette, vec2(trIdx / 256.0, 1));"								<< std::endl;
				shaderBuilder << "	vec4 bl = texture2D(g_palette, vec2(blIdx / 256.0, 1));"								<< std::endl;
				shaderBuilder << "	vec4 br = texture2D(g_palette, vec2(brIdx / 256.0, 1));"								<< std::endl;
			}

			shaderBuilder << "	vec2 f = fract(texCoord.xy * g_textureSize);"												<< std::endl;
			shaderBuilder << "	vec4 tA = mix(tl, tr, f.x);"																<< std::endl;
			shaderBuilder << "	vec4 tB = mix(bl, br, f.x);"																<< std::endl;
			shaderBuilder << "	textureColor = mix(tA, tB, f.y);"															<< std::endl;
		}
	}
	else if(caps.texSourceMode == TEXTURE_SOURCE_MODE_STD)
	{
		shaderBuilder << "	textureColor = texture2D(g_texture, texCoord.st);"								<< std::endl;
	}

	if(caps.texSourceMode != TEXTURE_SOURCE_MODE_NONE)
	{
		if(!caps.texHasAlpha)
		{
			shaderBuilder << "	textureColor.a = 1.0;" << std::endl;
		}

		switch(caps.texFunction)
		{
		case TEX0_FUNCTION_MODULATE:
			shaderBuilder << "	textureColor *= gl_Color;" << std::endl;
			break;
		case TEX0_FUNCTION_DECAL:
			break;
		case TEX0_FUNCTION_HIGHLIGHT:
			shaderBuilder << "	textureColor.rgb = (textureColor.rgb * gl_Color.rgb) + gl_Color.aaa;" << std::endl;
			if(!caps.texHasAlpha)
			{
				shaderBuilder << "	textureColor.a = gl_Color.a;" << std::endl;
			}
			else
			{
				shaderBuilder << "	textureColor.a += gl_Color.a;" << std::endl;
			}
			break;
		case TEX0_FUNCTION_HIGHLIGHT2:
			shaderBuilder << "	textureColor.rgb = (textureColor.rgb * gl_Color.rgb) + gl_Color.aaa;" << std::endl;
			if(!caps.texHasAlpha)
			{
				shaderBuilder << "	textureColor.a = gl_Color.a;" << std::endl;
			}
			break;
		default:
			assert(0);
			break;
		}
	}
	else
	{
		shaderBuilder << "	textureColor = gl_Color;" << std::endl;
	}

	if(caps.hasFog)
	{
		shaderBuilder << "	gl_FragColor = vec4(mix(textureColor.rgb, gl_Fog.color.rgb, gl_FogFragCoord), textureColor.a);" << std::endl;
	}
	else
	{
		shaderBuilder << "	gl_FragColor = textureColor;"																	<< std::endl;
	}

	shaderBuilder << "}"																					<< std::endl;

	auto shaderSource = shaderBuilder.str();

	Framework::OpenGl::CShader result(GL_FRAGMENT_SHADER);
	result.SetSource(shaderSource.c_str(), shaderSource.size());
	bool compilationResult = result.Compile();
	assert(compilationResult);

	assert(glGetError() == GL_NO_ERROR);

	return result;
}

std::string CGSH_OpenGL::GenerateTexCoordClampingSection(TEXTURE_CLAMP_MODE clampMode, const char* coordinate)
{
	std::stringstream shaderBuilder;

	switch(clampMode)
	{
	case TEXTURE_CLAMP_MODE_REGION_CLAMP:
		shaderBuilder << "	texCoord." << coordinate << " = min(g_clampMax." << coordinate << ", " <<
			"max(g_clampMin." << coordinate << ", texCoord." << coordinate << "));" << std::endl;
		break;
	case TEXTURE_CLAMP_MODE_REGION_REPEAT:
		shaderBuilder << "	texCoord." << coordinate << " = or(int(and(int(texCoord." << coordinate << "), " <<
			"int(g_clampMin." << coordinate << "))), int(g_clampMax." << coordinate << "));";
		break;
	case TEXTURE_CLAMP_MODE_REGION_REPEAT_SIMPLE:
		shaderBuilder << "	texCoord." << coordinate << " = mod(texCoord." << coordinate << ", " <<
			"g_clampMin." << coordinate << ") + g_clampMax." << coordinate << ";" << std::endl;
		break;
	}

	std::string shaderSource = shaderBuilder.str();
	return shaderSource;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 PLUMgrid, Inc.
 *
 * 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 <map>
#include <string>
#include <algorithm>
#include <fcntl.h>
#include <ftw.h>
#include <map>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <utility>
#include <vector>
#include <linux/bpf.h>

#include <clang/Basic/FileManager.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/CodeGen/BackendUtil.h>
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Driver/Compilation.h>
#include <clang/Driver/Driver.h>
#include <clang/Driver/Job.h>
#include <clang/Driver/Tool.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/CompilerInvocation.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Frontend/FrontendDiagnostic.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/FrontendTool/Utils.h>
#include <clang/Lex/PreprocessorOptions.h>

#include <llvm/IR/Module.h>

#include "common.h"
#include "bcc_exception.h"
#include "exported_files.h"
#include "kbuild_helper.h"
#include "b_frontend_action.h"
#include "tp_frontend_action.h"
#include "loader.h"

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

namespace ebpf {

map<string, unique_ptr<llvm::MemoryBuffer>> ClangLoader::remapped_files_;

ClangLoader::ClangLoader(llvm::LLVMContext *ctx, unsigned flags)
    : ctx_(ctx), flags_(flags)
{
  if (remapped_files_.empty()) {
    for (auto f : ExportedFiles::headers())
      remapped_files_[f.first] = llvm::MemoryBuffer::getMemBuffer(f.second);
  }
}

ClangLoader::~ClangLoader() {}

namespace
{

bool is_dir(const string& path)
{
  struct stat buf;

  if (::stat (path.c_str (), &buf) < 0)
    return false;

  return S_ISDIR(buf.st_mode);
}

std::pair<bool, string> get_kernel_path_info(const string kdir)
{
  if (is_dir(kdir + "/build") && is_dir(kdir + "/source"))
    return std::make_pair (true, "source");

  const char* suffix_from_env = ::getenv("BCC_KERNEL_MODULES_SUFFIX");
  if (suffix_from_env)
    return std::make_pair(false, string(suffix_from_env));

  return std::make_pair(false, "build");
}

}

int ClangLoader::parse(unique_ptr<llvm::Module> *mod, unique_ptr<vector<TableDesc>> *tables,
                       const string &file, bool in_memory, const char *cflags[], int ncflags) {
  using namespace clang;

  string main_path = "/virtual/main.c";
  unique_ptr<llvm::MemoryBuffer> main_buf;
  struct utsname un;
  uname(&un);
  string kdir = string(KERNEL_MODULES_DIR) + "/" + un.release;
  auto kernel_path_info = get_kernel_path_info (kdir);

  // clang needs to run inside the kernel dir
  DirStack dstack(kdir + "/" + kernel_path_info.second);
  if (!dstack.ok())
    return -1;

  string abs_file;
  if (in_memory) {
    abs_file = main_path;
    main_buf = llvm::MemoryBuffer::getMemBuffer(file);
  } else {
    if (file.substr(0, 1) == "/")
      abs_file = file;
    else
      abs_file = string(dstack.cwd()) + "/" + file;
  }

  // -fno-color-diagnostics: this is a workaround for a bug in llvm terminalHasColors() as of
  // 22 Jul 2016. Also see bcc #615.
  vector<const char *> flags_cstr({"-O0", "-emit-llvm", "-I", dstack.cwd(),
                                   "-Wno-deprecated-declarations",
                                   "-Wno-gnu-variable-sized-type-not-at-end",
                                   "-fno-color-diagnostics",
                                   "-fno-unwind-tables",
                                   "-fno-asynchronous-unwind-tables",
                                   "-x", "c", "-c", abs_file.c_str()});

  KBuildHelper kbuild_helper(kdir, kernel_path_info.first);
  vector<string> kflags;
  if (kbuild_helper.get_flags(un.machine, &kflags))
    return -1;
  kflags.push_back("-include");
  kflags.push_back("/virtual/include/bcc/bpf.h");
  kflags.push_back("-include");
  kflags.push_back("/virtual/include/bcc/helpers.h");
  kflags.push_back("-isystem");
  kflags.push_back("/virtual/include");
  for (auto it = kflags.begin(); it != kflags.end(); ++it)
    flags_cstr.push_back(it->c_str());
  if (cflags) {
    for (auto i = 0; i < ncflags; ++i)
      flags_cstr.push_back(cflags[i]);
  }

  // set up the error reporting class
  IntrusiveRefCntPtr<DiagnosticOptions> diag_opts(new DiagnosticOptions());
  auto diag_client = new TextDiagnosticPrinter(llvm::errs(), &*diag_opts);

  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  DiagnosticsEngine diags(DiagID, &*diag_opts, diag_client);

  // set up the command line argument wrapper
#if defined(__powerpc64__)
#if defined(_CALL_ELF) && _CALL_ELF == 2
  driver::Driver drv("", "powerpc64le-unknown-linux-gnu", diags);
#else
  driver::Driver drv("", "powerpc64-unknown-linux-gnu", diags);
#endif
#elif defined(__aarch64__)
  driver::Driver drv("", "aarch64-unknown-linux-gnu", diags);
#else
  driver::Driver drv("", "x86_64-unknown-linux-gnu", diags);
#endif
  drv.setTitle("bcc-clang-driver");
  drv.setCheckInputsExist(false);

  unique_ptr<driver::Compilation> compilation(drv.BuildCompilation(flags_cstr));
  if (!compilation)
    return -1;

  // expect exactly 1 job, otherwise error
  const driver::JobList &jobs = compilation->getJobs();
  if (jobs.size() != 1 || !isa<driver::Command>(*jobs.begin())) {
    SmallString<256> msg;
    llvm::raw_svector_ostream os(msg);
    jobs.Print(os, "; ", true);
    diags.Report(diag::err_fe_expected_compiler_job) << os.str();
    return -1;
  }

  const driver::Command &cmd = cast<driver::Command>(*jobs.begin());
  if (llvm::StringRef(cmd.getCreator().getName()) != "clang") {
    diags.Report(diag::err_fe_expected_clang_command);
    return -1;
  }

  // Initialize a compiler invocation object from the clang (-cc1) arguments.
  const driver::ArgStringList &ccargs = cmd.getArguments();

  if (flags_ & DEBUG_PREPROCESSOR) {
    llvm::errs() << "clang";
    for (auto arg : ccargs)
      llvm::errs() << " " << arg;
    llvm::errs() << "\n";
  }

  // pre-compilation pass for generating tracepoint structures
  CompilerInstance compiler0;
  CompilerInvocation &invocation0 = compiler0.getInvocation();
  if (!CompilerInvocation::CreateFromArgs(invocation0, const_cast<const char **>(ccargs.data()),
                                          const_cast<const char **>(ccargs.data()) + ccargs.size(), diags))
    return -1;

  invocation0.getPreprocessorOpts().RetainRemappedFileBuffers = true;
  for (const auto &f : remapped_files_)
    invocation0.getPreprocessorOpts().addRemappedFile(f.first, &*f.second);

  if (in_memory) {
    invocation0.getPreprocessorOpts().addRemappedFile(main_path, &*main_buf);
    invocation0.getFrontendOpts().Inputs.clear();
    invocation0.getFrontendOpts().Inputs.push_back(FrontendInputFile(main_path, IK_C));
  }
  invocation0.getFrontendOpts().DisableFree = false;

  compiler0.createDiagnostics(new IgnoringDiagConsumer());

  // capture the rewritten c file
  string out_str;
  llvm::raw_string_ostream os(out_str);
  TracepointFrontendAction tpact(os);
  compiler0.ExecuteAction(tpact); // ignore errors, they will be reported later
  unique_ptr<llvm::MemoryBuffer> out_buf = llvm::MemoryBuffer::getMemBuffer(out_str);

  // first pass
  CompilerInstance compiler1;
  CompilerInvocation &invocation1 = compiler1.getInvocation();
  if (!CompilerInvocation::CreateFromArgs(invocation1, const_cast<const char **>(ccargs.data()),
                                          const_cast<const char **>(ccargs.data()) + ccargs.size(), diags))
    return -1;

  // This option instructs clang whether or not to free the file buffers that we
  // give to it. Since the embedded header files should be copied fewer times
  // and reused if possible, set this flag to true.
  invocation1.getPreprocessorOpts().RetainRemappedFileBuffers = true;
  for (const auto &f : remapped_files_)
    invocation1.getPreprocessorOpts().addRemappedFile(f.first, &*f.second);
  invocation1.getPreprocessorOpts().addRemappedFile(main_path, &*out_buf);
  invocation1.getFrontendOpts().Inputs.clear();
  invocation1.getFrontendOpts().Inputs.push_back(FrontendInputFile(main_path, IK_C));
  invocation1.getFrontendOpts().DisableFree = false;

  compiler1.createDiagnostics();

  // capture the rewritten c file
  string out_str1;
  llvm::raw_string_ostream os1(out_str1);
  BFrontendAction bact(os1, flags_);
  if (!compiler1.ExecuteAction(bact))
    return -1;
  unique_ptr<llvm::MemoryBuffer> out_buf1 = llvm::MemoryBuffer::getMemBuffer(out_str1);
  // this contains the open FDs
  *tables = bact.take_tables();

  // second pass, clear input and take rewrite buffer
  CompilerInstance compiler2;
  CompilerInvocation &invocation2 = compiler2.getInvocation();
  if (!CompilerInvocation::CreateFromArgs(invocation2, const_cast<const char **>(ccargs.data()),
                                          const_cast<const char **>(ccargs.data()) + ccargs.size(), diags))
    return -1;
  invocation2.getPreprocessorOpts().RetainRemappedFileBuffers = true;
  for (const auto &f : remapped_files_)
    invocation2.getPreprocessorOpts().addRemappedFile(f.first, &*f.second);
  invocation2.getPreprocessorOpts().addRemappedFile(main_path, &*out_buf1);
  invocation2.getFrontendOpts().Inputs.clear();
  invocation2.getFrontendOpts().Inputs.push_back(FrontendInputFile(main_path, IK_C));
  invocation2.getFrontendOpts().DisableFree = false;
  // suppress warnings in the 2nd pass, but bail out on errors (our fault)
  invocation2.getDiagnosticOpts().IgnoreWarnings = true;
  compiler2.createDiagnostics();

  EmitLLVMOnlyAction ir_act(&*ctx_);
  if (!compiler2.ExecuteAction(ir_act))
    return -1;
  *mod = ir_act.takeModule();

  return 0;
}

}  // namespace ebpf
<commit_msg>Style fixes for loader.cc<commit_after>/*
 * Copyright (c) 2015 PLUMgrid, Inc.
 *
 * 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 <map>
#include <string>
#include <algorithm>
#include <fcntl.h>
#include <ftw.h>
#include <map>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <utility>
#include <vector>
#include <linux/bpf.h>

#include <clang/Basic/FileManager.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/CodeGen/BackendUtil.h>
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Driver/Compilation.h>
#include <clang/Driver/Driver.h>
#include <clang/Driver/Job.h>
#include <clang/Driver/Tool.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/CompilerInvocation.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Frontend/FrontendDiagnostic.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/FrontendTool/Utils.h>
#include <clang/Lex/PreprocessorOptions.h>

#include <llvm/IR/Module.h>

#include "common.h"
#include "bcc_exception.h"
#include "exported_files.h"
#include "kbuild_helper.h"
#include "b_frontend_action.h"
#include "tp_frontend_action.h"
#include "loader.h"

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

namespace ebpf {

map<string, unique_ptr<llvm::MemoryBuffer>> ClangLoader::remapped_files_;

ClangLoader::ClangLoader(llvm::LLVMContext *ctx, unsigned flags)
    : ctx_(ctx), flags_(flags)
{
  if (remapped_files_.empty()) {
    for (auto f : ExportedFiles::headers())
      remapped_files_[f.first] = llvm::MemoryBuffer::getMemBuffer(f.second);
  }
}

ClangLoader::~ClangLoader() {}

namespace
{

bool is_dir(const string& path)
{
  struct stat buf;

  if (::stat (path.c_str (), &buf) < 0)
    return false;

  return S_ISDIR(buf.st_mode);
}

std::pair<bool, string> get_kernel_path_info(const string kdir)
{
  if (is_dir(kdir + "/build") && is_dir(kdir + "/source"))
    return std::make_pair (true, "source");

  const char* suffix_from_env = ::getenv("BCC_KERNEL_MODULES_SUFFIX");
  if (suffix_from_env)
    return std::make_pair(false, string(suffix_from_env));

  return std::make_pair(false, "build");
}

}

int ClangLoader::parse(unique_ptr<llvm::Module> *mod, unique_ptr<vector<TableDesc>> *tables,
                       const string &file, bool in_memory, const char *cflags[], int ncflags) {
  using namespace clang;

  string main_path = "/virtual/main.c";
  unique_ptr<llvm::MemoryBuffer> main_buf;
  struct utsname un;
  uname(&un);
  string kdir = string(KERNEL_MODULES_DIR) + "/" + un.release;
  auto kernel_path_info = get_kernel_path_info (kdir);

  // clang needs to run inside the kernel dir
  DirStack dstack(kdir + "/" + kernel_path_info.second);
  if (!dstack.ok())
    return -1;

  string abs_file;
  if (in_memory) {
    abs_file = main_path;
    main_buf = llvm::MemoryBuffer::getMemBuffer(file);
  } else {
    if (file.substr(0, 1) == "/")
      abs_file = file;
    else
      abs_file = string(dstack.cwd()) + "/" + file;
  }

  // -fno-color-diagnostics: this is a workaround for a bug in llvm terminalHasColors() as of
  // 22 Jul 2016. Also see bcc #615.
  vector<const char *> flags_cstr({"-O0", "-emit-llvm", "-I", dstack.cwd(),
                                   "-Wno-deprecated-declarations",
                                   "-Wno-gnu-variable-sized-type-not-at-end",
                                   "-fno-color-diagnostics",
                                   "-fno-unwind-tables",
                                   "-fno-asynchronous-unwind-tables",
                                   "-x", "c", "-c", abs_file.c_str()});

  KBuildHelper kbuild_helper(kdir, kernel_path_info.first);
  vector<string> kflags;
  if (kbuild_helper.get_flags(un.machine, &kflags))
    return -1;
  kflags.push_back("-include");
  kflags.push_back("/virtual/include/bcc/bpf.h");
  kflags.push_back("-include");
  kflags.push_back("/virtual/include/bcc/helpers.h");
  kflags.push_back("-isystem");
  kflags.push_back("/virtual/include");
  for (auto it = kflags.begin(); it != kflags.end(); ++it)
    flags_cstr.push_back(it->c_str());
  if (cflags) {
    for (auto i = 0; i < ncflags; ++i)
      flags_cstr.push_back(cflags[i]);
  }

  // set up the error reporting class
  IntrusiveRefCntPtr<DiagnosticOptions> diag_opts(new DiagnosticOptions());
  auto diag_client = new TextDiagnosticPrinter(llvm::errs(), &*diag_opts);

  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  DiagnosticsEngine diags(DiagID, &*diag_opts, diag_client);

  // set up the command line argument wrapper
#if defined(__powerpc64__)
#if defined(_CALL_ELF) && _CALL_ELF == 2
  driver::Driver drv("", "powerpc64le-unknown-linux-gnu", diags);
#else
  driver::Driver drv("", "powerpc64-unknown-linux-gnu", diags);
#endif
#elif defined(__aarch64__)
  driver::Driver drv("", "aarch64-unknown-linux-gnu", diags);
#else
  driver::Driver drv("", "x86_64-unknown-linux-gnu", diags);
#endif
  drv.setTitle("bcc-clang-driver");
  drv.setCheckInputsExist(false);

  unique_ptr<driver::Compilation> compilation(drv.BuildCompilation(flags_cstr));
  if (!compilation)
    return -1;

  // expect exactly 1 job, otherwise error
  const driver::JobList &jobs = compilation->getJobs();
  if (jobs.size() != 1 || !isa<driver::Command>(*jobs.begin())) {
    SmallString<256> msg;
    llvm::raw_svector_ostream os(msg);
    jobs.Print(os, "; ", true);
    diags.Report(diag::err_fe_expected_compiler_job) << os.str();
    return -1;
  }

  const driver::Command &cmd = cast<driver::Command>(*jobs.begin());
  if (llvm::StringRef(cmd.getCreator().getName()) != "clang") {
    diags.Report(diag::err_fe_expected_clang_command);
    return -1;
  }

  // Initialize a compiler invocation object from the clang (-cc1) arguments.
  const driver::ArgStringList &ccargs = cmd.getArguments();

  if (flags_ & DEBUG_PREPROCESSOR) {
    llvm::errs() << "clang";
    for (auto arg : ccargs)
      llvm::errs() << " " << arg;
    llvm::errs() << "\n";
  }

  // pre-compilation pass for generating tracepoint structures
  CompilerInstance compiler0;
  CompilerInvocation &invocation0 = compiler0.getInvocation();
  if (!CompilerInvocation::CreateFromArgs(
          invocation0, const_cast<const char **>(ccargs.data()),
          const_cast<const char **>(ccargs.data()) + ccargs.size(), diags))
    return -1;

  invocation0.getPreprocessorOpts().RetainRemappedFileBuffers = true;
  for (const auto &f : remapped_files_)
    invocation0.getPreprocessorOpts().addRemappedFile(f.first, &*f.second);

  if (in_memory) {
    invocation0.getPreprocessorOpts().addRemappedFile(main_path, &*main_buf);
    invocation0.getFrontendOpts().Inputs.clear();
    invocation0.getFrontendOpts().Inputs.push_back(
        FrontendInputFile(main_path, IK_C));
  }
  invocation0.getFrontendOpts().DisableFree = false;

  compiler0.createDiagnostics(new IgnoringDiagConsumer());

  // capture the rewritten c file
  string out_str;
  llvm::raw_string_ostream os(out_str);
  TracepointFrontendAction tpact(os);
  compiler0.ExecuteAction(tpact); // ignore errors, they will be reported later
  unique_ptr<llvm::MemoryBuffer> out_buf = llvm::MemoryBuffer::getMemBuffer(out_str);

  // first pass
  CompilerInstance compiler1;
  CompilerInvocation &invocation1 = compiler1.getInvocation();
  if (!CompilerInvocation::CreateFromArgs(
          invocation1, const_cast<const char **>(ccargs.data()),
          const_cast<const char **>(ccargs.data()) + ccargs.size(), diags))
    return -1;

  // This option instructs clang whether or not to free the file buffers that we
  // give to it. Since the embedded header files should be copied fewer times
  // and reused if possible, set this flag to true.
  invocation1.getPreprocessorOpts().RetainRemappedFileBuffers = true;
  for (const auto &f : remapped_files_)
    invocation1.getPreprocessorOpts().addRemappedFile(f.first, &*f.second);
  invocation1.getPreprocessorOpts().addRemappedFile(main_path, &*out_buf);
  invocation1.getFrontendOpts().Inputs.clear();
  invocation1.getFrontendOpts().Inputs.push_back(
      FrontendInputFile(main_path, IK_C));
  invocation1.getFrontendOpts().DisableFree = false;

  compiler1.createDiagnostics();

  // capture the rewritten c file
  string out_str1;
  llvm::raw_string_ostream os1(out_str1);
  BFrontendAction bact(os1, flags_);
  if (!compiler1.ExecuteAction(bact))
    return -1;
  unique_ptr<llvm::MemoryBuffer> out_buf1 = llvm::MemoryBuffer::getMemBuffer(out_str1);
  // this contains the open FDs
  *tables = bact.take_tables();

  // second pass, clear input and take rewrite buffer
  CompilerInstance compiler2;
  CompilerInvocation &invocation2 = compiler2.getInvocation();
  if (!CompilerInvocation::CreateFromArgs(
          invocation2, const_cast<const char **>(ccargs.data()),
          const_cast<const char **>(ccargs.data()) + ccargs.size(), diags))
    return -1;
  invocation2.getPreprocessorOpts().RetainRemappedFileBuffers = true;
  for (const auto &f : remapped_files_)
    invocation2.getPreprocessorOpts().addRemappedFile(f.first, &*f.second);
  invocation2.getPreprocessorOpts().addRemappedFile(main_path, &*out_buf1);
  invocation2.getFrontendOpts().Inputs.clear();
  invocation2.getFrontendOpts().Inputs.push_back(
      FrontendInputFile(main_path, IK_C));
  invocation2.getFrontendOpts().DisableFree = false;
  // suppress warnings in the 2nd pass, but bail out on errors (our fault)
  invocation2.getDiagnosticOpts().IgnoreWarnings = true;
  compiler2.createDiagnostics();

  EmitLLVMOnlyAction ir_act(&*ctx_);
  if (!compiler2.ExecuteAction(ir_act))
    return -1;
  *mod = ir_act.takeModule();

  return 0;
}

}  // namespace ebpf
<|endoftext|>


<commit_before>/*
 * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
 * Copyright (C) 2013-2015  Manav Bhatia
 *
 * 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
 */

// MAST includes
#include "solver/transient_solver_base.h"
#include "base/transient_assembly.h"

// libMesh includes
#include "libmesh/numeric_vector.h"
#include "libmesh/dof_map.h"

MAST::TransientSolverBase::TransientSolverBase():
dt(0.),
_first_step(false),
_assembly(NULL),
_system(NULL) {

}

MAST::TransientSolverBase::~TransientSolverBase() {
    this->clear_assembly();
}

void
MAST::TransientSolverBase::set_assembly(MAST::TransientAssembly& assembly) {

    // make sure that the previous assembly association has been cleared
    this->clear_assembly();

    _assembly = &assembly;
    _system   = dynamic_cast<libMesh::NonlinearImplicitSystem*>(&assembly.system());

    // number of time steps to store
    unsigned int n_iters = _n_iters_to_store();

    // resize the vectors if needed
    _solution.resize(n_iters);
    _velocity.resize(n_iters);
    if (this->ode_order()>1)
        _acceleration.resize(n_iters);

    for (unsigned int i=0; i<n_iters; i++) {
        _solution[i] = _system->solution->zero_clone().release();
        _velocity[i] = _system->solution->zero_clone().release();
        if (this->ode_order()>1)
            _acceleration[i] = _system->solution->zero_clone().release();
    }

    // now localize the vectors
    // add the vectors
    std::string nm;
    for (unsigned int i=0; i<n_iters; i++) {
        std::ostringstream iter;
        iter << i;

        // add the solution
        nm = "transient_solution_";
        nm += iter.str();
        if (!_system->have_vector(nm))
            _system->add_vector(nm);

        // add the velocity
        nm = "transient_velocity_";
        nm += iter.str();
        if (!_system->have_vector(nm))
            _system->add_vector(nm);

        if (this->ode_order() > 1) {
            // add the acceleration
            nm = "transient_acceleration_";
            nm += iter.str();
            if (!_system->have_vector(nm))
                _system->add_vector(nm);

        }
    }

    _first_step = true;
}

void
MAST::TransientSolverBase::clear_assembly() {

    // if no system has been set so far, nothing needs to be done
    if (!_system)
        return;

    // clear the transient solutions stored in system for solution
    // number of time steps to store
    unsigned int n_iters = _n_iters_to_store();

    // now localize the vectors
    // add the vectors
    std::string nm;
    for (unsigned int i=0; i<n_iters; i++) {
        std::ostringstream iter;
        iter << i;

        // add the solution
        nm = "transient_solution_";
        nm += iter.str();
        if (_system->have_vector(nm))
            _system->remove_vector(nm);

        // add the velocity
        nm = "transient_velocity_";
        nm += iter.str();
        if (_system->have_vector(nm))
            _system->remove_vector(nm);

        if (this->ode_order() > 1) {
            // add the acceleration
            nm = "transient_acceleration_";
            nm += iter.str();
            if (_system->have_vector(nm))
                _system->remove_vector(nm);

        }
    }

    if (_solution.size()) {

        for (unsigned int i=0; i<n_iters; i++) {
            delete _solution[i]; _solution[i] = NULL;
            delete _velocity[i]; _velocity[i] = NULL;
            if (this->ode_order()>1) {
                delete _acceleration[i]; _acceleration[i] = NULL;
            }
        }

        _solution.resize(0);
        _velocity.resize(0);
        if (this->ode_order()>1)
            _acceleration.resize(0);
    }

    _assembly   = NULL;
    _system     = NULL;
    _first_step = true;
}

const libMesh::NumericVector<Real>&
MAST::TransientSolverBase::solution(unsigned int prev_iter) const {

    // make sura that prev_iter is within acceptable bounds
    libmesh_assert_less(prev_iter, _n_iters_to_store());

    // make sure that the vectors have been initialized
    libmesh_assert_equal_to(_solution.size(), _n_iters_to_store());
    libmesh_assert(_solution[prev_iter]);

    return *(_solution[prev_iter]);
}

const libMesh::NumericVector<Real>&
MAST::TransientSolverBase::velocity(unsigned int prev_iter) const {

    // make sura that prev_iter is within acceptable bounds
    libmesh_assert_less(prev_iter, _n_iters_to_store());

    // make sure that the vectors have been initialized
    libmesh_assert_equal_to(_velocity.size(), _n_iters_to_store());
    libmesh_assert(_velocity[prev_iter]);

    return *(_velocity[prev_iter]);
}

const libMesh::NumericVector<Real>&
MAST::TransientSolverBase::acceleration(unsigned int prev_iter) const {

    // make sura that prev_iter is within acceptable bounds
    libmesh_assert_less(prev_iter, _n_iters_to_store());

    // make sure that the vectors have been initialized
    libmesh_assert_equal_to(_acceleration.size(), _n_iters_to_store());
    libmesh_assert(_acceleration[prev_iter]);

    return *(_acceleration[prev_iter]);
}

void
MAST::TransientSolverBase::
_localize_solutions(const libMesh::NumericVector<Real>& current_sol) {

    // make sure that the system has been specified
    libmesh_assert(_system);

    // number of time steps to store
    unsigned int n_iters = _n_iters_to_store();

    // send list
    const std::vector<libMesh::dof_id_type>& send_list =
    _system->get_dof_map().get_send_list();

    // now localize the vectors
    std::string nm;
    const libMesh::NumericVector<Real> *vec;
    for (unsigned int i=0; i<n_iters; i++) {

        std::ostringstream iter;
        iter << i;

        nm = "transient_solution_" + iter.str();

        ///////////////////////////////////////////
        // localize the solution
        ///////////////////////////////////////////
        if (i == 0) {
            // update both the localized and system stored solution
            _system->get_vector(nm) = current_sol;
            _system->get_vector(nm).close();
            vec = &current_sol;
        }
        else {
            // update the localized with the system stored solution
            vec = &(_system->get_vector(nm));
        }
        _solution[i]->init(_system->n_dofs(),
                           _system->n_local_dofs(),
                           send_list,
                           false,
                           libMesh::GHOSTED);
        vec->localize(*_solution[i], send_list);
        _solution[i]->close();

        ///////////////////////////////////////////
        // localize the velocity
        ///////////////////////////////////////////
        nm = "transient_velocity_" + iter.str();
        //
        if (i == 0) {
            // update the velocity using the current estimate
            _update_velocity(_system->get_vector(nm));
        }

        // now update localized vectors using the stored velocity
        vec = &(_system->get_vector(nm));
        _velocity[i]->init(_system->n_dofs(),
                           _system->n_local_dofs(),
                           send_list,
                           false,
                           libMesh::GHOSTED);
        vec->localize(*_velocity[i], send_list);
        _velocity[i]->close();

        if (this->ode_order()) {
            ///////////////////////////////////////////
            // localize the acceleration
            ///////////////////////////////////////////
            nm = "transient_acceleration_" + iter.str();
            //
            if (i == 0) {
                // update the acceleration using the current estimate
                _update_acceleration(_system->get_vector(nm));
            }

            // now update localized vectors using the stored acceleration
            vec = &(_system->get_vector(nm));
            _acceleration[i]->init(_system->n_dofs(),
                                   _system->n_local_dofs(),
                                   send_list,
                                   false,
                                   libMesh::GHOSTED);
            vec->localize(*_acceleration[i], send_list);
            _acceleration[i]->close();
        }

    }
}

void
MAST::TransientSolverBase::set_initial_condition(Real val) {

    libmesh_assert(_system);
    libmesh_assert(_first_step);

    std::string nm;
    for (unsigned int i=0; i<_n_iters_to_store(); i++) {
        std::ostringstream oss;
        oss << i;
        nm = "transient_solution_" + oss.str();
        libMesh::NumericVector<Real> & sol =  _system->get_vector(nm);
        sol = val;
        sol.close();
    }
    _system->solution->operator=(val);
    _system->solution->close();
}

void
MAST::TransientSolverBase::advance_time_step() {

    // first ask the solver to update the acceleration vector
    _update_velocity(_system->get_vector("transient_velocity_0"));
    if (this->ode_order() > 1)
        _update_acceleration(_system->get_vector("transient_acceleration_0"));

    // next, move all the solutions and velocities into older
    // time step locations
    std::string nm1, nm2;
    for (unsigned int i=_n_iters_to_store()-1; i>0; i--) {
        std::ostringstream oss1, oss2;
        oss1 << i;
        oss2 << i-1;

        // get references to the solution
        nm1 = "transient_solution_" + oss1.str();
        nm2 = "transient_solution_" + oss2.str();

        libMesh::NumericVector<Real>
        & old_sol     = _system->get_vector(nm1),
        & sol         = _system->get_vector(nm2);

        old_sol = sol;
        old_sol.close();

        // get references to the velocity
        nm1 = "transient_velocity_" + oss1.str();
        nm2 = "transient_velocity_" + oss2.str();

        libMesh::NumericVector<Real>
        & old_vel     = _system->get_vector(nm1),
        & vel         = _system->get_vector(nm2);

        old_vel = vel;
        old_vel.close();

        if (this->ode_order() > 1) {
            // get references to the acceleration
            nm1 = "transient_acceleration_" + oss1.str();
            nm2 = "transient_acceleration_" + oss2.str();

            libMesh::NumericVector<Real>
            & old_accel     = _system->get_vector(nm1),
            & accel         = _system->get_vector(nm2);

            old_accel = accel;
            old_accel.close();
        }

    }

    // and localize solution so that if the user calls the solution and
    // velocity routines,

    // finally, update the system time
    _system->time += dt;
    _first_step    = false;
}

<commit_msg>-- bug-fix for transient solver where the first order solver was asking for transient acceleration.<commit_after>/*
 * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
 * Copyright (C) 2013-2015  Manav Bhatia
 *
 * 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
 */

// MAST includes
#include "solver/transient_solver_base.h"
#include "base/transient_assembly.h"

// libMesh includes
#include "libmesh/numeric_vector.h"
#include "libmesh/dof_map.h"

MAST::TransientSolverBase::TransientSolverBase():
dt(0.),
_first_step(false),
_assembly(NULL),
_system(NULL) {

}

MAST::TransientSolverBase::~TransientSolverBase() {
    this->clear_assembly();
}

void
MAST::TransientSolverBase::set_assembly(MAST::TransientAssembly& assembly) {

    // make sure that the previous assembly association has been cleared
    this->clear_assembly();

    _assembly = &assembly;
    _system   = dynamic_cast<libMesh::NonlinearImplicitSystem*>(&assembly.system());

    // number of time steps to store
    unsigned int n_iters = _n_iters_to_store();

    // resize the vectors if needed
    _solution.resize(n_iters);
    _velocity.resize(n_iters);
    if (this->ode_order()>1)
        _acceleration.resize(n_iters);

    for (unsigned int i=0; i<n_iters; i++) {
        _solution[i] = _system->solution->zero_clone().release();
        _velocity[i] = _system->solution->zero_clone().release();
        if (this->ode_order()>1)
            _acceleration[i] = _system->solution->zero_clone().release();
    }

    // now localize the vectors
    // add the vectors
    std::string nm;
    for (unsigned int i=0; i<n_iters; i++) {
        std::ostringstream iter;
        iter << i;

        // add the solution
        nm = "transient_solution_";
        nm += iter.str();
        if (!_system->have_vector(nm))
            _system->add_vector(nm);

        // add the velocity
        nm = "transient_velocity_";
        nm += iter.str();
        if (!_system->have_vector(nm))
            _system->add_vector(nm);

        if (this->ode_order() > 1) {
            // add the acceleration
            nm = "transient_acceleration_";
            nm += iter.str();
            if (!_system->have_vector(nm))
                _system->add_vector(nm);

        }
    }

    _first_step = true;
}

void
MAST::TransientSolverBase::clear_assembly() {

    // if no system has been set so far, nothing needs to be done
    if (!_system)
        return;

    // clear the transient solutions stored in system for solution
    // number of time steps to store
    unsigned int n_iters = _n_iters_to_store();

    // now localize the vectors
    // add the vectors
    std::string nm;
    for (unsigned int i=0; i<n_iters; i++) {
        std::ostringstream iter;
        iter << i;

        // add the solution
        nm = "transient_solution_";
        nm += iter.str();
        if (_system->have_vector(nm))
            _system->remove_vector(nm);

        // add the velocity
        nm = "transient_velocity_";
        nm += iter.str();
        if (_system->have_vector(nm))
            _system->remove_vector(nm);

        if (this->ode_order() > 1) {
            // add the acceleration
            nm = "transient_acceleration_";
            nm += iter.str();
            if (_system->have_vector(nm))
                _system->remove_vector(nm);

        }
    }

    if (_solution.size()) {

        for (unsigned int i=0; i<n_iters; i++) {
            delete _solution[i]; _solution[i] = NULL;
            delete _velocity[i]; _velocity[i] = NULL;
            if (this->ode_order()>1) {
                delete _acceleration[i]; _acceleration[i] = NULL;
            }
        }

        _solution.resize(0);
        _velocity.resize(0);
        if (this->ode_order()>1)
            _acceleration.resize(0);
    }

    _assembly   = NULL;
    _system     = NULL;
    _first_step = true;
}

const libMesh::NumericVector<Real>&
MAST::TransientSolverBase::solution(unsigned int prev_iter) const {

    // make sura that prev_iter is within acceptable bounds
    libmesh_assert_less(prev_iter, _n_iters_to_store());

    // make sure that the vectors have been initialized
    libmesh_assert_equal_to(_solution.size(), _n_iters_to_store());
    libmesh_assert(_solution[prev_iter]);

    return *(_solution[prev_iter]);
}

const libMesh::NumericVector<Real>&
MAST::TransientSolverBase::velocity(unsigned int prev_iter) const {

    // make sura that prev_iter is within acceptable bounds
    libmesh_assert_less(prev_iter, _n_iters_to_store());

    // make sure that the vectors have been initialized
    libmesh_assert_equal_to(_velocity.size(), _n_iters_to_store());
    libmesh_assert(_velocity[prev_iter]);

    return *(_velocity[prev_iter]);
}

const libMesh::NumericVector<Real>&
MAST::TransientSolverBase::acceleration(unsigned int prev_iter) const {

    // make sura that prev_iter is within acceptable bounds
    libmesh_assert_less(prev_iter, _n_iters_to_store());

    // make sure that the vectors have been initialized
    libmesh_assert_equal_to(_acceleration.size(), _n_iters_to_store());
    libmesh_assert(_acceleration[prev_iter]);

    return *(_acceleration[prev_iter]);
}

void
MAST::TransientSolverBase::
_localize_solutions(const libMesh::NumericVector<Real>& current_sol) {

    // make sure that the system has been specified
    libmesh_assert(_system);

    // number of time steps to store
    unsigned int n_iters = _n_iters_to_store();

    // send list
    const std::vector<libMesh::dof_id_type>& send_list =
    _system->get_dof_map().get_send_list();

    // now localize the vectors
    std::string nm;
    const libMesh::NumericVector<Real> *vec;
    for (unsigned int i=0; i<n_iters; i++) {

        std::ostringstream iter;
        iter << i;

        nm = "transient_solution_" + iter.str();

        ///////////////////////////////////////////
        // localize the solution
        ///////////////////////////////////////////
        if (i == 0) {
            // update both the localized and system stored solution
            _system->get_vector(nm) = current_sol;
            _system->get_vector(nm).close();
            vec = &current_sol;
        }
        else {
            // update the localized with the system stored solution
            vec = &(_system->get_vector(nm));
        }
        _solution[i]->init(_system->n_dofs(),
                           _system->n_local_dofs(),
                           send_list,
                           false,
                           libMesh::GHOSTED);
        vec->localize(*_solution[i], send_list);
        _solution[i]->close();

        ///////////////////////////////////////////
        // localize the velocity
        ///////////////////////////////////////////
        nm = "transient_velocity_" + iter.str();
        //
        if (i == 0) {
            // update the velocity using the current estimate
            _update_velocity(_system->get_vector(nm));
        }

        // now update localized vectors using the stored velocity
        vec = &(_system->get_vector(nm));
        _velocity[i]->init(_system->n_dofs(),
                           _system->n_local_dofs(),
                           send_list,
                           false,
                           libMesh::GHOSTED);
        vec->localize(*_velocity[i], send_list);
        _velocity[i]->close();

        if (this->ode_order()>1) {
            ///////////////////////////////////////////
            // localize the acceleration
            ///////////////////////////////////////////
            nm = "transient_acceleration_" + iter.str();
            //
            if (i == 0) {
                // update the acceleration using the current estimate
                _update_acceleration(_system->get_vector(nm));
            }

            // now update localized vectors using the stored acceleration
            vec = &(_system->get_vector(nm));
            _acceleration[i]->init(_system->n_dofs(),
                                   _system->n_local_dofs(),
                                   send_list,
                                   false,
                                   libMesh::GHOSTED);
            vec->localize(*_acceleration[i], send_list);
            _acceleration[i]->close();
        }

    }
}

void
MAST::TransientSolverBase::set_initial_condition(Real val) {

    libmesh_assert(_system);
    libmesh_assert(_first_step);

    std::string nm;
    for (unsigned int i=0; i<_n_iters_to_store(); i++) {
        std::ostringstream oss;
        oss << i;
        nm = "transient_solution_" + oss.str();
        libMesh::NumericVector<Real> & sol =  _system->get_vector(nm);
        sol = val;
        sol.close();
    }
    _system->solution->operator=(val);
    _system->solution->close();
}

void
MAST::TransientSolverBase::advance_time_step() {

    // first ask the solver to update the acceleration vector
    _update_velocity(_system->get_vector("transient_velocity_0"));
    if (this->ode_order() > 1)
        _update_acceleration(_system->get_vector("transient_acceleration_0"));

    // next, move all the solutions and velocities into older
    // time step locations
    std::string nm1, nm2;
    for (unsigned int i=_n_iters_to_store()-1; i>0; i--) {
        std::ostringstream oss1, oss2;
        oss1 << i;
        oss2 << i-1;

        // get references to the solution
        nm1 = "transient_solution_" + oss1.str();
        nm2 = "transient_solution_" + oss2.str();

        libMesh::NumericVector<Real>
        & old_sol     = _system->get_vector(nm1),
        & sol         = _system->get_vector(nm2);

        old_sol = sol;
        old_sol.close();

        // get references to the velocity
        nm1 = "transient_velocity_" + oss1.str();
        nm2 = "transient_velocity_" + oss2.str();

        libMesh::NumericVector<Real>
        & old_vel     = _system->get_vector(nm1),
        & vel         = _system->get_vector(nm2);

        old_vel = vel;
        old_vel.close();

        if (this->ode_order() > 1) {
            // get references to the acceleration
            nm1 = "transient_acceleration_" + oss1.str();
            nm2 = "transient_acceleration_" + oss2.str();

            libMesh::NumericVector<Real>
            & old_accel     = _system->get_vector(nm1),
            & accel         = _system->get_vector(nm2);

            old_accel = accel;
            old_accel.close();
        }

    }

    // and localize solution so that if the user calls the solution and
    // velocity routines,

    // finally, update the system time
    _system->time += dt;
    _first_step    = false;
}

<|endoftext|>


<commit_before>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "swsharingservice.h"
#include "collections_adaptor.h"
#include <libsocialweb-qt/swclientdbustypes.h>

#include <QFile>
#include <libsocialweb-qt/swclientservice.h>
#include <libsocialweb-qt/swclientserviceconfig.h>

SwSharingService::SwSharingService(SwClientService *swService,
                                   MeeGoUXSharingServiceInfo serviceInfo,
                                   QObject *parent) :
    MeeGoUXSharingService(serviceInfo, parent),
    mService(swService),
    mShareID(0)
{
    qDebug() << QString("Starting up SwSharingService with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    connect(mService,
            SIGNAL(PhotoUploadProgress(SwClientService*,int,int,QString)),
            this,
            SLOT(onShareUploadProgress(SwClientService*,int,int,QString)));
    connect(mService,
            SIGNAL(VideoUploadProgress(SwClientService*,int,int,QString)),
            this,
            SLOT(onShareUploadProgress(SwClientService*,int,int,QString)));

    registerDataTypes();    //lsw-qt DBUS data types

    //QDBusConnection::sessionBus().registerObject(GetDBusObjPath().append("/Collections"), this);
    mCollections = new CollectionsAdaptor(this);

    connect(mService,
            SIGNAL(collCreated(SwClientService*,QString,bool)),
            this,
            SLOT(onCollCreated(SwClientService*,QString,bool)));
    connect(mService,
            SIGNAL(collDetailsRetrieved(SwClientService*,SwCollectionDetails,bool)),
            this,
            SLOT(onCollDetailsRetrieved(SwClientService*,SwCollectionDetails,bool)));
    connect(mService,
            SIGNAL(collListRetrieved(SwClientService*,ArrayOfSwCollectionDetails,bool)),
            this,
            SLOT(onCollListRetrieved(SwClientService*,ArrayOfSwCollectionDetails,bool)));

/*    connect(mService,
            SIGNAL(AudioUploadProgress(SwClientService*,int,int,QString)),
            this,
            SLOT(onAudioUploadProgress(SwClientService*,int,int,QString)));*/
}

SwSharingService::~SwSharingService()
{
}

//Begin MeeGoUXSharingService methods

bool SwSharingService::CanShareType(const QString &sharetype)
{
    return (mServiceInfo.serviceTypes.contains(sharetype));
}

bool SwSharingService::CancelShare(int opid)
{
    Q_UNUSED(opid);
    qDebug() << QString("Cannot cancel LSW sharing uploads!");
    return false;
}

uint SwSharingService::GetCredsState()
{
    qDebug() << QString("SwSharingService::GetCredsState with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mService->credsState();
}

QString SwSharingService::GetDisplayName()
{
    qDebug() << QString("SwSharingService::GetDisplayName with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mService->getDisplayName();
}

QString SwSharingService::GetIconPath()
{
    qDebug() << QString("SwSharingService::GetIconPath with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mService->getServiceConfig()->getIconPath();
}

bool SwSharingService::GetServiceAvailable()
{
    qDebug() << QString("SwSharingService::GetServiceAvailable with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mService->isConfigured();
}

QString SwSharingService::GetServiceDesc()
{
    qDebug() << QString("SwSharingService::GetServiceDesc with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mService->getServiceConfig()->getDescription();
}

QString SwSharingService::GetServiceName()
{
    qDebug() << QString("SwSharingService::GetServiceName with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mServiceInfo.serviceName;
}

QString SwSharingService::GetServiceStateText()
{
    qDebug() << QString("SwSharingService::GetServiceStateText with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    //TODO: make meaningful text based on service/creds state
    return QString("Blah");
}

QString SwSharingService::GetServiceType()
{
    qDebug() << QString("SwSharingService::GetServiceType with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return tr("Web");
}

QString SwSharingService::GetSettingsURI(const QString &platform,
                                       const QString &product)
{
    QString retVal = "";

    if (platform == "MeeGo") {
        if (product == "UX") {
            retVal = QString("meego-qml-launcher --opengl --app meego-ux-settings --fullscreen --cmd showPage --cdata \"Web\ Accounts\" ");
        } else {
            qDebug() << QString("Invalid product in SwSharingService::GetSettingsURI: %1").arg(product);
        }
    } else {
        qDebug() << QString("Invalid platform in SwSharingService::GetSettingsURI: %1").arg(platform);
    }
    return retVal;
}

QString SwSharingService::GetUIName(const QString &widgettype,
                                  const QString &platform,
                                  const QString &product,
                                  const QString &sharetype,
                                  uint sharecount)
{
    qDebug() << QString("SwSharingService::GetUIName with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);

    //No LSW support for audio yet...
    if (sharetype == MEEGO_SHARE_TYPE_AUDIO)
        return QString();

    QString type;
    QString mult;
    if (widgettype == "QML") {
        if (sharetype == MEEGO_SHARE_TYPE_IMAGE) {
            type = "image";
        } else if (sharetype == MEEGO_SHARE_TYPE_VIDEO) {
            type = "video";
        } else if (sharetype == MEEGO_SHARE_TYPE_AUDIO) {
            type = "audio";
        } else {
            type = QString(sharetype).replace(QString("/"), QString("_"));   //Custom type support
        }

        mult = (sharecount > 1 ? "multi" : "single");
        QString filename = QString("%1/%2/%3_%4_%5_%6_%7").arg(QML_TARGET_BASE_PATH, "socialweb", mServiceInfo.serviceName, platform, product, type, mult);
        //If we don't have a file for this prodct/platform
        if (!QFile::exists(filename + ".qml")) {
            //Try just this product
            filename = QString("%1/%2/%3_%4_%5_%6").arg(QML_TARGET_BASE_PATH, "socialweb", mServiceInfo.serviceName, platform, type, mult);
            if (!QFile::exists(filename + ".qml")) {
                //Otherwise, just return the standard one
                filename = QString("%1/%2/%3_%4_%5").arg(QML_TARGET_BASE_PATH, "socialweb", mServiceInfo.serviceName, type, mult);
            }
        }
        return filename;

    } else {
        //Handle other UI types here...
        return QString();
    }
}

int SwSharingService::Share(const QString &sharetype, ArrayOfShareItemStruct items, QString &errmessage)
{
    if (!CanShareType(sharetype)) {
        errmessage = QString("Invalid share type %1!").arg(sharetype);
	return -1;
    }
    int i = -1;
    if (items.count() < 1) {
        errmessage = "No items to share!";
        return -1;
    }

    foreach(ShareItemStruct sis, items) {
        qDebug() << QString("Received file %1!").arg(sis.shareURI);
        qDebug() << sis.params;
        //LSW can't deal with "file://" URIs, so we trim it to a local file instead
        if (sis.shareURI.startsWith("file://", Qt::CaseInsensitive))
            sis.shareURI = sis.shareURI.remove(0, 7);

        if (sharetype == MEEGO_SHARE_TYPE_IMAGE) {
            i = mService->uploadPhoto(sis.shareURI, sis.params);
        } else if (sharetype == MEEGO_SHARE_TYPE_VIDEO) {
            i = mService->uploadVideo(sis.shareURI, sis.params);
        } else if (sharetype == MEEGO_SHARE_TYPE_AUDIO) {
            //No audio share type in LSW yet...
        }
        //TODO: Figure out how to handle partial success, partial failure...
        //Maybe make Share return a QList< struct {sis.shareURI, shareID, message} > ?
        if (i != -1) {
            mShareOpsMap[mShareID].append(i);
            mShareOpProgressMap[mShareID].append(QPair<int, int>(i, 0));
        }
    }

    return mShareID++;
}

//Private slots:

void SwSharingService::onShareUploadProgress(SwClientService *service, int opid, int progress, QString message)
{
    int i, j = -1;
    int totalProgress = 0, count = 0;

    for (i = 0; i < mShareOpsMap.count(); ++i) {
        if (mShareOpsMap[i].contains(opid)) {
            j = i;
            break;
        }
    }
    if (j == -1) {
        qDebug() << QString("Couldn't find the aggregate opid for %1 sharing opid %2 in ShareUploadProgress!").arg(service->getServiceName(), opid);
        return;
    }
    QList<QPair<int, int> >::iterator it;

    for (it = mShareOpProgressMap[j].begin(); it != mShareOpProgressMap[j].end(); ++it) {

        if ((*it).first == opid)
            (*it).second = progress;
        if ((*it).second != -1) {
            count++;
            totalProgress += (*it).second;
        }
    }

    emit this->ShareProgress(service->getServiceName(), j, (count == 0 ? 0 : (int)(totalProgress/count)), message);
}

//End MeeGoUXSharingService methods

//Begin CollectionsAdaptor methods

bool SwSharingService::Create(const QString &collection_name,
                                 uint supported_types,
                                 const QString &collection_parent,
                                 SwParams extra_parameters)
{
    return mService->createColl(collection_name,
                                (SwClientService::CollectionMediaTypes)supported_types,
                                collection_parent,
                                extra_parameters);
}

bool SwSharingService::GetList()
{
    return mService->getCollList();
}

bool SwSharingService::GetDetails(const QString &collection_id)
{
    return mService->getCollDetails(collection_id);
}

bool SwSharingService::GetSupportsCollections()
{
    return mService->hasCollections();
}

//Private slots:

void SwSharingService::onCollCreated(SwClientService *service,
                                     const QString &collID,
                                     bool error)
{
    Q_UNUSED(service);
    emit this->CollectionCreated(collID, error);
}

void SwSharingService::onCollDetailsRetrieved(SwClientService *service,
                                              const SwCollectionDetails &collDetails,
                                              bool error)
{
    Q_UNUSED(service);
    emit this->DetailsRetrieved(collDetails, error);
}

void SwSharingService::onCollListRetrieved(SwClientService *service,
                                           const ArrayOfSwCollectionDetails &collList,
                                           bool error)
{
    Q_UNUSED(service);
    qDebug() << QString("SwSharingService::onCollListRetrieved, got %1 albums").arg(collList.count());
    emit this->ListRetrieved(collList, error);
}

//End CollectionsAdaptor methods

<commit_msg>Add debug output on failed item sharing<commit_after>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "swsharingservice.h"
#include "collections_adaptor.h"
#include <libsocialweb-qt/swclientdbustypes.h>

#include <QFile>
#include <libsocialweb-qt/swclientservice.h>
#include <libsocialweb-qt/swclientserviceconfig.h>

SwSharingService::SwSharingService(SwClientService *swService,
                                   MeeGoUXSharingServiceInfo serviceInfo,
                                   QObject *parent) :
    MeeGoUXSharingService(serviceInfo, parent),
    mService(swService),
    mShareID(0)
{
    qDebug() << QString("Starting up SwSharingService with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    connect(mService,
            SIGNAL(PhotoUploadProgress(SwClientService*,int,int,QString)),
            this,
            SLOT(onShareUploadProgress(SwClientService*,int,int,QString)));
    connect(mService,
            SIGNAL(VideoUploadProgress(SwClientService*,int,int,QString)),
            this,
            SLOT(onShareUploadProgress(SwClientService*,int,int,QString)));

    registerDataTypes();    //lsw-qt DBUS data types

    //QDBusConnection::sessionBus().registerObject(GetDBusObjPath().append("/Collections"), this);
    mCollections = new CollectionsAdaptor(this);

    connect(mService,
            SIGNAL(collCreated(SwClientService*,QString,bool)),
            this,
            SLOT(onCollCreated(SwClientService*,QString,bool)));
    connect(mService,
            SIGNAL(collDetailsRetrieved(SwClientService*,SwCollectionDetails,bool)),
            this,
            SLOT(onCollDetailsRetrieved(SwClientService*,SwCollectionDetails,bool)));
    connect(mService,
            SIGNAL(collListRetrieved(SwClientService*,ArrayOfSwCollectionDetails,bool)),
            this,
            SLOT(onCollListRetrieved(SwClientService*,ArrayOfSwCollectionDetails,bool)));

/*    connect(mService,
            SIGNAL(AudioUploadProgress(SwClientService*,int,int,QString)),
            this,
            SLOT(onAudioUploadProgress(SwClientService*,int,int,QString)));*/
}

SwSharingService::~SwSharingService()
{
}

//Begin MeeGoUXSharingService methods

bool SwSharingService::CanShareType(const QString &sharetype)
{
    return (mServiceInfo.serviceTypes.contains(sharetype));
}

bool SwSharingService::CancelShare(int opid)
{
    Q_UNUSED(opid);
    qDebug() << QString("Cannot cancel LSW sharing uploads!");
    return false;
}

uint SwSharingService::GetCredsState()
{
    qDebug() << QString("SwSharingService::GetCredsState with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mService->credsState();
}

QString SwSharingService::GetDisplayName()
{
    qDebug() << QString("SwSharingService::GetDisplayName with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mService->getDisplayName();
}

QString SwSharingService::GetIconPath()
{
    qDebug() << QString("SwSharingService::GetIconPath with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mService->getServiceConfig()->getIconPath();
}

bool SwSharingService::GetServiceAvailable()
{
    qDebug() << QString("SwSharingService::GetServiceAvailable with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mService->isConfigured();
}

QString SwSharingService::GetServiceDesc()
{
    qDebug() << QString("SwSharingService::GetServiceDesc with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mService->getServiceConfig()->getDescription();
}

QString SwSharingService::GetServiceName()
{
    qDebug() << QString("SwSharingService::GetServiceName with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return mServiceInfo.serviceName;
}

QString SwSharingService::GetServiceStateText()
{
    qDebug() << QString("SwSharingService::GetServiceStateText with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    //TODO: make meaningful text based on service/creds state
    return QString("Blah");
}

QString SwSharingService::GetServiceType()
{
    qDebug() << QString("SwSharingService::GetServiceType with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);
    return tr("Web");
}

QString SwSharingService::GetSettingsURI(const QString &platform,
                                       const QString &product)
{
    QString retVal = "";

    if (platform == "MeeGo") {
        if (product == "UX") {
            retVal = QString("meego-qml-launcher --opengl --app meego-ux-settings --fullscreen --cmd showPage --cdata \"Web\ Accounts\" ");
        } else {
            qDebug() << QString("Invalid product in SwSharingService::GetSettingsURI: %1").arg(product);
        }
    } else {
        qDebug() << QString("Invalid platform in SwSharingService::GetSettingsURI: %1").arg(platform);
    }
    return retVal;
}

QString SwSharingService::GetUIName(const QString &widgettype,
                                  const QString &platform,
                                  const QString &product,
                                  const QString &sharetype,
                                  uint sharecount)
{
    qDebug() << QString("SwSharingService::GetUIName with mServiceInfo.serviceName of %1!").arg(mServiceInfo.serviceName);

    //No LSW support for audio yet...
    if (sharetype == MEEGO_SHARE_TYPE_AUDIO)
        return QString();

    QString type;
    QString mult;
    if (widgettype == "QML") {
        if (sharetype == MEEGO_SHARE_TYPE_IMAGE) {
            type = "image";
        } else if (sharetype == MEEGO_SHARE_TYPE_VIDEO) {
            type = "video";
        } else if (sharetype == MEEGO_SHARE_TYPE_AUDIO) {
            type = "audio";
        } else {
            type = QString(sharetype).replace(QString("/"), QString("_"));   //Custom type support
        }

        mult = (sharecount > 1 ? "multi" : "single");
        QString filename = QString("%1/%2/%3_%4_%5_%6_%7").arg(QML_TARGET_BASE_PATH, "socialweb", mServiceInfo.serviceName, platform, product, type, mult);
        //If we don't have a file for this prodct/platform
        if (!QFile::exists(filename + ".qml")) {
            //Try just this product
            filename = QString("%1/%2/%3_%4_%5_%6").arg(QML_TARGET_BASE_PATH, "socialweb", mServiceInfo.serviceName, platform, type, mult);
            if (!QFile::exists(filename + ".qml")) {
                //Otherwise, just return the standard one
                filename = QString("%1/%2/%3_%4_%5").arg(QML_TARGET_BASE_PATH, "socialweb", mServiceInfo.serviceName, type, mult);
            }
        }
        return filename;

    } else {
        //Handle other UI types here...
        return QString();
    }
}

int SwSharingService::Share(const QString &sharetype, ArrayOfShareItemStruct items, QString &errmessage)
{
    if (!CanShareType(sharetype)) {
        errmessage = QString("Invalid share type %1!").arg(sharetype);
	return -1;
    }
    int i = -1;
    if (items.count() < 1) {
        errmessage = "No items to share!";
        return -1;
    }

    foreach(ShareItemStruct sis, items) {
        qDebug() << QString("Received file %1!").arg(sis.shareURI);
        qDebug() << sis.params;
        //LSW can't deal with "file://" URIs, so we trim it to a local file instead
        if (sis.shareURI.startsWith("file://", Qt::CaseInsensitive))
            sis.shareURI = sis.shareURI.remove(0, 7);

        if (sharetype == MEEGO_SHARE_TYPE_IMAGE) {
            i = mService->uploadPhoto(sis.shareURI, sis.params);
        } else if (sharetype == MEEGO_SHARE_TYPE_VIDEO) {
            i = mService->uploadVideo(sis.shareURI, sis.params);
        } else if (sharetype == MEEGO_SHARE_TYPE_AUDIO) {
            //No audio share type in LSW yet...
        }
        //TODO: Figure out how to handle partial success, partial failure...
        //Maybe make Share return a QList< struct {sis.shareURI, shareID, message} > ?
        if (i != -1) {
            mShareOpsMap[mShareID].append(i);
            mShareOpProgressMap[mShareID].append(QPair<int, int>(i, 0));
        } else {
            qDebug() << QString ("Got %1 back from upload attempt").arg(i);
            return i;
        }
    }

    return mShareID++;
}

//Private slots:

void SwSharingService::onShareUploadProgress(SwClientService *service, int opid, int progress, QString message)
{
    int i, j = -1;
    int totalProgress = 0, count = 0;

    for (i = 0; i < mShareOpsMap.count(); ++i) {
        if (mShareOpsMap[i].contains(opid)) {
            j = i;
            break;
        }
    }
    if (j == -1) {
        qDebug() << QString("Couldn't find the aggregate opid for %1 sharing opid %2 in ShareUploadProgress!").arg(service->getServiceName(), opid);
        return;
    }
    QList<QPair<int, int> >::iterator it;

    for (it = mShareOpProgressMap[j].begin(); it != mShareOpProgressMap[j].end(); ++it) {

        if ((*it).first == opid)
            (*it).second = progress;
        if ((*it).second != -1) {
            count++;
            totalProgress += (*it).second;
        }
    }

    emit this->ShareProgress(service->getServiceName(), j, (count == 0 ? 0 : (int)(totalProgress/count)), message);
}

//End MeeGoUXSharingService methods

//Begin CollectionsAdaptor methods

bool SwSharingService::Create(const QString &collection_name,
                                 uint supported_types,
                                 const QString &collection_parent,
                                 SwParams extra_parameters)
{
    return mService->createColl(collection_name,
                                (SwClientService::CollectionMediaTypes)supported_types,
                                collection_parent,
                                extra_parameters);
}

bool SwSharingService::GetList()
{
    return mService->getCollList();
}

bool SwSharingService::GetDetails(const QString &collection_id)
{
    return mService->getCollDetails(collection_id);
}

bool SwSharingService::GetSupportsCollections()
{
    return mService->hasCollections();
}

//Private slots:

void SwSharingService::onCollCreated(SwClientService *service,
                                     const QString &collID,
                                     bool error)
{
    Q_UNUSED(service);
    emit this->CollectionCreated(collID, error);
}

void SwSharingService::onCollDetailsRetrieved(SwClientService *service,
                                              const SwCollectionDetails &collDetails,
                                              bool error)
{
    Q_UNUSED(service);
    emit this->DetailsRetrieved(collDetails, error);
}

void SwSharingService::onCollListRetrieved(SwClientService *service,
                                           const ArrayOfSwCollectionDetails &collList,
                                           bool error)
{
    Q_UNUSED(service);
    qDebug() << QString("SwSharingService::onCollListRetrieved, got %1 albums").arg(collList.count());
    emit this->ListRetrieved(collList, error);
}

//End CollectionsAdaptor methods

<|endoftext|>


<commit_before>#include <unordered_set>
#include <vector>
#include <cstdint>

#include "benchmark/benchmark.h"
#include "GenerateInput.hpp"

constexpr std::size_t MAX_STRING_LEN = 8 << 14;

// Benchmark when there is no match.
static void BM_StringFindNoMatch(benchmark::State &state) {
  std::string s1(state.range(0), '-');
  std::string s2(8, '*');
  while (state.KeepRunning())
    benchmark::DoNotOptimize(s1.find(s2));
}
BENCHMARK(BM_StringFindNoMatch)->Range(10, MAX_STRING_LEN);

// Benchmark when the string matches first time.
static void BM_StringFindAllMatch(benchmark::State &state) {
  std::string s1(MAX_STRING_LEN, '-');
  std::string s2(state.range(0), '-');
  while (state.KeepRunning())
    benchmark::DoNotOptimize(s1.find(s2));
}
BENCHMARK(BM_StringFindAllMatch)->Range(1, MAX_STRING_LEN);

// Benchmark when the string matches somewhere in the end.
static void BM_StringFindMatch1(benchmark::State &state) {
  std::string s1(MAX_STRING_LEN / 2, '*');
  s1 += std::string(state.range(0), '-');
  std::string s2(state.range(0), '-');
  while (state.KeepRunning())
    benchmark::DoNotOptimize(s1.find(s2));
}
BENCHMARK(BM_StringFindMatch1)->Range(1, MAX_STRING_LEN / 4);

// Benchmark when the string matches somewhere from middle to the end.
static void BM_StringFindMatch2(benchmark::State &state) {
  std::string s1(MAX_STRING_LEN / 2, '*');
  s1 += std::string(state.range(0), '-');
  s1 += std::string(state.range(0), '*');
  std::string s2(state.range(0), '-');
  while (state.KeepRunning())
    benchmark::DoNotOptimize(s1.find(s2));
}
BENCHMARK(BM_StringFindMatch2)->Range(1, MAX_STRING_LEN / 4);

BENCHMARK_MAIN();
<commit_msg>Add new string benchmarks<commit_after>#include <unordered_set>
#include <vector>
#include <cstdint>

#include "benchmark/benchmark.h"
#include "GenerateInput.hpp"

constexpr std::size_t MAX_STRING_LEN = 8 << 14;

// Benchmark when there is no match.
static void BM_StringFindNoMatch(benchmark::State &state) {
  std::string s1(state.range(0), '-');
  std::string s2(8, '*');
  while (state.KeepRunning())
    benchmark::DoNotOptimize(s1.find(s2));
}
BENCHMARK(BM_StringFindNoMatch)->Range(10, MAX_STRING_LEN);

// Benchmark when the string matches first time.
static void BM_StringFindAllMatch(benchmark::State &state) {
  std::string s1(MAX_STRING_LEN, '-');
  std::string s2(state.range(0), '-');
  while (state.KeepRunning())
    benchmark::DoNotOptimize(s1.find(s2));
}
BENCHMARK(BM_StringFindAllMatch)->Range(1, MAX_STRING_LEN);

// Benchmark when the string matches somewhere in the end.
static void BM_StringFindMatch1(benchmark::State &state) {
  std::string s1(MAX_STRING_LEN / 2, '*');
  s1 += std::string(state.range(0), '-');
  std::string s2(state.range(0), '-');
  while (state.KeepRunning())
    benchmark::DoNotOptimize(s1.find(s2));
}
BENCHMARK(BM_StringFindMatch1)->Range(1, MAX_STRING_LEN / 4);

// Benchmark when the string matches somewhere from middle to the end.
static void BM_StringFindMatch2(benchmark::State &state) {
  std::string s1(MAX_STRING_LEN / 2, '*');
  s1 += std::string(state.range(0), '-');
  s1 += std::string(state.range(0), '*');
  std::string s2(state.range(0), '-');
  while (state.KeepRunning())
    benchmark::DoNotOptimize(s1.find(s2));
}
BENCHMARK(BM_StringFindMatch2)->Range(1, MAX_STRING_LEN / 4);

static void BM_StringCtorDefault(benchmark::State &state) {
  while (state.KeepRunning()) {
    for (unsigned I=0; I < 1000; ++I) {
      std::string Default;
      benchmark::DoNotOptimize(Default.c_str());
    }
  }
}
BENCHMARK(BM_StringCtorDefault);

static void BM_StringCtorCStr(benchmark::State &state) {
  std::string Input = getRandomString(state.range(0));
  const char *Str = Input.c_str();
  benchmark::DoNotOptimize(Str);
  while (state.KeepRunning()) {
    std::string Tmp(Str);
    benchmark::DoNotOptimize(Tmp.c_str());
  }
}
BENCHMARK(BM_StringCtorCStr)->Arg(1)->Arg(8)->Range(16, MAX_STRING_LEN / 4);

BENCHMARK_MAIN();
<|endoftext|>


<commit_before>#pragma once

#include <El.hpp>
#include <cmath>
#include <iostream>

inline void set_stream_precision(std::ofstream &ofs)
{
  ofs.precision(
    std::ceil(El::gmp::Precision() * std::log(2.0) / std::log(10.0)));
}
<commit_msg>Use log10 and add offset in set_stream_precision<commit_after>#pragma once

#include <El.hpp>
#include <cmath>
#include <iostream>

inline void set_stream_precision(std::ostream &os)
{
  os.precision(std::ceil(El::gmp::Precision() * std::log10(2.0)) + 1);
}
<|endoftext|>


<commit_before><commit_msg>added template code<commit_after>/*
 *  Lab 1 - Basic multiprogramming
 *
 *	By: Andrew Radlbeck & John Wood
 */
#include <iostream>
using namespace std;

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

	return 0;
} <|endoftext|>


<commit_before>//
//  dfa_single_regex.cpp
//  Parse
//
//  Created by Andrew Hunter on 28/04/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <string>
#include <sstream>

#include "dfa_single_regex.h"

#include "Dfa/lexer.h"

using namespace std;
using namespace dfa;

void test_dfa_single_regex::test(std::string name, std::string regex, std::string accepting, std::string rejecting) {
    // Create a lexer that accepts the regular expression
    lexer myLexer;
    myLexer.add_symbol(regex, 1);

    // Compile it
    myLexer.compile(true);

    // Try the accepting phrase
    stringstream acceptIn(accepting);
    lexeme_stream* stream = myLexer.create_stream_from(acceptIn);

    // Get the first lexeme
    lexeme* first;
    (*stream) >> first;
    delete stream;

    // Try the rejecting phrase
    stringstream rejectIn(rejecting);
    stream = myLexer.create_stream_from(rejectIn);

    lexeme* fail;
    (*stream) >> fail;

    delete stream;

    // first lexeme should be an accepting lexeme, second should be a rejection
    if (first != NULL && fail != NULL && first->matched() == 1 && first->content<char>() == accepting && fail->matched() == -1 && fail->content().size() == 1) {
        report(name, true);
    } else {
        // Break things down if we get a failure
        report(name + "-accept", first != NULL && first->matched() == 1);
        report(name + "-content", first != NULL && first->content<char>() == accepting);

        report(name + "-reject", fail != NULL && fail->matched() == -1);
        report(name + "-rejectone", fail != NULL && fail->content().size() == 1);
    }

    delete first;
    delete fail;
}

void test_dfa_single_regex::run_tests() {
    test("basic", "a", "a", "b");
    test("sayaaaa", "a*", "aaaaa", "b");
    test("ababab", "(ab)+", "ababab", "aaaaaa");

    test("a-or-b1", "a|b", "a", "c");
    test("a-or-b2", "a|b", "b", "c");
    test("a-or-b3", "a+|b+", "aaaaa", "c");
    test("a-or-b4", "a+|b+", "bbbbb", "c");
    test("a-or-b5", "a*|b*", "aaaaa", "c");
    test("a-or-b6", "a*|b*", "bbbbb", "c");
    test("a-or-b7", "(a*)|(b*)", "bbbbb", "c");
    test("a-or-b8", "(a+)|(b+)", "bbbbb", "c");

    test("ab-or-cd1", "ab|cd", "ab", "a");
    test("ab-or-cd2", "ab|cd", "cd", "a");
    test("ab-or-cd3", "(ab)+|(cd)+", "ababab", "a");
    test("ab-or-cd4", "(ab)+|(cd)+", "cdcdcd", "c");
    test("ab-or-cd5", "(ab)+|((cd)+)", "cdcdcd", "c");

    test("ab-or-cd-or-ef1", "ab|cd|ef", "ab", "af");
    test("ab-or-cd-or-ef2", "ab|cd|ef", "cd", "c");
    test("ab-or-cd-or-ef3", "ab|cd|ef", "ef", "d");

    test("a-or-b-c1", "(a|b?)c", "ac", "a");
    test("a-or-b-c2", "(a|b?)c", "bc", "b");
    test("a-or-b-c3", "(a|b?)c", "c", "b");
}
<commit_msg>Modified test to do both the 'full' and the 'compact' regular expressions<commit_after>//
//  dfa_single_regex.cpp
//  Parse
//
//  Created by Andrew Hunter on 28/04/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <string>
#include <sstream>

#include "dfa_single_regex.h"

#include "Dfa/lexer.h"

using namespace std;
using namespace dfa;

void test_dfa_single_regex::test(std::string name, std::string regex, std::string accepting, std::string rejecting) {
    // Create a lexer that accepts the regular expression
    lexer myLexer;
    myLexer.add_symbol(regex, 1);

    lexer myCompactLexer;
    myCompactLexer.add_symbol(regex, 1);

    // Compile it
    myLexer.compile(false);
    myCompactLexer.compile(true);

    // Try the accepting phrase
    stringstream acceptIn(accepting);
    lexeme_stream* stream = myLexer.create_stream_from(acceptIn);

    // Get the first lexeme
    lexeme* first;
    (*stream) >> first;
    delete stream;

    // Try again with the compact lexer
    stringstream acceptCompactIn(accepting);
    stream = myCompactLexer.create_stream_from(acceptCompactIn);

    lexeme* firstCompact;
    (*stream) >> firstCompact;
    delete stream;

    // Try the rejecting phrase
    stringstream rejectIn(rejecting);
    stream = myLexer.create_stream_from(rejectIn);

    lexeme* fail;
    (*stream) >> fail;

    delete stream;

    // first lexeme should be an accepting lexeme, second should be a rejection
    if (first != NULL && fail != NULL && first->matched() == 1 && first->content<char>() == accepting
        && firstCompact != NULL && firstCompact->matched() == 1 && firstCompact->content<char>() == accepting
        && fail != NULL && fail->matched() == -1 && fail->content().size() == 1) {
        report(name, true);
    } else {
        // Break things down if we get a failure
        report(name + "-accept", first != NULL && first->matched() == 1);
        report(name + "-content", first != NULL && first->content<char>() == accepting);

        report(name + "-compact-accept", firstCompact != NULL && firstCompact->matched() == 1);
        report(name + "-compact-content", firstCompact != NULL && firstCompact->content<char>() == accepting);

        report(name + "-reject", fail != NULL && fail->matched() == -1);
        report(name + "-rejectone", fail != NULL && fail->content().size() == 1);
    }

    delete first;
    delete firstCompact;
    delete fail;
}

void test_dfa_single_regex::run_tests() {
    test("basic", "a", "a", "b");
    test("sayaaaa", "a*", "aaaaa", "b");
    test("ababab", "(ab)+", "ababab", "aaaaaa");

    test("a-or-b1", "a|b", "a", "c");
    test("a-or-b2", "a|b", "b", "c");
    test("a-or-b3", "a+|b+", "aaaaa", "c");
    test("a-or-b4", "a+|b+", "bbbbb", "c");
    test("a-or-b5", "a*|b*", "aaaaa", "c");
    test("a-or-b6", "a*|b*", "bbbbb", "c");
    test("a-or-b7", "(a*)|(b*)", "bbbbb", "c");
    test("a-or-b8", "(a+)|(b+)", "bbbbb", "c");

    test("ab-or-cd1", "ab|cd", "ab", "a");
    test("ab-or-cd2", "ab|cd", "cd", "a");
    test("ab-or-cd3", "(ab)+|(cd)+", "ababab", "a");
    test("ab-or-cd4", "(ab)+|(cd)+", "cdcdcd", "c");
    test("ab-or-cd5", "(ab)+|((cd)+)", "cdcdcd", "c");

    test("ab-or-cd-or-ef1", "ab|cd|ef", "ab", "af");
    test("ab-or-cd-or-ef2", "ab|cd|ef", "cd", "c");
    test("ab-or-cd-or-ef3", "ab|cd|ef", "ef", "d");

    test("a-or-b-c1", "(a|b?)c", "ac", "a");
    test("a-or-b-c2", "(a|b?)c", "bc", "b");
    test("a-or-b-c3", "(a|b?)c", "c", "b");
}
<|endoftext|>