<commit_before>#include "IDatabaseEngine.h"
#include "DBEngineFactory.h"

#include "util/Datagram.h"
#include "util/DatagramIterator.h"
#include "core/logger.h"
#include "core/global.h"
#include "dcparser/dcSubatomicType.h"
#include "dcparser/dcAtomicField.h"

#include <yaml-cpp/yaml.h>
#include <fstream>
#include <list>

static ConfigVariable<std::string> foldername("foldername", "yaml_db");
LogCategory yamldb_log("yamldb", "YAML Database Engine");

class YAMLEngine : public IDatabaseEngine
{
private:
	unsigned int m_next_id;
	std::list<unsigned int> m_free_ids;
	std::string m_foldername;

	// update_info writes m_next_id and m_free_ids to "info.yaml"
	void update_info()
	{
		YAML::Emitter out;
		out << YAML::BeginMap
			<< YAML::Key << "next"
			<< YAML::Value << m_next_id;
		if(!m_free_ids.empty()) {
			out << YAML::Key << "free"
				<< YAML::Value << YAML::BeginSeq;
			for(auto it = m_free_ids.begin(); it != m_free_ids.end(); ++it)
			{
				out << *it;
			}
			out << YAML::EndSeq;
		}
		out << YAML::EndMap;

		std::fstream file;
		file.open(m_foldername + "/info.yaml", std::ios_base::out);
		if(file.is_open())
		{
			file << out.c_str();
			file.close();
		}
	}

	// get_next_id returns the next available id to be used in object creation
	unsigned int get_next_id()
	{
		unsigned int do_id;
		if(m_next_id <= m_max_id)
		{
			do_id = m_next_id++;
		}
		else
		{
			// Dequeue id from list
			if(!m_free_ids.empty())
			{
				do_id = *m_free_ids.begin();
				m_free_ids.remove(do_id);
			}
			else
			{
				return 0;
			}
		}

		update_info();
		return do_id;
	}

	std::string read_yaml_field(DCField* field, YAML::Node node)
	{
		DCAtomicField* atomic = field->as_atomic_field();
		if(atomic && atomic->get_num_elements() == 1)
		{
			switch(atomic->get_element_type(0))
			{
				case ST_char:
				{
					char value = node.as<char>();
					return std::string(&value);
				}
				break;
				case ST_int8:
				{
					// Cast as short because char treated as character data
					short value = node.as<short>();
					char buffer[1];

					memcpy(buffer, (char*)&value, 1);
					return std::string(buffer);
				}
				break;
				case ST_int16:
				{
					short value = node.as<short>();
					char buffer[2];

					memcpy(buffer, (char*)&value, 2);
					return std::string(buffer);
				}
				break;
				case ST_int32:
				{
					int value = node.as<int>();
					char buffer[4];

					memcpy(buffer, (char*)&value, 4);
					return std::string(buffer);
				}
				break;
				case ST_int64:
				{
					long long value = node.as<long long>();
					char buffer[8];

					memcpy(buffer, (char*)&value, 8);
					return std::string(buffer);
				}
				break;
				case ST_uint8:
				{
					unsigned short value = node.as<unsigned short>();
					char buffer[1];

					memcpy(buffer, (char*)&value, 1);
					return std::string(buffer);
				}
				break;
				case ST_uint16:
				{
					unsigned short value = node.as<unsigned short>();
					char buffer[2];

					memcpy(buffer, (char*)&value, 2);
					return std::string(buffer);
				}
				break;
				case ST_uint32:
				{
					unsigned int value = node.as<unsigned int>();
					char buffer[4];

					memcpy(buffer, (char*)&value, 4);
					return std::string(buffer);
				}
				break;
				case ST_uint64:
				{
					unsigned long long value = node.as<unsigned long long>();
					char buffer[8];

					memcpy(buffer, (char*)&value, 8);
					return std::string(buffer);
				}
				break;
				case ST_float64:
				{
					double value = node.as<double>();
					char buffer[8];

					memcpy(buffer, (char*)&value, 8);
					return std::string(buffer);
				}
				break;
				case ST_string:
				{
					std::string value = node.as<std::string>();
					unsigned int len = value.length();
					char lenstr[2];

					memcpy(lenstr, (char*)&len, 2);
					return std::string(lenstr) + value;
				}
				break;
				default:
					return node.as<std::string>();
			}

		}

		return "";
	}

	void write_yaml_field(YAML::Emitter& out, DCField* field, const std::string& value)
	{
		out << YAML::Key << field->get_name();
		DCAtomicField* atomic = field->as_atomic_field();

		if(atomic && atomic->get_num_elements() == 1)
		{
			out << YAML::Value;
			switch(atomic->get_element_type(0))
			{
				case ST_char:
				{
					out << *(char*)(value.c_str());
				}
				break;
				case ST_int8:
				{
					// Cast as short, because char treated as character data
					out << *(short*)(value.c_str());
				}
				break;
				case ST_int16:
				{
					out << *(short*)(value.c_str());
				}
				break;
				case ST_int32:
				{
					out << *(int*)(value.c_str());
				}
				break;
				case ST_int64:
				{
					out << *(long long*)(value.c_str());
				}
				break;
				case ST_uint8:
				{
					out << *(unsigned char*)(value.c_str());
				}
				break;
				case ST_uint16:
				{
					out << *(unsigned short*)(value.c_str());
				}
				break;
				case ST_uint32:
				{
					out << *(unsigned int*)(value.c_str());
				}
				break;
				case ST_uint64:
				{
					out << *(unsigned long long*)(value.c_str());
				}
				break;
				case ST_float64:
				{
					out << *(double*)(value.c_str());
				}
				break;
				case ST_string:
				{
					// Skip the length bytes
					out << value.substr(2);
				}
				break;
				default:
					out << value;
			}
			return;
		}

		yamldb_log.error() << "Recieved non-atomic field: " << field->get_name() << std::endl;
		out << YAML::Value << value;
	}
public:
	YAMLEngine(DBEngineConfig dbeconfig, unsigned int min_id, unsigned int max_id) :
		IDatabaseEngine(dbeconfig, min_id, max_id),
		m_next_id(min_id),
		m_free_ids(),
		m_foldername(foldername.get_rval(m_config))
	{
		// Open database info file
		std::ifstream infostream(m_foldername + "/info.yaml");
		YAML::Node document = YAML::Load(infostream);

		if(!document.IsNull()) {
			// Read next available id
			YAML::Node key_next = document["next"];
			if(!key_next.IsNull())
			{
				m_next_id = document["next"].as<unsigned int>();
			}

			// Read available freed ids
			YAML::Node key_free = document["free"];
			if(!key_free.IsNull())
			{
				for(unsigned int i = 0; i < key_free.size(); i++)
				{
					m_free_ids.push_back(key_free[i].as<unsigned int>());
				}
			}
		}

		// Close database info file
		infostream.close();
	}

	unsigned int create_object(const DatabaseObject &dbo)
	{
		unsigned int do_id = get_next_id();
		if(do_id == 0)
		{
			return 0;
		}

		DCClass *dcc = gDCF->get_class(dbo.dc_id);

		// Build object as YAMl output
		YAML::Emitter out;
		out << YAML::BeginMap
			<< YAML::Key << "id"
			<< YAML::Value << do_id
			<< YAML::Key << "class"
			<< YAML::Value << dcc->get_name()
			<< YAML::Key << "fields"
			<< YAML::Value << YAML::BeginMap;
		for(auto it = dbo.fields.begin(); it != dbo.fields.end(); ++it)
		{
			write_yaml_field(out, it->first, it->second);
		}
		out << YAML::EndMap
			<< YAML::EndMap;

		// Prepare object filename
		std::stringstream filename;
		filename << m_foldername << "/" << do_id << ".yaml";

		// Print YAML to file
		std::fstream file;
		file.open(filename.str(), std::ios_base::out);
		if(file.is_open())
		{
			file << out.c_str();
			file.close();
			return do_id;
		}

		return 0;
	}

	bool get_object(unsigned int do_id, DatabaseObject &dbo)
	{
		yamldb_log.spam() << "Getting object #" << do_id << " ..." << std::endl;

		// Prepare object filename
		std::stringstream filename;
		filename << m_foldername << "/" << do_id << ".yaml";

		// Open database object file
		std::ifstream objstream(filename.str());
		YAML::Node document = YAML::Load(objstream);

		if(document.IsNull()) {
			yamldb_log.error() << "Object #" << do_id << " does not exist in database." << std::endl;
			return false;
		}

		// Read object's DistributedClass
		YAML::Node key_class = document["class"];
		if(key_class.IsNull())
		{
			yamldb_log.error() << filename.str() << " does not contain the 'class' key." << std::endl;
			return false;
		}
		DCClass* dcc = gDCF->get_class_by_name(document["class"].as<std::string>());
		if(!dcc) {
			yamldb_log.error() << "Class '" << document["class"].as<std::string>() << "', loaded from '" << filename.str() << "', does not exist." << std::endl;
			return false;
		}
		dbo.dc_id = dcc->get_number();

		// Read object's fields
		YAML::Node key_fields = document["fields"];
		if(key_fields.IsNull())
		{
			yamldb_log.error() << filename.str() << " does not contain the 'fields' key." << std::endl;
			return false;
		}
		for(auto it = key_fields.begin(); it != key_fields.end(); ++it)
		{
			DCField* field = dcc->get_field_by_name(it->first.as<std::string>());
			if(!field) {
				yamldb_log.warning() << "Field '" << it->first.as<std::string>() << "', loaded from '" << filename.str() << "', does not exist." << std::endl;
				continue;
			}

			dbo.fields[field] = read_yaml_field(field, it->second);
		}

		return true;
	}

	void delete_object(unsigned int do_id)
	{
		std::stringstream filename;
		filename << m_foldername << "/" << do_id << ".yaml";
		yamldb_log.debug() << "Deleting file: " << filename.str() << std::endl;
		if(!std::remove(filename.str().c_str()))
		{
			m_free_ids.insert(m_free_ids.end(), do_id);
			update_info();
		}
	}
};

DBEngineCreator<YAMLEngine> yamlengine_creator("yaml");<commit_msg>YAMLDatabase: Update yamldb to use vector<uchar> for binary values instead of string.<commit_after>#include "IDatabaseEngine.h"
#include "DBEngineFactory.h"

#include "util/Datagram.h"
#include "util/DatagramIterator.h"
#include "core/logger.h"
#include "core/global.h"
#include "dcparser/dcSubatomicType.h"
#include "dcparser/dcAtomicField.h"

#include <yaml-cpp/yaml.h>
#include <fstream>
#include <list>

#define as_bytes(value, len) bytes((unsigned char*)&value, (unsigned char*)&value + len)

static ConfigVariable<std::string> foldername("foldername", "yaml_db");
LogCategory yamldb_log("yamldb", "YAML Database Engine");

class YAMLEngine : public IDatabaseEngine
{
private:
	unsigned int m_next_id;
	std::list<unsigned int> m_free_ids;
	std::string m_foldername;

	// update_info writes m_next_id and m_free_ids to "info.yaml"
	void update_info()
	{
		YAML::Emitter out;
		out << YAML::BeginMap
			<< YAML::Key << "next"
			<< YAML::Value << m_next_id;
		if(!m_free_ids.empty()) {
			out << YAML::Key << "free"
				<< YAML::Value << YAML::BeginSeq;
			for(auto it = m_free_ids.begin(); it != m_free_ids.end(); ++it)
			{
				out << *it;
			}
			out << YAML::EndSeq;
		}
		out << YAML::EndMap;

		std::fstream file;
		file.open(m_foldername + "/info.yaml", std::ios_base::out);
		if(file.is_open())
		{
			file << out.c_str();
			file.close();
		}
	}

	// get_next_id returns the next available id to be used in object creation
	unsigned int get_next_id()
	{
		unsigned int do_id;
		if(m_next_id <= m_max_id)
		{
			do_id = m_next_id++;
		}
		else
		{
			// Dequeue id from list
			if(!m_free_ids.empty())
			{
				do_id = *m_free_ids.begin();
				m_free_ids.remove(do_id);
			}
			else
			{
				return 0;
			}
		}

		update_info();
		return do_id;
	}

	bytes read_yaml_field(DCField* field, YAML::Node node)
	{
		DCAtomicField* atomic = field->as_atomic_field();
		if(atomic && atomic->get_num_elements() == 1)
		{
			switch(atomic->get_element_type(0))
			{
				case ST_char:
				{
					char value = node.as<char>();
					return bytes(value, 1);
				}
				break;
				case ST_int8:
				{
					char value = node.as<char>();
					return bytes(value, 1);
				}
				break;
				case ST_int16:
				{
					short value = node.as<short>();
					return as_bytes(value, 2);
				}
				break;
				case ST_int32:
				{
					int value = node.as<int>();
					return as_bytes(value, 4);
				}
				break;
				case ST_int64:
				{
					long long value = node.as<long long>();
					return as_bytes(value, 8);
				}
				break;
				case ST_uint8:
				{
					unsigned short value = node.as<unsigned char>();
					return as_bytes(value, 1);
				}
				break;
				case ST_uint16:
				{
					unsigned short value = node.as<unsigned short>();
					return as_bytes(value, 2);
				}
				break;
				case ST_uint32:
				{
					unsigned int value = node.as<unsigned int>();
					return as_bytes(value, 4);
				}
				break;
				case ST_uint64:
				{
					unsigned long long value = node.as<unsigned long long>();
					return as_bytes(value, 8);
				}
				break;
				case ST_float64:
				{
					double value = node.as<double>();
					return as_bytes(value, 8);
				}
				break;
				case ST_string:
				{
					std::string value = node.as<std::string>();
					unsigned short length = value.length();

					bytes str = as_bytes(length, 2);
					str.insert(str.end(), value.begin(), value.end());
					return str;
				}
				break;
				default:
					std::string value = node.as<std::string>();
					return bytes(value.begin(), value.end());
			}

		}

		return bytes();
	}

	void write_yaml_field(YAML::Emitter& out, DCField* field, const bytes& value)
	{
		out << YAML::Key << field->get_name();
		DCAtomicField* atomic = field->as_atomic_field();

		if(atomic && atomic->get_num_elements() == 1)
		{
			out << YAML::Value;
			switch(atomic->get_element_type(0))
			{
				case ST_char:
				{
					out << *(char*)(&value[0]);
				}
				break;
				case ST_int8:
				{
					// Cast as short, because char treated as character data
					out << *(short*)(&value[0]);
				}
				break;
				case ST_int16:
				{
					out << *(short*)(&value[0]);
				}
				break;
				case ST_int32:
				{
					out << *(int*)(&value[0]);
				}
				break;
				case ST_int64:
				{
					out << *(long long*)(&value[0]);
				}
				break;
				case ST_uint8:
				{
					out << *(unsigned char*)(&value[0]);
				}
				break;
				case ST_uint16:
				{
					out << *(unsigned short*)(&value[0]);
				}
				break;
				case ST_uint32:
				{
					out << *(unsigned int*)(&value[0]);
				}
				break;
				case ST_uint64:
				{
					out << *(unsigned long long*)(&value[0]);
				}
				break;
				case ST_float64:
				{
					out << *(double*)(&value[0]);
				}
				break;
				case ST_string:
				{
					// Skip the length bytes
					out << std::string(value.begin()+2, value.end());
				}
				break;
				default:
					out << value;
			}
			return;
		}

		yamldb_log.error() << "Recieved non-atomic field: " << field->get_name() << std::endl;
		out << YAML::Value << value;
	}
public:
	YAMLEngine(DBEngineConfig dbeconfig, unsigned int min_id, unsigned int max_id) :
		IDatabaseEngine(dbeconfig, min_id, max_id),
		m_next_id(min_id),
		m_free_ids(),
		m_foldername(foldername.get_rval(m_config))
	{
		// Open database info file
		std::ifstream infostream(m_foldername + "/info.yaml");
		YAML::Node document = YAML::Load(infostream);

		if(!document.IsNull()) {
			// Read next available id
			YAML::Node key_next = document["next"];
			if(!key_next.IsNull())
			{
				m_next_id = document["next"].as<unsigned int>();
			}

			// Read available freed ids
			YAML::Node key_free = document["free"];
			if(!key_free.IsNull())
			{
				for(unsigned int i = 0; i < key_free.size(); i++)
				{
					m_free_ids.push_back(key_free[i].as<unsigned int>());
				}
			}
		}

		// Close database info file
		infostream.close();
	}

	unsigned int create_object(const DatabaseObject &dbo)
	{
		unsigned int do_id = get_next_id();
		if(do_id == 0)
		{
			return 0;
		}

		DCClass *dcc = gDCF->get_class(dbo.dc_id);

		// Build object as YAMl output
		YAML::Emitter out;
		out << YAML::BeginMap
			<< YAML::Key << "id"
			<< YAML::Value << do_id
			<< YAML::Key << "class"
			<< YAML::Value << dcc->get_name()
			<< YAML::Key << "fields"
			<< YAML::Value << YAML::BeginMap;
		for(auto it = dbo.fields.begin(); it != dbo.fields.end(); ++it)
		{
			write_yaml_field(out, it->first, it->second);
		}
		out << YAML::EndMap
			<< YAML::EndMap;

		// Prepare object filename
		std::stringstream filename;
		filename << m_foldername << "/" << do_id << ".yaml";

		// Print YAML to file
		std::fstream file;
		file.open(filename.str(), std::ios_base::out);
		if(file.is_open())
		{
			file << out.c_str();
			file.close();
			return do_id;
		}

		return 0;
	}

	bool get_object(unsigned int do_id, DatabaseObject &dbo)
	{
		yamldb_log.spam() << "Getting object #" << do_id << " ..." << std::endl;

		// Prepare object filename
		std::stringstream filename;
		filename << m_foldername << "/" << do_id << ".yaml";

		// Open database object file
		std::ifstream objstream(filename.str());
		YAML::Node document = YAML::Load(objstream);

		if(document.IsNull()) {
			yamldb_log.error() << "Object #" << do_id << " does not exist in database." << std::endl;
			return false;
		}

		// Read object's DistributedClass
		YAML::Node key_class = document["class"];
		if(key_class.IsNull())
		{
			yamldb_log.error() << filename.str() << " does not contain the 'class' key." << std::endl;
			return false;
		}
		DCClass* dcc = gDCF->get_class_by_name(document["class"].as<std::string>());
		if(!dcc) {
			yamldb_log.error() << "Class '" << document["class"].as<std::string>() << "', loaded from '" << filename.str() << "', does not exist." << std::endl;
			return false;
		}
		dbo.dc_id = dcc->get_number();

		// Read object's fields
		YAML::Node key_fields = document["fields"];
		if(key_fields.IsNull())
		{
			yamldb_log.error() << filename.str() << " does not contain the 'fields' key." << std::endl;
			return false;
		}
		for(auto it = key_fields.begin(); it != key_fields.end(); ++it)
		{
			DCField* field = dcc->get_field_by_name(it->first.as<std::string>());
			if(!field) {
				yamldb_log.warning() << "Field '" << it->first.as<std::string>() << "', loaded from '" << filename.str() << "', does not exist." << std::endl;
				continue;
			}

			dbo.fields[field] = read_yaml_field(field, it->second);
		}

		return true;
	}

	void delete_object(unsigned int do_id)
	{
		std::stringstream filename;
		filename << m_foldername << "/" << do_id << ".yaml";
		yamldb_log.debug() << "Deleting file: " << filename.str() << std::endl;
		if(!std::remove(filename.str().c_str()))
		{
			m_free_ids.insert(m_free_ids.end(), do_id);
			update_info();
		}
	}
};

DBEngineCreator<YAMLEngine> yamlengine_creator("yaml");<|endoftext|>


<commit_before>//===-- MachineFunction.cpp -----------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Collect native machine code information for a function.  This allows
// target-specific information about the generated code to be stored with each
// function.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Config/config.h"
#include <fstream>
#include <iostream>
#include <sstream>

using namespace llvm;

static AnnotationID MF_AID(
  AnnotationManager::getID("CodeGen::MachineCodeForFunction"));

// Out of line virtual function to home classes.
void MachineFunctionPass::virtfn() {}

namespace {
  struct VISIBILITY_HIDDEN Printer : public MachineFunctionPass {
    std::ostream *OS;
    const std::string Banner;

    Printer (std::ostream *_OS, const std::string &_Banner) :
      OS (_OS), Banner (_Banner) { }

    const char *getPassName() const { return "MachineFunction Printer"; }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }

    bool runOnMachineFunction(MachineFunction &MF) {
      (*OS) << Banner;
      MF.print (*OS);
      return false;
    }
  };
}

/// Returns a newly-created MachineFunction Printer pass. The default output
/// stream is std::cerr; the default banner is empty.
///
FunctionPass *llvm::createMachineFunctionPrinterPass(std::ostream *OS,
                                                     const std::string &Banner){
  return new Printer(OS, Banner);
}

namespace {
  struct VISIBILITY_HIDDEN Deleter : public MachineFunctionPass {
    const char *getPassName() const { return "Machine Code Deleter"; }

    bool runOnMachineFunction(MachineFunction &MF) {
      // Delete the annotation from the function now.
      MachineFunction::destruct(MF.getFunction());
      return true;
    }
  };
}

/// MachineCodeDeletion Pass - This pass deletes all of the machine code for
/// the current function, which should happen after the function has been
/// emitted to a .s file or to memory.
FunctionPass *llvm::createMachineCodeDeleter() {
  return new Deleter();
}

//===---------------------------------------------------------------------===//
// MachineFunction implementation
//===---------------------------------------------------------------------===//

MachineBasicBlock* ilist_traits<MachineBasicBlock>::createSentinel() {
  MachineBasicBlock* dummy = new MachineBasicBlock();
  LeakDetector::removeGarbageObject(dummy);
  return dummy;
}

void ilist_traits<MachineBasicBlock>::transferNodesFromList(
  iplist<MachineBasicBlock, ilist_traits<MachineBasicBlock> >& toList,
  ilist_iterator<MachineBasicBlock> first,
  ilist_iterator<MachineBasicBlock> last) {
  if (Parent != toList.Parent)
    for (; first != last; ++first)
      first->Parent = toList.Parent;
}

MachineFunction::MachineFunction(const Function *F,
                                 const TargetMachine &TM)
  : Annotation(MF_AID), Fn(F), Target(TM), UsedPhysRegs(0) {
  SSARegMapping = new SSARegMap();
  MFInfo = 0;
  FrameInfo = new MachineFrameInfo();
  ConstantPool = new MachineConstantPool(TM.getTargetData());
  JumpTableInfo = new MachineJumpTableInfo(TM.getTargetData());
  BasicBlocks.Parent = this;
}

MachineFunction::~MachineFunction() {
  BasicBlocks.clear();
  delete SSARegMapping;
  delete MFInfo;
  delete FrameInfo;
  delete ConstantPool;
  delete JumpTableInfo;
  delete[] UsedPhysRegs;
}

void MachineFunction::dump() const { print(std::cerr); }

void MachineFunction::print(std::ostream &OS) const {
  OS << "# Machine code for " << Fn->getName () << "():\n";

  // Print Frame Information
  getFrameInfo()->print(*this, OS);

  // Print JumpTable Information
  getJumpTableInfo()->print(OS);

  // Print Constant Pool
  getConstantPool()->print(OS);

  const MRegisterInfo *MRI = getTarget().getRegisterInfo();

  if (livein_begin() != livein_end()) {
    OS << "Live Ins:";
    for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I) {
      if (MRI)
        OS << " " << MRI->getName(I->first);
      else
        OS << " Reg #" << I->first;

      if (I->second)
        OS << " in VR#" << I->second << " ";
    }
    OS << "\n";
  }
  if (liveout_begin() != liveout_end()) {
    OS << "Live Outs:";
    for (liveout_iterator I = liveout_begin(), E = liveout_end(); I != E; ++I)
      if (MRI)
        OS << " " << MRI->getName(*I);
      else
        OS << " Reg #" << *I;
    OS << "\n";
  }

  for (const_iterator BB = begin(); BB != end(); ++BB)
    BB->print(OS);

  OS << "\n# End machine code for " << Fn->getName () << "().\n\n";
}

/// CFGOnly flag - This is used to control whether or not the CFG graph printer
/// prints out the contents of basic blocks or not.  This is acceptable because
/// this code is only really used for debugging purposes.
///
static bool CFGOnly = false;

namespace llvm {
  template<>
  struct DOTGraphTraits<const MachineFunction*> : public DefaultDOTGraphTraits {
    static std::string getGraphName(const MachineFunction *F) {
      return "CFG for '" + F->getFunction()->getName() + "' function";
    }

    static std::string getNodeLabel(const MachineBasicBlock *Node,
                                    const MachineFunction *Graph) {
      if (CFGOnly && Node->getBasicBlock() &&
          !Node->getBasicBlock()->getName().empty())
        return Node->getBasicBlock()->getName() + ":";

      std::ostringstream Out;
      if (CFGOnly) {
        Out << Node->getNumber() << ':';
        return Out.str();
      }

      Node->print(Out);

      std::string OutStr = Out.str();
      if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());

      // Process string output to make it nicer...
      for (unsigned i = 0; i != OutStr.length(); ++i)
        if (OutStr[i] == '\n') {                            // Left justify
          OutStr[i] = '\\';
          OutStr.insert(OutStr.begin()+i+1, 'l');
        }
      return OutStr;
    }
  };
}

void MachineFunction::viewCFG() const
{
#ifndef NDEBUG
  ViewGraph(this, "mf" + getFunction()->getName());
#else
  std::cerr << "SelectionDAG::viewGraph is only available in debug builds on "
            << "systems with Graphviz or gv!\n";
#endif // NDEBUG
}

void MachineFunction::viewCFGOnly() const
{
  CFGOnly = true;
  viewCFG();
  CFGOnly = false;
}

// The next two methods are used to construct and to retrieve
// the MachineCodeForFunction object for the given function.
// construct() -- Allocates and initializes for a given function and target
// get()       -- Returns a handle to the object.
//                This should not be called before "construct()"
//                for a given Function.
//
MachineFunction&
MachineFunction::construct(const Function *Fn, const TargetMachine &Tar)
{
  assert(Fn->getAnnotation(MF_AID) == 0 &&
         "Object already exists for this function!");
  MachineFunction* mcInfo = new MachineFunction(Fn, Tar);
  Fn->addAnnotation(mcInfo);
  return *mcInfo;
}

void MachineFunction::destruct(const Function *Fn) {
  bool Deleted = Fn->deleteAnnotation(MF_AID);
  assert(Deleted && "Machine code did not exist for function!");
}

MachineFunction& MachineFunction::get(const Function *F)
{
  MachineFunction *mc = (MachineFunction*)F->getAnnotation(MF_AID);
  assert(mc && "Call construct() method first to allocate the object");
  return *mc;
}

void MachineFunction::clearSSARegMap() {
  delete SSARegMapping;
  SSARegMapping = 0;
}

//===----------------------------------------------------------------------===//
//  MachineFrameInfo implementation
//===----------------------------------------------------------------------===//

void MachineFrameInfo::print(const MachineFunction &MF, std::ostream &OS) const{
  int ValOffset = MF.getTarget().getFrameInfo()->getOffsetOfLocalArea();

  for (unsigned i = 0, e = Objects.size(); i != e; ++i) {
    const StackObject &SO = Objects[i];
    OS << "  <fi #" << (int)(i-NumFixedObjects) << ">: ";
    if (SO.Size == 0)
      OS << "variable sized";
    else
      OS << "size is " << SO.Size << " byte" << (SO.Size != 1 ? "s," : ",");
    OS << " alignment is " << SO.Alignment << " byte"
       << (SO.Alignment != 1 ? "s," : ",");

    if (i < NumFixedObjects)
      OS << " fixed";
    if (i < NumFixedObjects || SO.SPOffset != -1) {
      int Off = SO.SPOffset - ValOffset;
      OS << " at location [SP";
      if (Off > 0)
        OS << "+" << Off;
      else if (Off < 0)
        OS << Off;
      OS << "]";
    }
    OS << "\n";
  }

  if (HasVarSizedObjects)
    OS << "  Stack frame contains variable sized objects\n";
}

void MachineFrameInfo::dump(const MachineFunction &MF) const {
  print(MF, std::cerr);
}

//===----------------------------------------------------------------------===//
//  MachineJumpTableInfo implementation
//===----------------------------------------------------------------------===//

/// getJumpTableIndex - Create a new jump table entry in the jump table info
/// or return an existing one.
///
unsigned MachineJumpTableInfo::getJumpTableIndex(
                                     std::vector<MachineBasicBlock*> &DestBBs) {
  for (unsigned i = 0, e = JumpTables.size(); i != e; ++i)
    if (JumpTables[i].MBBs == DestBBs)
      return i;

  JumpTables.push_back(MachineJumpTableEntry(DestBBs));
  return JumpTables.size()-1;
}

void MachineJumpTableInfo::print(std::ostream &OS) const {
  // FIXME: this is lame, maybe we could print out the MBB numbers or something
  // like {1, 2, 4, 5, 3, 0}
  for (unsigned i = 0, e = JumpTables.size(); i != e; ++i) {
    OS << "  <jt #" << i << "> has " << JumpTables[i].MBBs.size()
       << " entries\n";
  }
}

unsigned MachineJumpTableInfo::getEntrySize() const {
  return TD->getPointerSize();
}

unsigned MachineJumpTableInfo::getAlignment() const {
  return TD->getPointerAlignment();
}

void MachineJumpTableInfo::dump() const { print(std::cerr); }

//===----------------------------------------------------------------------===//
//  MachineConstantPool implementation
//===----------------------------------------------------------------------===//

const Type *MachineConstantPoolEntry::getType() const {
  if (isMachineConstantPoolEntry())
      return Val.MachineCPVal->getType();
  return Val.ConstVal->getType();
}

MachineConstantPool::~MachineConstantPool() {
  for (unsigned i = 0, e = Constants.size(); i != e; ++i)
    if (Constants[i].isMachineConstantPoolEntry())
      delete Constants[i].Val.MachineCPVal;
}

/// getConstantPoolIndex - Create a new entry in the constant pool or return
/// an existing one.  User must specify an alignment in bytes for the object.
///
unsigned MachineConstantPool::getConstantPoolIndex(Constant *C,
                                                   unsigned Alignment) {
  assert(Alignment && "Alignment must be specified!");
  if (Alignment > PoolAlignment) PoolAlignment = Alignment;

  // Check to see if we already have this constant.
  //
  // FIXME, this could be made much more efficient for large constant pools.
  unsigned AlignMask = (1 << Alignment)-1;
  for (unsigned i = 0, e = Constants.size(); i != e; ++i)
    if (Constants[i].Val.ConstVal == C && (Constants[i].Offset & AlignMask)== 0)
      return i;

  unsigned Offset = 0;
  if (!Constants.empty()) {
    Offset = Constants.back().Offset;
    Offset += TD->getTypeSize(Constants.back().getType());
    Offset = (Offset+AlignMask)&~AlignMask;
  }

  Constants.push_back(MachineConstantPoolEntry(C, Offset));
  return Constants.size()-1;
}

unsigned MachineConstantPool::getConstantPoolIndex(MachineConstantPoolValue *V,
                                                   unsigned Alignment) {
  assert(Alignment && "Alignment must be specified!");
  if (Alignment > PoolAlignment) PoolAlignment = Alignment;

  // Check to see if we already have this constant.
  //
  // FIXME, this could be made much more efficient for large constant pools.
  unsigned AlignMask = (1 << Alignment)-1;
  int Idx = V->getExistingMachineCPValue(this, Alignment);
  if (Idx != -1)
    return (unsigned)Idx;

  unsigned Offset = 0;
  if (!Constants.empty()) {
    Offset = Constants.back().Offset;
    Offset += TD->getTypeSize(Constants.back().getType());
    Offset = (Offset+AlignMask)&~AlignMask;
  }

  Constants.push_back(MachineConstantPoolEntry(V, Offset));
  return Constants.size()-1;
}

void MachineConstantPool::print(std::ostream &OS) const {
  for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
    OS << "  <cp #" << i << "> is";
    if (Constants[i].isMachineConstantPoolEntry())
      Constants[i].Val.MachineCPVal->print(OS);
    else
      OS << *(Value*)Constants[i].Val.ConstVal;
    OS << " , offset=" << Constants[i].Offset;
    OS << "\n";
  }
}

void MachineConstantPool::dump() const { print(std::cerr); }
<commit_msg>Use getOffset() instead.<commit_after>//===-- MachineFunction.cpp -----------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Collect native machine code information for a function.  This allows
// target-specific information about the generated code to be stored with each
// function.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Config/config.h"
#include <fstream>
#include <iostream>
#include <sstream>

using namespace llvm;

static AnnotationID MF_AID(
  AnnotationManager::getID("CodeGen::MachineCodeForFunction"));

// Out of line virtual function to home classes.
void MachineFunctionPass::virtfn() {}

namespace {
  struct VISIBILITY_HIDDEN Printer : public MachineFunctionPass {
    std::ostream *OS;
    const std::string Banner;

    Printer (std::ostream *_OS, const std::string &_Banner) :
      OS (_OS), Banner (_Banner) { }

    const char *getPassName() const { return "MachineFunction Printer"; }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }

    bool runOnMachineFunction(MachineFunction &MF) {
      (*OS) << Banner;
      MF.print (*OS);
      return false;
    }
  };
}

/// Returns a newly-created MachineFunction Printer pass. The default output
/// stream is std::cerr; the default banner is empty.
///
FunctionPass *llvm::createMachineFunctionPrinterPass(std::ostream *OS,
                                                     const std::string &Banner){
  return new Printer(OS, Banner);
}

namespace {
  struct VISIBILITY_HIDDEN Deleter : public MachineFunctionPass {
    const char *getPassName() const { return "Machine Code Deleter"; }

    bool runOnMachineFunction(MachineFunction &MF) {
      // Delete the annotation from the function now.
      MachineFunction::destruct(MF.getFunction());
      return true;
    }
  };
}

/// MachineCodeDeletion Pass - This pass deletes all of the machine code for
/// the current function, which should happen after the function has been
/// emitted to a .s file or to memory.
FunctionPass *llvm::createMachineCodeDeleter() {
  return new Deleter();
}

//===---------------------------------------------------------------------===//
// MachineFunction implementation
//===---------------------------------------------------------------------===//

MachineBasicBlock* ilist_traits<MachineBasicBlock>::createSentinel() {
  MachineBasicBlock* dummy = new MachineBasicBlock();
  LeakDetector::removeGarbageObject(dummy);
  return dummy;
}

void ilist_traits<MachineBasicBlock>::transferNodesFromList(
  iplist<MachineBasicBlock, ilist_traits<MachineBasicBlock> >& toList,
  ilist_iterator<MachineBasicBlock> first,
  ilist_iterator<MachineBasicBlock> last) {
  if (Parent != toList.Parent)
    for (; first != last; ++first)
      first->Parent = toList.Parent;
}

MachineFunction::MachineFunction(const Function *F,
                                 const TargetMachine &TM)
  : Annotation(MF_AID), Fn(F), Target(TM), UsedPhysRegs(0) {
  SSARegMapping = new SSARegMap();
  MFInfo = 0;
  FrameInfo = new MachineFrameInfo();
  ConstantPool = new MachineConstantPool(TM.getTargetData());
  JumpTableInfo = new MachineJumpTableInfo(TM.getTargetData());
  BasicBlocks.Parent = this;
}

MachineFunction::~MachineFunction() {
  BasicBlocks.clear();
  delete SSARegMapping;
  delete MFInfo;
  delete FrameInfo;
  delete ConstantPool;
  delete JumpTableInfo;
  delete[] UsedPhysRegs;
}

void MachineFunction::dump() const { print(std::cerr); }

void MachineFunction::print(std::ostream &OS) const {
  OS << "# Machine code for " << Fn->getName () << "():\n";

  // Print Frame Information
  getFrameInfo()->print(*this, OS);

  // Print JumpTable Information
  getJumpTableInfo()->print(OS);

  // Print Constant Pool
  getConstantPool()->print(OS);

  const MRegisterInfo *MRI = getTarget().getRegisterInfo();

  if (livein_begin() != livein_end()) {
    OS << "Live Ins:";
    for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I) {
      if (MRI)
        OS << " " << MRI->getName(I->first);
      else
        OS << " Reg #" << I->first;

      if (I->second)
        OS << " in VR#" << I->second << " ";
    }
    OS << "\n";
  }
  if (liveout_begin() != liveout_end()) {
    OS << "Live Outs:";
    for (liveout_iterator I = liveout_begin(), E = liveout_end(); I != E; ++I)
      if (MRI)
        OS << " " << MRI->getName(*I);
      else
        OS << " Reg #" << *I;
    OS << "\n";
  }

  for (const_iterator BB = begin(); BB != end(); ++BB)
    BB->print(OS);

  OS << "\n# End machine code for " << Fn->getName () << "().\n\n";
}

/// CFGOnly flag - This is used to control whether or not the CFG graph printer
/// prints out the contents of basic blocks or not.  This is acceptable because
/// this code is only really used for debugging purposes.
///
static bool CFGOnly = false;

namespace llvm {
  template<>
  struct DOTGraphTraits<const MachineFunction*> : public DefaultDOTGraphTraits {
    static std::string getGraphName(const MachineFunction *F) {
      return "CFG for '" + F->getFunction()->getName() + "' function";
    }

    static std::string getNodeLabel(const MachineBasicBlock *Node,
                                    const MachineFunction *Graph) {
      if (CFGOnly && Node->getBasicBlock() &&
          !Node->getBasicBlock()->getName().empty())
        return Node->getBasicBlock()->getName() + ":";

      std::ostringstream Out;
      if (CFGOnly) {
        Out << Node->getNumber() << ':';
        return Out.str();
      }

      Node->print(Out);

      std::string OutStr = Out.str();
      if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());

      // Process string output to make it nicer...
      for (unsigned i = 0; i != OutStr.length(); ++i)
        if (OutStr[i] == '\n') {                            // Left justify
          OutStr[i] = '\\';
          OutStr.insert(OutStr.begin()+i+1, 'l');
        }
      return OutStr;
    }
  };
}

void MachineFunction::viewCFG() const
{
#ifndef NDEBUG
  ViewGraph(this, "mf" + getFunction()->getName());
#else
  std::cerr << "SelectionDAG::viewGraph is only available in debug builds on "
            << "systems with Graphviz or gv!\n";
#endif // NDEBUG
}

void MachineFunction::viewCFGOnly() const
{
  CFGOnly = true;
  viewCFG();
  CFGOnly = false;
}

// The next two methods are used to construct and to retrieve
// the MachineCodeForFunction object for the given function.
// construct() -- Allocates and initializes for a given function and target
// get()       -- Returns a handle to the object.
//                This should not be called before "construct()"
//                for a given Function.
//
MachineFunction&
MachineFunction::construct(const Function *Fn, const TargetMachine &Tar)
{
  assert(Fn->getAnnotation(MF_AID) == 0 &&
         "Object already exists for this function!");
  MachineFunction* mcInfo = new MachineFunction(Fn, Tar);
  Fn->addAnnotation(mcInfo);
  return *mcInfo;
}

void MachineFunction::destruct(const Function *Fn) {
  bool Deleted = Fn->deleteAnnotation(MF_AID);
  assert(Deleted && "Machine code did not exist for function!");
}

MachineFunction& MachineFunction::get(const Function *F)
{
  MachineFunction *mc = (MachineFunction*)F->getAnnotation(MF_AID);
  assert(mc && "Call construct() method first to allocate the object");
  return *mc;
}

void MachineFunction::clearSSARegMap() {
  delete SSARegMapping;
  SSARegMapping = 0;
}

//===----------------------------------------------------------------------===//
//  MachineFrameInfo implementation
//===----------------------------------------------------------------------===//

void MachineFrameInfo::print(const MachineFunction &MF, std::ostream &OS) const{
  int ValOffset = MF.getTarget().getFrameInfo()->getOffsetOfLocalArea();

  for (unsigned i = 0, e = Objects.size(); i != e; ++i) {
    const StackObject &SO = Objects[i];
    OS << "  <fi #" << (int)(i-NumFixedObjects) << ">: ";
    if (SO.Size == 0)
      OS << "variable sized";
    else
      OS << "size is " << SO.Size << " byte" << (SO.Size != 1 ? "s," : ",");
    OS << " alignment is " << SO.Alignment << " byte"
       << (SO.Alignment != 1 ? "s," : ",");

    if (i < NumFixedObjects)
      OS << " fixed";
    if (i < NumFixedObjects || SO.SPOffset != -1) {
      int Off = SO.SPOffset - ValOffset;
      OS << " at location [SP";
      if (Off > 0)
        OS << "+" << Off;
      else if (Off < 0)
        OS << Off;
      OS << "]";
    }
    OS << "\n";
  }

  if (HasVarSizedObjects)
    OS << "  Stack frame contains variable sized objects\n";
}

void MachineFrameInfo::dump(const MachineFunction &MF) const {
  print(MF, std::cerr);
}

//===----------------------------------------------------------------------===//
//  MachineJumpTableInfo implementation
//===----------------------------------------------------------------------===//

/// getJumpTableIndex - Create a new jump table entry in the jump table info
/// or return an existing one.
///
unsigned MachineJumpTableInfo::getJumpTableIndex(
                                     std::vector<MachineBasicBlock*> &DestBBs) {
  for (unsigned i = 0, e = JumpTables.size(); i != e; ++i)
    if (JumpTables[i].MBBs == DestBBs)
      return i;

  JumpTables.push_back(MachineJumpTableEntry(DestBBs));
  return JumpTables.size()-1;
}

void MachineJumpTableInfo::print(std::ostream &OS) const {
  // FIXME: this is lame, maybe we could print out the MBB numbers or something
  // like {1, 2, 4, 5, 3, 0}
  for (unsigned i = 0, e = JumpTables.size(); i != e; ++i) {
    OS << "  <jt #" << i << "> has " << JumpTables[i].MBBs.size()
       << " entries\n";
  }
}

unsigned MachineJumpTableInfo::getEntrySize() const {
  return TD->getPointerSize();
}

unsigned MachineJumpTableInfo::getAlignment() const {
  return TD->getPointerAlignment();
}

void MachineJumpTableInfo::dump() const { print(std::cerr); }

//===----------------------------------------------------------------------===//
//  MachineConstantPool implementation
//===----------------------------------------------------------------------===//

const Type *MachineConstantPoolEntry::getType() const {
  if (isMachineConstantPoolEntry())
      return Val.MachineCPVal->getType();
  return Val.ConstVal->getType();
}

MachineConstantPool::~MachineConstantPool() {
  for (unsigned i = 0, e = Constants.size(); i != e; ++i)
    if (Constants[i].isMachineConstantPoolEntry())
      delete Constants[i].Val.MachineCPVal;
}

/// getConstantPoolIndex - Create a new entry in the constant pool or return
/// an existing one.  User must specify an alignment in bytes for the object.
///
unsigned MachineConstantPool::getConstantPoolIndex(Constant *C,
                                                   unsigned Alignment) {
  assert(Alignment && "Alignment must be specified!");
  if (Alignment > PoolAlignment) PoolAlignment = Alignment;

  // Check to see if we already have this constant.
  //
  // FIXME, this could be made much more efficient for large constant pools.
  unsigned AlignMask = (1 << Alignment)-1;
  for (unsigned i = 0, e = Constants.size(); i != e; ++i)
    if (Constants[i].Val.ConstVal == C && (Constants[i].Offset & AlignMask)== 0)
      return i;

  unsigned Offset = 0;
  if (!Constants.empty()) {
    Offset = Constants.back().getOffset();
    Offset += TD->getTypeSize(Constants.back().getType());
    Offset = (Offset+AlignMask)&~AlignMask;
  }

  Constants.push_back(MachineConstantPoolEntry(C, Offset));
  return Constants.size()-1;
}

unsigned MachineConstantPool::getConstantPoolIndex(MachineConstantPoolValue *V,
                                                   unsigned Alignment) {
  assert(Alignment && "Alignment must be specified!");
  if (Alignment > PoolAlignment) PoolAlignment = Alignment;

  // Check to see if we already have this constant.
  //
  // FIXME, this could be made much more efficient for large constant pools.
  unsigned AlignMask = (1 << Alignment)-1;
  int Idx = V->getExistingMachineCPValue(this, Alignment);
  if (Idx != -1)
    return (unsigned)Idx;

  unsigned Offset = 0;
  if (!Constants.empty()) {
    Offset = Constants.back().getOffset();
    Offset += TD->getTypeSize(Constants.back().getType());
    Offset = (Offset+AlignMask)&~AlignMask;
  }

  Constants.push_back(MachineConstantPoolEntry(V, Offset));
  return Constants.size()-1;
}

void MachineConstantPool::print(std::ostream &OS) const {
  for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
    OS << "  <cp #" << i << "> is";
    if (Constants[i].isMachineConstantPoolEntry())
      Constants[i].Val.MachineCPVal->print(OS);
    else
      OS << *(Value*)Constants[i].Val.ConstVal;
    OS << " , offset=" << Constants[i].Offset;
    OS << "\n";
  }
}

void MachineConstantPool::dump() const { print(std::cerr); }
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "URISupport.hpp"

#include <algorithm>
#include <vector>

#include <util/PlatformUtils.hpp>

#include "STLHelper.hpp"

URISupport::URLAutoPtrType
URISupport::getURLFromString(const XalanDOMString&	urlString)
{
#if !defined(XALAN_NO_NAMESPACES)
	using std::auto_ptr;
#endif

	URLAutoPtrType	url(new XMLURL);

	try
	{
		XalanDOMString	theNormalizedURI(clone(urlString));

		// Let's see what sort of URI we have...
		const unsigned int	len = length(theNormalizedURI);
		const unsigned int	index = indexOf(theNormalizedURI, ':');

		bool				protocolPresent = false;

		if (index != len)
		{
			// $$$ ToDo: XMLURL::lookupByName() is supposed to be static, but is not.
			const XMLURL::Protocols		theProtocol =
				XMLURL().lookupByName(c_wstr(substring(theNormalizedURI, 0 , index)));

			if (theProtocol != XMLURL::Unknown)
			{
				protocolPresent = true;
			}
		}

		if (protocolPresent == true)
		{
			NormalizeURIText(theNormalizedURI);
		}
		else
		{
			// Assume it's a file specification...
			array_auto_ptr<XMLCh>	theFullPath(XMLPlatformUtils::getFullPath(c_wstr(urlString)));
			assert(theFullPath.get() != 0);

			theNormalizedURI = theFullPath.get();
			assert(length(theNormalizedURI) > 0);

			NormalizeURIText(theNormalizedURI);

			const XalanDOMString	theFilePrefix(indexOf(theNormalizedURI, '/') == 0 ?
						XALAN_STATIC_UCODE_STRING("file://") :
						XALAN_STATIC_UCODE_STRING("file:///"));

			theNormalizedURI = theFilePrefix + theNormalizedURI;
		}

		url->setURL(c_wstr(theNormalizedURI));
	}
	catch (...)
	{
		throw ("Error! Cannot create url for: " + urlString);
	}

	return url;
}

URISupport::URLAutoPtrType
URISupport::getURLFromString(
			const XalanDOMString&	urlString,
			const XalanDOMString&	base)
{
	XalanDOMString	context(clone(base));

	NormalizeURIText(context);

	const unsigned int	theContextLength = length(context);

	const unsigned int	indexOfSlash = theContextLength == 0 ? 0 : lastIndexOf(context, '/');

	bool				hasPath = true;

	if (indexOfSlash < theContextLength)
	{
		context = substring(context, 0, indexOfSlash + 1);
	}
	else
	{
		hasPath = false;
	}

	// OK, now let's look at the urlString...

	// Is there a colon, indicating some sort of drive spec, or protocol?
	const unsigned int	theURLStringLength = length(urlString);
	const unsigned int	theColonIndex = indexOf(urlString, ':');

	if (theColonIndex == theURLStringLength)
	{
		// No colon, so just use the urlString as is...

		// Strip off file name from context...
		if (indexOfSlash < theContextLength)
		{
			context = substring(context, 0, indexOfSlash + 1);
		}

		if (hasPath == true)
		{
			context += urlString;
		}
		else
		{
			context = urlString;
		}
	}
	else
	{
		const XalanDOMString		theProtocolString(substring(urlString, 0, theColonIndex));

		// $$$ ToDo: XMLURL::lookupByName() is supposed to be static, but is not.
		const XMLURL::Protocols		theProtocol =
			XMLURL().lookupByName(c_wstr(theProtocolString));

		if (theColonIndex == 1 &&
			theProtocol == XMLURL::Unknown)
		{
			// Ahh, it's a drive letter, so ignore the context...
			context = urlString;
		}
		else
		{
			// It's a protocol...
			if (startsWith(context, theProtocolString) == true)
			{
				// They share the same protocol...

				// Strip off file name from context...
				if (indexOfSlash < theContextLength)
				{
					context = substring(context, 0, indexOfSlash + 1);
				}

				// OK, everything looks good, so strip off the protocol and colon...
				context += substring(urlString, theColonIndex + 1, theURLStringLength);
			}
			else
			{
				// OK, not the same protocol, so what can we do???
				context = urlString;
			}
		}
	}

	return getURLFromString(context);
}

XalanDOMString&
URISupport::NormalizeURIText(XalanDOMString&	uriString)
{
#if !defined(XALAN_NO_NAMESPACES)
	using std::vector;
	using std::replace;
#endif

	// OK, look for a quick, cheap exit...
	const unsigned int	len = length(uriString);
	const unsigned int	index = indexOf(uriString, '\\');

	if (index != len)
	{
		XalanDOMCharVectorType	theVector =
			MakeXalanDOMCharVector(uriString);

		// Start replacing at the index point, since that's the
		// first one...
		replace(theVector.begin(), theVector.end(), '\\', '/');

		uriString = XalanDOMString(&theVector[0]);
	}

	return uriString;
}

URISupport::InvalidURIException::InvalidURIException(const XalanDOMString&	theMessage) :
	XSLException(theMessage,
				 XALAN_STATIC_UCODE_STRING("InvalidURIException"))
{
}

URISupport::InvalidURIException::~InvalidURIException()
{
}
<commit_msg>New functions.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "URISupport.hpp"

#include <algorithm>
#include <vector>

#include <util/PlatformUtils.hpp>

#include "STLHelper.hpp"

URISupport::URLAutoPtrType
URISupport::getURLFromString(const XalanDOMString&	urlString)
{
	URLAutoPtrType	url(new XMLURL);

	try
	{
		url->setURL(c_wstr(getURLStringFromString(urlString)));
	}
	catch (...)
	{
		throw ("Error! Cannot create url for: " + urlString);
	}
	return url;
}

XalanDOMString
URISupport::getURLStringFromString(const XalanDOMString&	urlString)
{
	XalanDOMString	theNormalizedURI(clone(urlString));

	// Let's see what sort of URI we have...
	const unsigned int	len = length(theNormalizedURI);
	const unsigned int	index = indexOf(theNormalizedURI, ':');

	bool				protocolPresent = false;

	if (index != len)
	{
		// $$$ ToDo: XMLURL::lookupByName() is supposed to be static, but is not.
		const XMLURL::Protocols		theProtocol =
			XMLURL().lookupByName(c_wstr(substring(theNormalizedURI, 0 , index)));

		if (theProtocol != XMLURL::Unknown)
		{
			protocolPresent = true;
		}
	}

	if (protocolPresent == true)
	{
		NormalizeURIText(theNormalizedURI);
	}
	else
	{
		// Assume it's a file specification...
		array_auto_ptr<XMLCh>	theFullPath(XMLPlatformUtils::getFullPath(c_wstr(urlString)));
		assert(theFullPath.get() != 0);

		theNormalizedURI = theFullPath.get();
		assert(length(theNormalizedURI) > 0);

		NormalizeURIText(theNormalizedURI);

		const XalanDOMString	theFilePrefix(indexOf(theNormalizedURI, '/') == 0 ?
					XALAN_STATIC_UCODE_STRING("file://") :
					XALAN_STATIC_UCODE_STRING("file:///"));

		theNormalizedURI = theFilePrefix + theNormalizedURI;
	}

	return theNormalizedURI;
}

URISupport::URLAutoPtrType
URISupport::getURLFromString(
			const XalanDOMString&	urlString,
			const XalanDOMString&	base)
{
	return getURLFromString(getURLStringFromString(urlString, base));
}

XalanDOMString
URISupport::getURLStringFromString(
			const XalanDOMString&	urlString,
			const XalanDOMString&	base)
{
	XalanDOMString	context(clone(base));

	NormalizeURIText(context);

	const unsigned int	theContextLength = length(context);

	const unsigned int	indexOfSlash = theContextLength == 0 ? 0 : lastIndexOf(context, '/');

	bool				hasPath = true;

	if (indexOfSlash < theContextLength)
	{
		context = substring(context, 0, indexOfSlash + 1);
	}
	else
	{
		hasPath = false;
	}

	// OK, now let's look at the urlString...

	// Is there a colon, indicating some sort of drive spec, or protocol?
	const unsigned int	theURLStringLength = length(urlString);
	const unsigned int	theColonIndex = indexOf(urlString, ':');

	if (theColonIndex == theURLStringLength)
	{
		// No colon, so just use the urlString as is...

		// Strip off file name from context...
		if (indexOfSlash < theContextLength)
		{
			context = substring(context, 0, indexOfSlash + 1);
		}

		if (hasPath == true)
		{
			context += urlString;
		}
		else
		{
			context = urlString;
		}
	}
	else
	{
		const XalanDOMString		theProtocolString(substring(urlString, 0, theColonIndex));

		// $$$ ToDo: XMLURL::lookupByName() is supposed to be static, but is not.
		const XMLURL::Protocols		theProtocol =
			XMLURL().lookupByName(c_wstr(theProtocolString));

		if (theColonIndex == 1 &&
			theProtocol == XMLURL::Unknown)
		{
			// Ahh, it's a drive letter, so ignore the context...
			context = urlString;
		}
		else
		{
			// It's a protocol...
			if (startsWith(context, theProtocolString) == true)
			{
				// They share the same protocol...

				// Strip off file name from context...
				if (indexOfSlash < theContextLength)
				{
					context = substring(context, 0, indexOfSlash + 1);
				}

				// OK, everything looks good, so strip off the protocol and colon...
				context += substring(urlString, theColonIndex + 1, theURLStringLength);
			}
			else
			{
				// OK, not the same protocol, so what can we do???
				context = urlString;
			}
		}
	}

	return getURLStringFromString(context);
}

XalanDOMString&
URISupport::NormalizeURIText(XalanDOMString&	uriString)
{
#if !defined(XALAN_NO_NAMESPACES)
	using std::replace;
#endif

	// OK, look for a quick, cheap exit...
	const unsigned int	len = length(uriString);
	const unsigned int	index = indexOf(uriString, '\\');

	if (index != len)
	{
		XalanDOMCharVectorType	theVector =
			MakeXalanDOMCharVector(uriString);

		// Start replacing at the index point, since that's the
		// first one...
		replace(theVector.begin(), theVector.end(), '\\', '/');

		uriString = XalanDOMString(&theVector[0]);
	}

	return uriString;
}

URISupport::InvalidURIException::InvalidURIException(const XalanDOMString&	theMessage) :
	XSLException(theMessage,
				 XALAN_STATIC_UCODE_STRING("InvalidURIException"))
{
}

URISupport::InvalidURIException::~InvalidURIException()
{
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: tdservice.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kso $ $Date: 2002-11-13 16:01:21 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif

#ifndef _STOC_RDBTDP_BASE_HXX
#include "base.hxx"
#endif

using namespace com::sun::star;

namespace stoc_rdbtdp
{

//==================================================================================================
//
// class PropertyTypeDescriptionImpl
//
//==================================================================================================
class PropertyTypeDescriptionImpl : public WeakImplHelper1< XPropertyTypeDescription >
{
    OUString                      _aName;
    Reference< XTypeDescription > _xTD;
    sal_Int16                     _nFlags;

public:
    PropertyTypeDescriptionImpl( const OUString & rName,
                                 const Reference< XTypeDescription > & xTD,
                                 sal_Int16 nFlags )
    : _aName( rName ), _xTD( xTD ), _nFlags( nFlags )
    {
        g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
    }
    virtual ~PropertyTypeDescriptionImpl();

    // XTypeDescription
    virtual TypeClass SAL_CALL getTypeClass()
        throw( RuntimeException );
    virtual OUString SAL_CALL getName()
        throw( RuntimeException );

    // XPropertyTypeDescription
    virtual sal_Int16 SAL_CALL getPropertyFlags()
        throw ( RuntimeException );
    virtual Reference< XTypeDescription > SAL_CALL getPropertyTypeDescription()
        throw ( RuntimeException );
};

//__________________________________________________________________________________________________
// virtual
PropertyTypeDescriptionImpl::~PropertyTypeDescriptionImpl()
{
    g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}

// XTypeDescription
//__________________________________________________________________________________________________
// virtual
TypeClass PropertyTypeDescriptionImpl::getTypeClass()
    throw ( RuntimeException )
{
    return TypeClass_PROPERTY;
}
//__________________________________________________________________________________________________
// virtual
OUString PropertyTypeDescriptionImpl::getName()
    throw ( RuntimeException )
{
    return _aName;
}

// XPropertyTypeDescription
//__________________________________________________________________________________________________
// virtual
sal_Int16 SAL_CALL PropertyTypeDescriptionImpl::getPropertyFlags()
    throw ( RuntimeException )
{
    return _nFlags;
}

//__________________________________________________________________________________________________
// virtual
Reference< XTypeDescription > SAL_CALL
PropertyTypeDescriptionImpl::getPropertyTypeDescription()
    throw ( RuntimeException )
{
    return _xTD;
}

//==================================================================================================
//
// ServiceTypeDescriptionImpl implementation
//
//==================================================================================================

//__________________________________________________________________________________________________
// virtual
ServiceTypeDescriptionImpl::~ServiceTypeDescriptionImpl()
{
    delete _pMandatoryServices;
    delete _pOptionalServices;
    delete _pMandatoryInterfaces;
    delete _pOptionalInterfaces;
    delete _pProps;

    g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}

// XTypeDescription
//__________________________________________________________________________________________________
// virtual
TypeClass ServiceTypeDescriptionImpl::getTypeClass()
    throw(::com::sun::star::uno::RuntimeException)
{
    return TypeClass_SERVICE;
}
//__________________________________________________________________________________________________
// virtual
OUString ServiceTypeDescriptionImpl::getName()
    throw(::com::sun::star::uno::RuntimeException)
{
    return _aName;
}

// XServiceTypeDescription
//__________________________________________________________________________________________________
// virtual
Sequence< Reference< XServiceTypeDescription > > SAL_CALL
ServiceTypeDescriptionImpl::getMandatoryServices()
    throw ( RuntimeException )
{
    getReferences();
    return *_pMandatoryServices;
}

//__________________________________________________________________________________________________
// virtual
Sequence< Reference< XServiceTypeDescription > > SAL_CALL
ServiceTypeDescriptionImpl::getOptionalServices()
    throw ( RuntimeException )
{
    getReferences();
    return *_pOptionalServices;
}

//__________________________________________________________________________________________________
// virtual
Sequence< Reference< XInterfaceTypeDescription > > SAL_CALL
ServiceTypeDescriptionImpl::getMandatoryInterfaces()
    throw ( RuntimeException )
{
    getReferences();
    return *_pMandatoryInterfaces;
}

//__________________________________________________________________________________________________
// virtual
Sequence< Reference< XInterfaceTypeDescription > > SAL_CALL
ServiceTypeDescriptionImpl::getOptionalInterfaces()
    throw ( RuntimeException )
{
    getReferences();
    return *_pOptionalInterfaces;
}

//__________________________________________________________________________________________________
// virtual
Sequence< Reference< XPropertyTypeDescription > > SAL_CALL
ServiceTypeDescriptionImpl::getProperties()
    throw ( RuntimeException )
{
    if ( !_pProps )
    {
        RegistryTypeReaderLoader aLoader;
        RegistryTypeReader aReader(
            aLoader, (const sal_uInt8 *)_aBytes.getConstArray(),
            _aBytes.getLength(), sal_False );

        sal_uInt16 nFields = (sal_uInt16)aReader.getFieldCount();
        Sequence< Reference< XPropertyTypeDescription > > * pTempProps =
            new Sequence< Reference< XPropertyTypeDescription > >( nFields );
        Reference< XPropertyTypeDescription > * pProps = pTempProps->getArray();

        while ( nFields-- )
        {
            // name
            OUStringBuffer aName( _aName );
            aName.appendAscii( "." );
            aName.append( aReader.getFieldName( nFields ) );

            // type description
            Reference< XTypeDescription > xTD;
            try
            {
                _xTDMgr->getByHierarchicalName(
                    aReader.getFieldType( nFields ).replace( '/', '.' ) )
                        >>= xTD;
            }
            catch ( NoSuchElementException const & )
            {
            }
            OSL_ENSURE( xTD.is(), "### no type description for property!" );

            // flags
            RTFieldAccess nFlags = aReader.getFieldAccess( nFields );

            sal_Int16 nAttribs = 0;
            if ( nFlags & RT_ACCESS_READONLY )
                nAttribs |= beans::PropertyAttribute::READONLY;
            if ( nFlags & RT_ACCESS_OPTIONAL )
                nAttribs |= beans::PropertyAttribute::OPTIONAL;
            if ( nFlags & RT_ACCESS_MAYBEVOID )
                nAttribs |= beans::PropertyAttribute::MAYBEVOID;
            if ( nFlags & RT_ACCESS_BOUND )
                nAttribs |= beans::PropertyAttribute::BOUND;
            if ( nFlags & RT_ACCESS_CONSTRAINED )
                nAttribs |= beans::PropertyAttribute::CONSTRAINED;
            if ( nFlags & RT_ACCESS_TRANSIENT )
                nAttribs |= beans::PropertyAttribute::TRANSIENT;
            if ( nFlags & RT_ACCESS_MAYBEAMBIGUOUS )
                nAttribs |= beans::PropertyAttribute::MAYBEAMBIGUOUS;
            if ( nFlags & RT_ACCESS_MAYBEDEFAULT )
                nAttribs |= beans::PropertyAttribute::MAYBEDEFAULT;
            if ( nFlags & RT_ACCESS_REMOVEABLE )
                nAttribs |= beans::PropertyAttribute::REMOVEABLE;

            OSL_ENSURE( !(nFlags & RT_ACCESS_PROPERTY),
                        "### RT_ACCESS_PROPERTY is unexpected here!" );
            OSL_ENSURE( !(nFlags & RT_ACCESS_ATTRIBUTE),
                        "### RT_ACCESS_ATTRIBUTE is unexpected here!" );
            OSL_ENSURE( !(nFlags & RT_ACCESS_CONST),
                        "### RT_ACCESS_CONST is unexpected here!" );
            // always set, unless RT_ACCESS_READONLY is set.
            //OSL_ENSURE( !(nFlags & RT_ACCESS_READWRITE),
            //            "### RT_ACCESS_READWRITE is unexpected here" );
            OSL_ENSURE( !(nFlags & RT_ACCESS_DEFAULT),
                        "### RT_ACCESS_DEAFAULT is unexpected here" );

            pProps[ nFields ]
                = new PropertyTypeDescriptionImpl( aName.makeStringAndClear(),
                                                   xTD,
                                                   nAttribs );
        }

        ClearableMutexGuard aGuard( _aMutex );
        if ( _pProps )
        {
            aGuard.clear();
            delete pTempProps;
        }
        else
        {
            _pProps = pTempProps;
        }
    }

    return *_pProps;
}

//__________________________________________________________________________________________________
void ServiceTypeDescriptionImpl::getReferences()
    throw ( RuntimeException )
{
    if ( !_pMandatoryServices || !_pOptionalServices ||
         !_pMandatoryInterfaces || !_pOptionalInterfaces )
    {
        RegistryTypeReaderLoader aLoader;
        RegistryTypeReader aReader(
            aLoader, (const sal_uInt8 *)_aBytes.getConstArray(),
            _aBytes.getLength(), sal_False );

        sal_uInt32 nRefs = aReader.getReferenceCount();
        Sequence< Reference < XServiceTypeDescription > > * pTempMS
            = new Sequence< Reference < XServiceTypeDescription > >( nRefs );
        Sequence< Reference < XServiceTypeDescription > > * pTempOS
            = new Sequence< Reference < XServiceTypeDescription > >( nRefs );
        Sequence< Reference < XInterfaceTypeDescription > > * pTempMI
            = new Sequence< Reference < XInterfaceTypeDescription > >( nRefs );
        Sequence< Reference < XInterfaceTypeDescription > > * pTempOI
            = new Sequence< Reference < XInterfaceTypeDescription > >( nRefs );
        sal_uInt32 nMS = 0;
        sal_uInt32 nOS = 0;
        sal_uInt32 nMI = 0;
        sal_uInt32 nOI = 0;

        while ( nRefs-- )
        {
            RTReferenceType eType = aReader.getReferenceType( nRefs );
            switch ( eType )
            {
                case RT_REF_EXPORTS: // service
                {
                    uno::Any aTypeDesc;
                    try
                    {
                        aTypeDesc = _xTDMgr->getByHierarchicalName(
                            aReader.getReferenceName( nRefs )
                                .replace( '/', '.' ) );
                    }
                    catch ( NoSuchElementException const & )
                    {
                    }
                    OSL_ENSURE( aTypeDesc.hasValue(),
                                "### no type description!" );

                    RTFieldAccess nAccess = aReader.getReferenceAccess( nRefs );
                    if ( nAccess & RT_ACCESS_OPTIONAL )
                    {
                        // optional service
                        aTypeDesc >>= (*pTempOS)[ nOS ];
                        OSL_ENSURE( (*pTempOS)[ nOS ].is(),
                                    "### wrong type description type!" );
                        nOS++;
                    }
                    else
                    {
                        // mandatory service
                        aTypeDesc >>= (*pTempMS)[ nMS ];
                        OSL_ENSURE( (*pTempMS)[ nMS ].is(),
                                    "### wrong type description type!" );
                        nMS++;
                    }
                    break;
                }
                case RT_REF_SUPPORTS: // interface
                {
                    uno::Any aTypeDesc;
                    try
                    {
                        aTypeDesc = _xTDMgr->getByHierarchicalName(
                            aReader.getReferenceName( nRefs )
                                .replace( '/', '.' ) );
                    }
                    catch ( NoSuchElementException const & )
                    {
                    }
                    OSL_ENSURE( aTypeDesc.hasValue(),
                                "### no type description!" );

                    RTFieldAccess nAccess = aReader.getReferenceAccess( nRefs );
                    if ( nAccess & RT_ACCESS_OPTIONAL )
                    {
                        // optional interface
                        aTypeDesc >>= (*pTempOI)[ nOI ];
                        OSL_ENSURE( (*pTempOI)[ nOI ].is(),
                                    "### wrong type description type!" );
                        nOI++;
                    }
                    else
                    {
                        // mandatory interface
                        aTypeDesc >>= (*pTempMI)[ nMI ];
                        OSL_ENSURE( (*pTempMI)[ nMI ].is(),
                                    "### wrong type description type!" );
                        nMI++;
                    }
                    break;
                }
                case RT_REF_INVALID:
                case RT_REF_OBSERVES:
                case RT_REF_NEEDS:
                default:
                    OSL_ENSURE( sal_False,
                                "### unsupported reference type!" );
                    break;
            }
        }

        {
            ClearableMutexGuard aGuard( _aMutex );
            if ( _pMandatoryServices )
            {
                aGuard.clear();
                delete pTempMS;
            }
            else
            {
                pTempMS->realloc( nMS );
                _pMandatoryServices = pTempMS;
            }
        }

        {
            ClearableMutexGuard aGuard( _aMutex );
            if ( _pOptionalServices )
            {
                aGuard.clear();
                delete pTempOS;
            }
            else
            {
                pTempOS->realloc( nOS );
                _pOptionalServices = pTempOS;
            }
        }

        {
            ClearableMutexGuard aGuard( _aMutex );
            if ( _pMandatoryInterfaces )
            {
                aGuard.clear();
                delete pTempMI;
            }
            else
            {
                pTempMI->realloc( nMI );
                _pMandatoryInterfaces = pTempMI;
            }
        }

        {
            ClearableMutexGuard aGuard( _aMutex );
            if ( _pOptionalInterfaces )
            {
                aGuard.clear();
                delete pTempOI;
            }
            else
            {
                pTempOI->realloc( nOI );
                _pOptionalInterfaces = pTempOI;
            }
        }
    }
}

}

<commit_msg>INTEGRATION: CWS jl3 (1.3.82); FILE MERGED 2003/12/19 11:32:31 dbo 1.3.82.1: #114506# cleanup<commit_after>/*************************************************************************
 *
 *  $RCSfile: tdservice.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2004-03-25 14:49:07 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif

#ifndef _STOC_RDBTDP_BASE_HXX
#include "base.hxx"
#endif

using namespace com::sun::star;

namespace stoc_rdbtdp
{

//==================================================================================================
//
// class PropertyTypeDescriptionImpl
//
//==================================================================================================
class PropertyTypeDescriptionImpl : public WeakImplHelper1< XPropertyTypeDescription >
{
    OUString                      _aName;
    Reference< XTypeDescription > _xTD;
    sal_Int16                     _nFlags;

public:
    PropertyTypeDescriptionImpl( const OUString & rName,
                                 const Reference< XTypeDescription > & xTD,
                                 sal_Int16 nFlags )
    : _aName( rName ), _xTD( xTD ), _nFlags( nFlags )
    {
        g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
    }
    virtual ~PropertyTypeDescriptionImpl();

    // XTypeDescription
    virtual TypeClass SAL_CALL getTypeClass()
        throw( RuntimeException );
    virtual OUString SAL_CALL getName()
        throw( RuntimeException );

    // XPropertyTypeDescription
    virtual sal_Int16 SAL_CALL getPropertyFlags()
        throw ( RuntimeException );
    virtual Reference< XTypeDescription > SAL_CALL getPropertyTypeDescription()
        throw ( RuntimeException );
};

//__________________________________________________________________________________________________
// virtual
PropertyTypeDescriptionImpl::~PropertyTypeDescriptionImpl()
{
    g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}

// XTypeDescription
//__________________________________________________________________________________________________
// virtual
TypeClass PropertyTypeDescriptionImpl::getTypeClass()
    throw ( RuntimeException )
{
    return TypeClass_PROPERTY;
}
//__________________________________________________________________________________________________
// virtual
OUString PropertyTypeDescriptionImpl::getName()
    throw ( RuntimeException )
{
    return _aName;
}

// XPropertyTypeDescription
//__________________________________________________________________________________________________
// virtual
sal_Int16 SAL_CALL PropertyTypeDescriptionImpl::getPropertyFlags()
    throw ( RuntimeException )
{
    return _nFlags;
}

//__________________________________________________________________________________________________
// virtual
Reference< XTypeDescription > SAL_CALL
PropertyTypeDescriptionImpl::getPropertyTypeDescription()
    throw ( RuntimeException )
{
    return _xTD;
}

//==================================================================================================
//
// ServiceTypeDescriptionImpl implementation
//
//==================================================================================================

//__________________________________________________________________________________________________
// virtual
ServiceTypeDescriptionImpl::~ServiceTypeDescriptionImpl()
{
    delete _pMandatoryServices;
    delete _pOptionalServices;
    delete _pMandatoryInterfaces;
    delete _pOptionalInterfaces;
    delete _pProps;

    g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}

// XTypeDescription
//__________________________________________________________________________________________________
// virtual
TypeClass ServiceTypeDescriptionImpl::getTypeClass()
    throw(::com::sun::star::uno::RuntimeException)
{
    return TypeClass_SERVICE;
}
//__________________________________________________________________________________________________
// virtual
OUString ServiceTypeDescriptionImpl::getName()
    throw(::com::sun::star::uno::RuntimeException)
{
    return _aName;
}

// XServiceTypeDescription
//__________________________________________________________________________________________________
// virtual
Sequence< Reference< XServiceTypeDescription > > SAL_CALL
ServiceTypeDescriptionImpl::getMandatoryServices()
    throw ( RuntimeException )
{
    getReferences();
    return *_pMandatoryServices;
}

//__________________________________________________________________________________________________
// virtual
Sequence< Reference< XServiceTypeDescription > > SAL_CALL
ServiceTypeDescriptionImpl::getOptionalServices()
    throw ( RuntimeException )
{
    getReferences();
    return *_pOptionalServices;
}

//__________________________________________________________________________________________________
// virtual
Sequence< Reference< XInterfaceTypeDescription > > SAL_CALL
ServiceTypeDescriptionImpl::getMandatoryInterfaces()
    throw ( RuntimeException )
{
    getReferences();
    return *_pMandatoryInterfaces;
}

//__________________________________________________________________________________________________
// virtual
Sequence< Reference< XInterfaceTypeDescription > > SAL_CALL
ServiceTypeDescriptionImpl::getOptionalInterfaces()
    throw ( RuntimeException )
{
    getReferences();
    return *_pOptionalInterfaces;
}

//__________________________________________________________________________________________________
// virtual
Sequence< Reference< XPropertyTypeDescription > > SAL_CALL
ServiceTypeDescriptionImpl::getProperties()
    throw ( RuntimeException )
{
    if ( !_pProps )
    {
        RegistryTypeReaderLoader aLoader;
        RegistryTypeReader aReader(
            aLoader, (const sal_uInt8 *)_aBytes.getConstArray(),
            _aBytes.getLength(), sal_False );

        sal_uInt16 nFields = (sal_uInt16)aReader.getFieldCount();
        Sequence< Reference< XPropertyTypeDescription > > * pTempProps =
            new Sequence< Reference< XPropertyTypeDescription > >( nFields );
        Reference< XPropertyTypeDescription > * pProps = pTempProps->getArray();

        while ( nFields-- )
        {
            // name
            OUStringBuffer aName( _aName );
            aName.appendAscii( "." );
            aName.append( aReader.getFieldName( nFields ) );

            // type description
            Reference< XTypeDescription > xTD;
            try
            {
                _xTDMgr->getByHierarchicalName(
                    aReader.getFieldType( nFields ).replace( '/', '.' ) )
                        >>= xTD;
            }
            catch ( NoSuchElementException const & )
            {
            }
            OSL_ENSURE( xTD.is(), "### no type description for property!" );

            // flags
            RTFieldAccess nFlags = aReader.getFieldAccess( nFields );

            sal_Int16 nAttribs = 0;
            if ( nFlags & RT_ACCESS_READONLY )
                nAttribs |= beans::PropertyAttribute::READONLY;
            if ( nFlags & RT_ACCESS_OPTIONAL )
                nAttribs |= beans::PropertyAttribute::OPTIONAL;
            if ( nFlags & RT_ACCESS_MAYBEVOID )
                nAttribs |= beans::PropertyAttribute::MAYBEVOID;
            if ( nFlags & RT_ACCESS_BOUND )
                nAttribs |= beans::PropertyAttribute::BOUND;
            if ( nFlags & RT_ACCESS_CONSTRAINED )
                nAttribs |= beans::PropertyAttribute::CONSTRAINED;
            if ( nFlags & RT_ACCESS_TRANSIENT )
                nAttribs |= beans::PropertyAttribute::TRANSIENT;
            if ( nFlags & RT_ACCESS_MAYBEAMBIGUOUS )
                nAttribs |= beans::PropertyAttribute::MAYBEAMBIGUOUS;
            if ( nFlags & RT_ACCESS_MAYBEDEFAULT )
                nAttribs |= beans::PropertyAttribute::MAYBEDEFAULT;
            if ( nFlags & RT_ACCESS_REMOVEABLE )
                nAttribs |= beans::PropertyAttribute::REMOVEABLE;

            OSL_ENSURE( !(nFlags & RT_ACCESS_PROPERTY),
                        "### RT_ACCESS_PROPERTY is unexpected here!" );
            OSL_ENSURE( !(nFlags & RT_ACCESS_ATTRIBUTE),
                        "### RT_ACCESS_ATTRIBUTE is unexpected here!" );
            OSL_ENSURE( !(nFlags & RT_ACCESS_CONST),
                        "### RT_ACCESS_CONST is unexpected here!" );
            // always set, unless RT_ACCESS_READONLY is set.
            //OSL_ENSURE( !(nFlags & RT_ACCESS_READWRITE),
            //            "### RT_ACCESS_READWRITE is unexpected here" );
            OSL_ENSURE( !(nFlags & RT_ACCESS_DEFAULT),
                        "### RT_ACCESS_DEAFAULT is unexpected here" );

            pProps[ nFields ]
                = new PropertyTypeDescriptionImpl( aName.makeStringAndClear(),
                                                   xTD,
                                                   nAttribs );
        }

        ClearableMutexGuard aGuard( getMutex() );
        if ( _pProps )
        {
            aGuard.clear();
            delete pTempProps;
        }
        else
        {
            _pProps = pTempProps;
        }
    }

    return *_pProps;
}

//__________________________________________________________________________________________________
void ServiceTypeDescriptionImpl::getReferences()
    throw ( RuntimeException )
{
    if ( !_pMandatoryServices || !_pOptionalServices ||
         !_pMandatoryInterfaces || !_pOptionalInterfaces )
    {
        RegistryTypeReaderLoader aLoader;
        RegistryTypeReader aReader(
            aLoader, (const sal_uInt8 *)_aBytes.getConstArray(),
            _aBytes.getLength(), sal_False );

        sal_uInt32 nRefs = aReader.getReferenceCount();
        Sequence< Reference < XServiceTypeDescription > > * pTempMS
            = new Sequence< Reference < XServiceTypeDescription > >( nRefs );
        Sequence< Reference < XServiceTypeDescription > > * pTempOS
            = new Sequence< Reference < XServiceTypeDescription > >( nRefs );
        Sequence< Reference < XInterfaceTypeDescription > > * pTempMI
            = new Sequence< Reference < XInterfaceTypeDescription > >( nRefs );
        Sequence< Reference < XInterfaceTypeDescription > > * pTempOI
            = new Sequence< Reference < XInterfaceTypeDescription > >( nRefs );
        sal_uInt32 nMS = 0;
        sal_uInt32 nOS = 0;
        sal_uInt32 nMI = 0;
        sal_uInt32 nOI = 0;

        while ( nRefs-- )
        {
            RTReferenceType eType = aReader.getReferenceType( nRefs );
            switch ( eType )
            {
                case RT_REF_EXPORTS: // service
                {
                    uno::Any aTypeDesc;
                    try
                    {
                        aTypeDesc = _xTDMgr->getByHierarchicalName(
                            aReader.getReferenceName( nRefs )
                                .replace( '/', '.' ) );
                    }
                    catch ( NoSuchElementException const & )
                    {
                    }
                    OSL_ENSURE( aTypeDesc.hasValue(),
                                "### no type description!" );

                    RTFieldAccess nAccess = aReader.getReferenceAccess( nRefs );
                    if ( nAccess & RT_ACCESS_OPTIONAL )
                    {
                        // optional service
                        aTypeDesc >>= (*pTempOS)[ nOS ];
                        OSL_ENSURE( (*pTempOS)[ nOS ].is(),
                                    "### wrong type description type!" );
                        nOS++;
                    }
                    else
                    {
                        // mandatory service
                        aTypeDesc >>= (*pTempMS)[ nMS ];
                        OSL_ENSURE( (*pTempMS)[ nMS ].is(),
                                    "### wrong type description type!" );
                        nMS++;
                    }
                    break;
                }
                case RT_REF_SUPPORTS: // interface
                {
                    uno::Any aTypeDesc;
                    try
                    {
                        aTypeDesc = _xTDMgr->getByHierarchicalName(
                            aReader.getReferenceName( nRefs )
                                .replace( '/', '.' ) );
                    }
                    catch ( NoSuchElementException const & )
                    {
                    }
                    OSL_ENSURE( aTypeDesc.hasValue(),
                                "### no type description!" );

                    RTFieldAccess nAccess = aReader.getReferenceAccess( nRefs );
                    if ( nAccess & RT_ACCESS_OPTIONAL )
                    {
                        // optional interface
                        aTypeDesc >>= (*pTempOI)[ nOI ];
                        OSL_ENSURE( (*pTempOI)[ nOI ].is(),
                                    "### wrong type description type!" );
                        nOI++;
                    }
                    else
                    {
                        // mandatory interface
                        aTypeDesc >>= (*pTempMI)[ nMI ];
                        OSL_ENSURE( (*pTempMI)[ nMI ].is(),
                                    "### wrong type description type!" );
                        nMI++;
                    }
                    break;
                }
                case RT_REF_INVALID:
                case RT_REF_OBSERVES:
                case RT_REF_NEEDS:
                default:
                    OSL_ENSURE( sal_False,
                                "### unsupported reference type!" );
                    break;
            }
        }

        {
            ClearableMutexGuard aGuard( getMutex() );
            if ( _pMandatoryServices )
            {
                aGuard.clear();
                delete pTempMS;
            }
            else
            {
                pTempMS->realloc( nMS );
                _pMandatoryServices = pTempMS;
            }
        }

        {
            ClearableMutexGuard aGuard( getMutex() );
            if ( _pOptionalServices )
            {
                aGuard.clear();
                delete pTempOS;
            }
            else
            {
                pTempOS->realloc( nOS );
                _pOptionalServices = pTempOS;
            }
        }

        {
            ClearableMutexGuard aGuard( getMutex() );
            if ( _pMandatoryInterfaces )
            {
                aGuard.clear();
                delete pTempMI;
            }
            else
            {
                pTempMI->realloc( nMI );
                _pMandatoryInterfaces = pTempMI;
            }
        }

        {
            ClearableMutexGuard aGuard( getMutex() );
            if ( _pOptionalInterfaces )
            {
                aGuard.clear();
                delete pTempOI;
            }
            else
            {
                pTempOI->realloc( nOI );
                _pOptionalInterfaces = pTempOI;
            }
        }
    }
}

}

<|endoftext|>